GLSL : common mistakes
The following article discusses common mistakes made in the OpenGL Shading Language, GLSL.
Enable Or Not To Enable
With fixed pipeline, you needed to call
glEnable(GL_TEXTURE_2D) to enable 2D texturing. You needed to call
glEnable(GL_LIGHTING). Since shaders override these functionalities, you don't need to glEnable/glDisable. If you don't want texturing, you either need to write another shader that doesn't do texturing or you can attach a all white or all black texture, depending on your needs. You can also write one shader that does lighting and one that doesn't.
Things that are not overriden by shaders, like the alpha test, depth test, stencil test... calling glEnable/glDisable will have an effect.
Binding A Texture
When you compile and link your GLSL shader, the next step is to get uniform locations for your samplers (I'm talking about texture samplers) and setup the samplers. Some people do this:
You can't send a GL texture ID as your sampler. A sampler should be from 0 to the max number of texture image units.
To bind a texture, always use
Once you compile and link your shader, make sure that you setup all the samplers by calling
(assuming of course your samplers are named Texture0, Texture1 and Texture2
location=glGetUniformLocation(shaderProgram, "Texture0"); glUniform1i(location, 0); location=glGetUniformLocation(shaderProgram, "Texture1"); glUniform1i(location, 1); location=glGetUniformLocation(shaderProgram, "Texture2"); glUniform1i(location, 2);
nVidia drivers are more relaxed. You could do
float myvalue = 0;
but this won't compile on other platforms. Use 0.0 instead.
0.0f. GLSL is not C or C++.
float texel = texture2D(tex, texcoord);
The above is wrong since
texture2D returns a
Do this instead
float texel = float(texture2D(tex, texcoord));
float texel = texture2D(tex, texcoord).r;
float texel = texture2D(tex, texcoord).x;
Functions should look like this
vec4 myfunction(inout float value1, in vec3 value2, in vec4 value3)
vec4 myfunction(float value1, vec3 value2, vec4 value3)
In the vertex shader
gl_TexCoord = gl_MultiTexCoord0;
and in the fragment shader
vec4 texel = texture2D(tex, gl_TexCoord.xy);
zw isn't being used in the fs.
gl_TexCoord.x = gl_MultiTexCoord0.x; gl_TexCoord.y = gl_MultiTexCoord0.y;
gl_TexCoord.xy = gl_MultiTexCoord0.xy;
The MAD instruction
MAD is short for multiply, then add. It is a special floating point circuit. Very fast. Costs 1 GPU cycle.
vec4 result1 = (value / 2.0) + 1.0; vec4 result2 = (value / 2.0) - 1.0; vec4 result3 = (value / -2.0) + 1.0;
The above doesn't quite easily turn into a MAD. It might be compiled to a reciprocal, then add. That might cost 2 or more cycles. Below is GLSL code that converts to a single MAD instruction (for each line of code of course)
vec4 result1 = (value * 0.5) + 1.0; vec4 result2 = (value * 0.5) - 1.0; vec4 result3 = (value * -0.5) + 1.0;