<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xml:base="http://www.mimec.org" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
 <title>Blog</title>
 <link>http://www.mimec.org/blog</link>
 <description>The taxonomy view with a depth of 0.</description>
 <language>en</language>
<item>
 <title>Reflections from POP diaries</title>
 <link>http://www.mimec.org/node/339</link>
 <description>&lt;p&gt;Recently I came across Jordan Mechner&#039;s blog and the &lt;a href=&quot;http://jordanmechner.com/blog/2012/04/source/&quot;&gt;news&lt;/a&gt; that he just found the original source code of Prince of Persia on some old floppy disks after being lost for 22 years. That made me think about the time when I first played POP; I was no more than 10 years old and it was one of the first computer games I&#039;ve seen. It was about that time when I started thinking that computers are fun and that I want to learn programming and create games myself.&lt;/p&gt;
&lt;p&gt;I wonder if I also still have some floppy disks from Amiga 500 (and later Amiga 1200) hidden somewhere, with old pieces of code written by me. The oldest program that I wrote which survived to this day is called Polyglot. I wrote it in 1997 (being 15 years old) under the nick name &quot;CompLex&quot;. It is still available in the &lt;a href=&quot;http://aminet.net/package/misc/edu/polyglot&quot;&gt;Aminet archives&lt;/a&gt;, although only in binary form. I no longer have the source code. Maybe it still exists on the hard drive which I damaged many years ago by screwing it with too long screws which caused a short-circuit :). The oldest source code which I still have is Grape3D, written almost 12 years ago. It&#039;s almost completely unreadable, with lots of bitwise operations, pointer math, abbreviated variable names and literally zero comments, but it remains a really ingenious work of art that would be hard for me to match today.&lt;/p&gt;
&lt;p&gt;I also read Jordan&#039;s &lt;a href=&quot;http://jordanmechner.com/blog/2011/10/ebook/&quot;&gt;diaries&lt;/a&gt; from making POP in late 80s and early 90s. It&#039;s really interesting and also quite inspiring. It also reminded me that I kept a diary between 1999 and 2007. It was mostly dedicated to various frustrations caused by my social life (or the lack of it), girls (or the inability to meet any), and general uncertainty of what I should do and what awaits me in the future. There are few mentions about the programs that I were writing at that time, because I deliberately avoided that topic. Anyway, from the perspective of a decade, life doesn&#039;t seem as bad as it used to, but it&#039;s definitely not getting any easier. It&#039;s just running much faster.&lt;/p&gt;
&lt;p&gt;Jordan wrote a lot about his dilemma whether to write computer games or movie scripts. It&#039;s quite similar to the problem I currently have, trying to reconcile writing open source programs and the novel that I&#039;m working on. I guess that&#039;s just the problem of people that are too creative :). There are a few major differences, though: Jordan had royalties from Karateka, and I need a full time job for living and for paying my loans; he was 21 when he started and I already turned 30 and have a wife and a kid to look after. So I&#039;m not in a great position to disappear for half a year and write a bestseller book, or to invest in starting my own software company.&lt;/p&gt;
&lt;p&gt;I really can&#039;t complain about my job, but I can&#039;t imagine working as an &quot;outsourced&quot; developer for the rest of my life, and being paid by the hour and not by the actual value of what I create. This is actually kind of frustrating and counter-productive, because the better and more efficient I work, the less I get paid for it. There are some ideas on the horizon how to change, or at least improve this situation. Perhaps I will finally be able to make some profit from the countless hours I spent on WebIssues. But so far, the only way I can do something to make me feel more accomplished is to pull all-nighters. I&#039;m even doing it now writing this post. That&#039;s also not something I want to do for the rest of my life. Living from WebIssues royalties, travelling and writing books sounds much better.&lt;/p&gt;
&lt;p&gt;Another lesson from Jordan&#039;s diaries is that even if you do a great job, there are still many things that may go wrong. Poor marketing decisions almost sank Prince of Persia, even though it was getting excellent reviews. I fear the same may happen to the commercial version of WebIssues. I know the value of this project; it can successfully compete with other applications, and the competition in this sector of the market, both open source and commercial, is very strong. But being able to make a profit from it is a completely different story. Of course, the only way to find out is to take the chance, and I will do it, but until I see some serious action going on, I will remain moderately enthusiastic about it.&lt;/p&gt;
&lt;p&gt;Oh, and by the way, a new version of WebIssues is coming out probably next week. I&#039;m just waiting for one Mac related bug to be fixed. And in the meantime I&#039;m making some last minute improvements.&lt;/p&gt;
</description>
 <comments>http://www.mimec.org/node/339#comments</comments>
 <pubDate>Wed, 09 May 2012 01:25:12 +0200</pubDate>
 <dc:creator>mimec</dc:creator>
 <guid isPermaLink="false">339 at http://www.mimec.org</guid>
</item>
<item>
 <title>Tooltips for truncated items in a QTreeView</title>
 <link>http://www.mimec.org/node/337</link>
 <description>&lt;p&gt;It is quite common in various applications to display tooltips for truncated items in list views and tree views. Such functionality was present in Qt 3, but in Qt 4 the application, or rather the model, is fully responsible for providing the tooltip using the &lt;code&gt;Qt::ToolTipRole&lt;/code&gt; and such automatic behavior no longer exist. You can obviously return the same text for both &lt;code&gt;Qt::DisplayRole&lt;/code&gt; and &lt;code&gt;Qt::ToolTipRole&lt;/code&gt;, but then tooltips are shown for all items, whether they are truncated or not. It doesn&#039;t look very well.&lt;/p&gt;
&lt;p&gt;It&#039;s surprisingly hard to find a solution. The best I could find was &lt;a href=&quot;http://lists.trolltech.com/qt-interest/2006-10/thread00662-0.html&quot;&gt;this thread&lt;/a&gt; on the qt-interest mailing list. It suggests subclassing the view and overriding the tooltip event. I felt that there must be a better way, so I looked into the source code of &lt;code&gt;QAbstractItemView&lt;/code&gt;. It turned out that since Qt 4.3, handling tooltips (and various other help events) is delegated to... the item delegate.&lt;/p&gt;
&lt;p&gt;The definition of a custom item delegate may look like this:&lt;/p&gt;
&lt;p&gt;&lt;div class=&quot;codeblock&quot;&gt;&lt;code&gt;class AutoToolTipDelegate : public QStyledItemDelegate&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Q_OBJECT&lt;br /&gt;public:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; AutoToolTipDelegate( QObject* parent );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ~AutoToolTipDelegate();&lt;br /&gt;&lt;br /&gt;public slots:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; bool helpEvent( QHelpEvent* e, QAbstractItemView* view, const QStyleOptionViewItem&amp;amp; option,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; const QModelIndex&amp;amp; index );&lt;br /&gt;};&lt;/code&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;Notice that the &lt;code&gt;helpEvent&lt;/code&gt; method is a slot. It should be a virtual method; however adding a new virtual method to an existing class would break binary compatibility with earlier versions of the Qt library, so instead this method is invoked dynamically using the slots mechanism.&lt;/p&gt;
&lt;p&gt;In order to check if the given item is truncated or not, we simply have to compare its visual rectangle (which can be retrieved from the view) with the size hint (provided by the item delegate itself). The full code of the &lt;code&gt;helpEvent&lt;/code&gt; method looks like this:&lt;/p&gt;
&lt;p&gt;&lt;div class=&quot;codeblock&quot;&gt;&lt;code&gt;bool AutoToolTipDelegate::helpEvent( QHelpEvent* e, QAbstractItemView* view,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; const QStyleOptionViewItem&amp;amp; option, const QModelIndex&amp;amp; index )&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ( !e || !view )&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ( e-&amp;gt;type() == QEvent::ToolTip ) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; QRect rect = view-&amp;gt;visualRect( index );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; QSize size = sizeHint( option, index );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ( rect.width() &amp;lt; size.width() ) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; QVariant tooltip = index.data( Qt::DisplayRole );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ( tooltip.canConvert&amp;lt;QString&amp;gt;() ) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; QToolTip::showText( e-&amp;gt;globalPos(), QString( &amp;quot;&amp;lt;div&amp;gt;%1&amp;lt;/div&amp;gt;&amp;quot; )&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .arg( Qt::escape( tooltip.toString() ) ), view );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ( !QStyledItemDelegate::helpEvent( e, view, option, index ) )&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; QToolTip::hideText();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return QStyledItemDelegate::helpEvent( e, view, option, index );&lt;br /&gt;}&lt;/code&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;If the item is truncated, the display text is retrieved and displayed as a tooltip. Otherwise the default handler is called, so a custom tooltip may be displayed. If you want, you may reverse this behavior and only display the automatic tooltip if there is no custom one, or remove the call to the default handler if there are no custom tooltips.&lt;/p&gt;
&lt;p&gt;Also notice that the text is wrapped into a &amp;lt;div&amp;gt; tag. That&#039;s in case the text is really long. When a HTML text is passed to the tooltip, it will be automatically wrapped into multiple lines if necessary. Otherwise the entire text would be displayed as a single line which may not fit on the screen. The &lt;code&gt;Qt::escape&lt;/code&gt; method replaces any special characters with HTML entities to ensure that the text is displayed correctly.&lt;/p&gt;
&lt;p&gt;All we have to do to enable automatic tooltips for a view is to assign our delegate to it:&lt;/p&gt;
&lt;p&gt;&lt;div class=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; view-&amp;gt;setItemDelegate( new AutoToolTipDelegate( view ) );&lt;/code&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;Note that it will also work for other kinds of views, no only &lt;code&gt;QTreeView&lt;/code&gt;.&lt;/p&gt;
</description>
 <comments>http://www.mimec.org/node/337#comments</comments>
 <pubDate>Mon, 23 Apr 2012 20:43:22 +0200</pubDate>
 <dc:creator>mimec</dc:creator>
 <guid isPermaLink="false">337 at http://www.mimec.org</guid>
</item>
<item>
 <title>Loading OpenGL functions</title>
 <link>http://www.mimec.org/node/336</link>
 <description>&lt;p&gt;I already wrote about using OpenGL 3.3 with Qt applications, using new style shaders and helper classes for handling shader programs and buffers. But there is one more important thing to do before we can start writing OpenGL 3.3 applications with Qt. The problem is that usually functions and constants from OpenGL 3.3 won&#039;t be available even if we have the appropriate libraries and drivers. That&#039;s simply how OpenGL works and we have to work around this limitation.&lt;/p&gt;
&lt;p&gt;The qgl.h header, which is used by all other headers from the QtOpenGL module, includes &amp;lt;GL/gl.h&amp;gt; (or its equivalent, depending on the platform). However, on Windows this standard header is always compatible with version 1.1 of OpenGL (even if you have the latest Platform SDK), and on systems using recent versions of MESA (including most Linuxes) it&#039;s compatible with version 1.3. To have all the new symbols from version 3.3, you need to include &amp;lt;GL/glext.h&amp;gt;, but it also doesn&#039;t help much. First, this header is not available on Windows. Second, it only defines typedefs for function pointers that you have to retrieve by yourself using a platform-specific function, because they are not directly exported by the OpenGL library like in case of most other APIs. And even if they were, they may not be available on some platforms, depending on the actual version and available extensions, and you may still want your code to work without some of them.&lt;/p&gt;
&lt;p&gt;There are some existing libraries that attempt to solve this problem by automatically loading those functions behind the scenes. The most popular ones are &lt;a href=&quot;http://glew.sourceforge.net/&quot;&gt;GLEW&lt;/a&gt; and GL Load (which is a part of the &lt;a href=&quot;http://glsdk.sourceforge.net/docs/html/index.html&quot;&gt;Unofficial GL SDK&lt;/a&gt;). They are cool but both are relatively huge (well over 2 MB of header files and source code) for a simple task of loading a few dozens of functions. They include a bunch of extensions which are not part of the OpenGL 3.3 core profile. They are also meant to completely replace &amp;lt;GL/gl.h&amp;gt;, and although they work with Qt, it&#039;s not an elegant solution.&lt;/p&gt;
&lt;p&gt;Qt itself also has a rather funny approach to this problem. All classes that require 2.0+ functionality (shaders, buffers, etc.) use an internal header, &lt;code&gt;qglextensions_p.h&lt;/code&gt;. It works in a somewhat similar way to those libraries. It defines the function pointer types and constants and then defines macros which replace canonical function names with appropriate entries in an internal structure which is stored in the &lt;code&gt;QGLContext&lt;/code&gt;. Obviously we cannot rely on it because it&#039;s internal, and besides it only defines a small set of functions and constants which are directly used by Qt.&lt;/p&gt;
&lt;p&gt;There is also a public class &lt;code&gt;QGLFunctions&lt;/code&gt; which is part of the API, though it&#039;s not internally used by Qt. It takes a completely different approach and instead of using macros, it&#039;s a class with methods of the same name as canonical OpenGL functions. The recommended way to use it is to inherit this class in each class that needs to use those functions. It seems like a bit WTF to me. Even worse, it only covers OpenGL/ES 2.0 which is fine for embedded applications, but not enough for a desktop application targeting OpenGL 3.3.&lt;/p&gt;
&lt;p&gt;As you can probably guess I came up with a custom solution. The idea is that it only needs to add symbols not already defined in &amp;lt;GL/gl.h&amp;gt;, assuming that it&#039;s compatible with at least OpenGL 1.1. It also only covers the OpenGL 3.3 core profile without any additional extensions or features removed from the core profile (though those defined by &amp;lt;GL/gl.h&amp;gt; will still be available). It consists of a header file which is basically a slightly stripped version of &lt;code&gt;gl3.h&lt;/code&gt; from the official &lt;a href=&quot;http://www.opengl.org/registry/&quot;&gt;OpenGL Registry&lt;/a&gt;. I basically removed everything pre-1.2 and post-3.3 and some other unnecessary stuff. Another header defines a structure holding all function pointers and all the necessary macro definitions, and a single source file contains code that initializes this structure using a &lt;code&gt;QGLContext&lt;/code&gt;, which takes care of retrieving function pointers in a cross-platform way.&lt;/p&gt;
&lt;p&gt;The size of all three files is a mere 120 kilobytes. Some day I may publish them as a separate mini-libary, but for now you can find them in the &lt;a href=&quot;http://descend.svn.sourceforge.net/viewvc/descend/trunk/src/scene/&quot;&gt;SVN repository&lt;/a&gt; of Descend.&lt;/p&gt;
</description>
 <comments>http://www.mimec.org/node/336#comments</comments>
 <pubDate>Mon, 16 Apr 2012 23:09:04 +0200</pubDate>
 <dc:creator>mimec</dc:creator>
 <guid isPermaLink="false">336 at http://www.mimec.org</guid>
</item>
<item>
 <title>QGLShaderProgram and QGLBuffer</title>
 <link>http://www.mimec.org/node/332</link>
 <description>&lt;p&gt;In the &lt;a href=&quot;/node/331&quot;&gt;previous article&lt;/a&gt; I wrote that using modern OpenGL (i.e. version 3.0 and above) is possible, although the core profile cannot be used yet. I also mentioned &lt;a href=&quot;http://qt-project.org/wiki/How_to_use_OpenGL_Core_Profile_with_Qt&quot;&gt;this article&lt;/a&gt; which briefly describes how to use the core profile, although in fact this example will also work in the default compatibility mode. In this mode we can use both the fixed pipeline and shaders, but I will focus on the &quot;modern&quot; approach.&lt;/p&gt;
&lt;p&gt;Qt has a handy class called &lt;code&gt;QGLShaderProgram&lt;/code&gt; which wraps the OpenGL API related to shaders. A big advantage of this class is that it supports all classes related to 3D graphics provided by Qt, such as &lt;code&gt;QVector3D&lt;/code&gt; and &lt;code&gt;QMatrix4x4&lt;/code&gt;, as well as basic types like &lt;code&gt;QColor&lt;/code&gt;. This way we don&#039;t have to worry about converting those types to OpenGL types. Internally this class is little more than a &lt;code&gt;GLuint&lt;/code&gt; storing the handle of the shader program and most its methods are simple wrappers around functions like &lt;code&gt;glUniform3fv&lt;/code&gt; so it&#039;s very lightweight.&lt;/p&gt;
&lt;p&gt;Note, however, that shaders work in quite a different way depending on the version of the GLSL specification. By default version 1.20 is assumed, so your shaders can access all information known from the fixed pipeline - vertex position, normal, texture coordinates, transformation matrices, lighting parameters, etc. Things change dramatically when you put the following declaration at the beginning of the shader:&lt;/p&gt;
&lt;p&gt;&lt;div class=&quot;codeblock&quot;&gt;&lt;code&gt;#version 330&lt;/code&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;Any attempt to access these built-in uniforms and attributes will result in an error. It means that you have to pass all information using explicitly declared uniforms and attributes. For example, to define the world-to-camera transformation matrix, you could use the following code:&lt;/p&gt;
&lt;p&gt;&lt;div class=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; QMatrix4x4 view;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; view.translate( 0.0, 0.0, -CameraDistance );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; view.rotate( m_angle, 1.0, 0.0, 0.0 );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; view.rotate( m_rotation, 0.0, 0.0, 1.0 );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_program.setUniformValue( &amp;quot;ViewMatrix&amp;quot;, view );&lt;/code&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;This is not only much more elegant than a series of calls to &lt;code&gt;glMatrixMode&lt;/code&gt;, &lt;code&gt;glIdentity&lt;/code&gt;, &lt;code&gt;glRotate&lt;/code&gt; etc., but also faster and more flexible. The vector and matrix classes provided by Qt are really handy; the authors of this class even thought about the &lt;code&gt;normalMatrix&lt;/code&gt; method that calculates the transposed inverse (or was it inversed transpose?) for transforming normal vectors.&lt;/p&gt;
&lt;p&gt;Similarly, uniforms can be used to pass lighting parameters, materials, blending information and many more things which are not possible to achieve using the fixed pipeline. When it comes to attributes, the &lt;code&gt;QGLShaderProgram&lt;/code&gt; offers a bunch of functions for passing single values to attributes (which are not very useful in most cases) and for passing arrays of various types. However this is not recommended, because OpenGL knows nothing about the contents of these arrays and it cannot assume that they don&#039;t change between executions of the shader or between successive frames.&lt;/p&gt;
&lt;p&gt;A much better approach is to use the &lt;code&gt;setAttributeBuffer&lt;/code&gt; method in connection with the &lt;code&gt;QGLBuffer&lt;/code&gt; class. Internally this method is a wrapper for &lt;code&gt;glVertexAttribPointer&lt;/code&gt; just like the attribute array methods, but it makes the code much more readable as it explicitly states that vertex buffers are used. In addition there&#039;s no need to cast the offset to a pointer because Qt will do that for us.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;QGLBuffer&lt;/code&gt; class is also a very thin wrapper around a &lt;code&gt;GLuint&lt;/code&gt; representing the vertex buffer object (or index buffer or pixel buffer object). Unlike &lt;code&gt;QGLShaderProgram&lt;/code&gt; it&#039;s a value type (it doesn&#039;t make sense to copy a program anyway), so we can share buffers without having to worry about tracking and releasing them when they are no longer needed.&lt;/p&gt;
&lt;p&gt;In order to use the &lt;code&gt;QGLBuffer&lt;/code&gt;, we need to create it and fill it with data; then we can bind it with the attributes of the shader program. By using appropriate offset and stride, we can easily bind multiple attributes to a single buffer; usually all attributes of a single vertex would be stored together, followed by the remaining vertices. Don&#039;t forget about calling &lt;code&gt;enableAttributeArray&lt;/code&gt; for each attribute. We can also use another instance of &lt;code&gt;QGLBuffer&lt;/code&gt; to store the indexes.&lt;/p&gt;
&lt;p&gt;When everything is set up like this, the rendering is a matter of binding the program and both buffers to the context and calling &lt;code&gt;glDrawElements&lt;/code&gt;. In more complex scenarios we can use multiple vertex array objects to store the bindings between vertex buffers and attributes. But since we&#039;re not using the core profile, OpenGL will create an implicit vertex array object for us.&lt;/p&gt;
&lt;p&gt;We can also use uniform buffer objects to simplify passing lots of uniforms to multiple programs. Although Qt doesn&#039;t support them at the moment, there is a simple hack which allows us to abuse &lt;code&gt;QGLBuffer&lt;/code&gt;. If you look at the declaration of this class you will notice that the values of the enumeration defining the type of a buffer are the same as the corresponding target constants in OpenGL. So we could simply pass &lt;code&gt;GL_UNIFORM_BUFFER&lt;/code&gt; as the type of the buffer - I haven&#039;t tested it yet, but it should work.&lt;/p&gt;
</description>
 <comments>http://www.mimec.org/node/332#comments</comments>
 <pubDate>Mon, 09 Apr 2012 23:44:48 +0200</pubDate>
 <dc:creator>mimec</dc:creator>
 <guid isPermaLink="false">332 at http://www.mimec.org</guid>
</item>
<item>
 <title>Qt and OpenGL 3.3</title>
 <link>http://www.mimec.org/node/331</link>
 <description>&lt;p&gt;Some time ago I stumbled upon a great e-book on OpenGL programming: &lt;a href=&quot;http://www.arcsynthesis.org/gltut/&quot;&gt;Learning Modern 3D Graphics Programming&lt;/a&gt;. The best thing about it is that it teaches the modern approach to graphics programming, based on OpenGL 3.3 with programmable shaders, and not the &quot;fixed pipeline&quot; known from OpenGL 1.x which is now considered obsolete. I already know a lot about vectors, matrices and all the basics, and I have some general idea about how shaders work, but this book describes everything in a very organized fashion and it allows me to broaden my knowledge.&lt;/p&gt;
&lt;p&gt;When I first learned OpenGL over 10 years ago, it was all about a bunch of glBegin/glVertex/glEnd calls and that&#039;s how Grape3D, my first 3D graphics program, actually worked. Fraqtive, which also has a 3D mode, used the incredibly advanced technique of glVertexPointer and glDrawElements, which dates back to OpenGL 1.1.&lt;/p&gt;
&lt;p&gt;A lot has changed since then. OpenGL 2.0 introduced shaders, but they were still closely tied to the fixed pipeline state objects, such as materials and lights. The idea was that shaders could be used when supported to improve graphical effects, for example by using per-pixel Phong lighting instead of Gouraud lighting provided by the fixed pipeline. Since many graphics cards didn&#039;t support shaders at that time, OpenGL would gracefully fall back to the fixed pipeline functionality, and everything would still be rendered correctly.&lt;/p&gt;
&lt;p&gt;Nowadays all decent graphics cards support shaders, so in OpenGL 3.x the entire fixed pipeline became obsolete and using shaders is the only &quot;right&quot; way to go. There is even a special mode called the &quot;Core profile&quot; which enforces this by disabling all the old style API. This means that without a proper graphics chipset the program will simply no longer work. I don&#039;t consider this a big issue. All modern games require a chipset compatible with DirectX 10, so why should a program dedicated to rendering 3D graphics be any different? Functionally OpenGL 3.3 is more or less the equivalent of DirectX 10, so it seems like a reasonable choice.&lt;/p&gt;
&lt;p&gt;I was happy to learn that &lt;a href=&quot;http://qt-project.org/wiki/How_to_use_OpenGL_Core_Profile_with_Qt&quot;&gt;Qt supports the Core profile&lt;/a&gt;, only to discover that it&#039;s not actually working because of an &lt;a href=&quot;https://bugreports.qt-project.org/browse/QTBUG-11052&quot;&gt;unresolved bug&lt;/a&gt;. Besides, the article mentions that &quot;some drivers may incur a small performance penalty when using the Core profile&quot;. This sounds like a major WTF to me, because the whole idea of the Core profile was to simplify and optimize things, right? Anyway I decided to use OpenGL 3.3 without enforcing the Core profile for now, but to try to implement everything as if I was using that profile.&lt;/p&gt;
&lt;p&gt;Another problem that I faced is that my laptop is three years old, and even though its graphics chipset is pretty good for that time (NVIDIA Quadro NVS 140M), I discovered that the OpenGL version was only 2.1. I couldn&#039;t find any newer drivers from Lenovo, so I installed the latest generic drivers from NVIDIA and now I have OpenGL 3.3. Yay! So I modified my Descend prototype to use shaders 3.30 and &lt;code&gt;QGLBuffer&lt;/code&gt; objects (which are wrappers for Vertex Buffer Objects and Index Buffer Objects), but I will write more about it in the next post.&lt;/p&gt;
</description>
 <comments>http://www.mimec.org/node/331#comments</comments>
 <pubDate>Sat, 31 Mar 2012 00:28:43 +0200</pubDate>
 <dc:creator>mimec</dc:creator>
 <guid isPermaLink="false">331 at http://www.mimec.org</guid>
</item>
</channel>
</rss>

