I’ve been moving LxEngine from using OpenGL 3.2 Compatibility Profile to the Core Profile. That means saying goodbye to various bits of functionality I had been using in the interest of cleaner, more concise (and forward-moving) OpenGL API usage.
Here’s a list of the minor items that had to be corrected:
Short answer: split your quads into triangles and duplicate your data as needed
This was the first issue as LxEngine currently uses quad lists rather than triangle lists for much of its geometry.
The fix is straightforward: split each quad into two triangles. Now where to do this? This is done in the rasterizer right before the glBindBuffer() calls. Why? Because, apparently (I have no verification of this), modern drivers actually split quads into triangles before uploading to the card – so effectively doing the translation myself before the glBindBuffer() call should be more or less equivalent in terms of speed. This allows any data higher up in the application to retain quad format data for a bit less memory usage. If the higher level data wants to avoid the translation, it can use the triangle-based APIs. Thus quads in LxEngine have become a compression technique…
In terms of memory usage, for an index-buffer based quad list, the index buffer size increases by 3/2 (i.e. 6 indices describe the quad instead of 4). Any associated face data is obviously double in size. However, vertex data itself does not increase at all since it is an index-based approach. For an unindexed primitive, the vertex array sizes all increase by 3/2 or 150% as every 4 vertices is again now 6. At this point, LxEngine is assuming a soup of unconnected quads as input so there’s no attempt made to stripify the triangles to recover some of that memory loss.
Short answer: store the matrices in a software stack, set them as GLSL uniforms before the draw call, use GLM to do the dirty-work of the math for you
gl_ModelViewMatrix, gl_ProjectionMatrix, and gl_NormalMatrix are gone. How is this fixed?
Add uniform mat4 and mat3 variables to cover for them. Presumably the model-view and projection matrices are directly available within your code, so simply set the uniforms to those values instead of making a glLoadMatrix call.
Now, if you’re also using functions like glRotate() and/or glPushMatrix() then simply move the model-view and projection matrices to a software stack within your application. Right before making any draw calls, set the uniform variable to the current top of the stack for those values.
If you want to avoid writing all the math to do a rotation like glRotate(), then I suggest using GLM.
Oh, and gl_NormalMatrix is the upper 3×3 of the model-view matrix, so simply compute that using GLM via some code like this:
glm::mat3 normalMatrix = glm::mat3(glm::inverseTranspose(viewMatrix));
GLint idx = glGetUniformLocation(progId, "myNormalMatrix");
glUniformMatrix3fv(idx, 1, GL_FALSE, glm::value_ptr(normalMatrix));
Not much to say about this one: check the color.a in the fragment shader and use the discard keyword to fail the alpha test. Use uniforms if you want a non-hard coded test. (LxEngine only uses it for masking, therefore a fixed test works fine.)
Replace GL_CLAMP with GL_CLAMP_TO_EDGE, most likely. See http://www.khronos.org/opengles/documentation/opengles1_0/html/glTexParameter.html
The GL_GEOMETRY_INPUT_TYPE and GL_GEOMETRY_OUTPUT_TYPE are now set in the geometry shader itself using the GLSL keyword “layout”. See http://www.lighthouse3d.com/tutorials/glsl-core-tutorial/geometry-shader/.