Here's a short summary of things I have learned in the last months of OpenGL programming - sometimes the hard way (read: while destroying awful amounts of Club Mate and coffee).
Some of these are rather subtle pitfalls and do not get mentioned in tutorials or books too often.
- Textures must have one or more mipmaps attached, otherwise they are not considered complete by OpenGL and will not be rendered (or rendered completely black).
- if you want to re-display what you render into a framebuffer object, use a texture. If you just want to do some processing on the data or use it as the basis for something else - use a renderbuffer.
- be wary of if-conditionals in GLSL - due to the SIMD architecture of GPUs, even branches which you do not expect to be currently evaluated are actually evaluated in parallel - that might lead to crashes, for example due to unbound texture samplers.
- when specifying the texture format in
glTexImage*D
, use a bytesize-specifying format likeGL_RGBA8
instead ofGL_RGBA
- since OpenGL 3.3 some requirements have gotten stronger and not specifying the bytesize is actually not supported anymore and might lead to unexpected results. - when using textures in a fragment shader, set the uniform to the texture unit, not the texture ID - for some reason, this is wrong in many code snippets on the internet. One correct way is
// set the active texture unit 0
glActiveTexture(GL_TEXTURE0);
// bind the texture to texture unit 0
glBindTexture(GL_TEXTURE_2D, myTextureID);
// tell the fragment shader the texture sits in unit 0
glUniform1i(glGetUniformLocation(shaderId, "mySamplerUniform"), 0);
- don't upload geometry data with every frame - in the sense of running
glBufferData()
in every iteration of the rendering loop. This carries a massive performance penalty of about a factor 5 to 10(!). This generalizes to basically everything: Don't recreate or reupload stuff repeatedly if it's not changing.