In reading the OpenGL specs, I have noticed throughout that it mentions that you can include multiple shaders of the same kind in a single program (i.e. more than one GL_VERTEX_SHADER attached with glAttachShader). Specifically in OpenGL 4.2, §2.11.3, Program Objects: "Multiple shader objects of the same type may be attached to a single program object...".
OpenGL pipeline programs and subroutines might apply here, but this was defined before those existed (in fact it goes back to the 2.1 spec, §2.15.2) so I am looking for a pre-GL4 example of this idea. When I did some simple testing, I found that including more than one void main()
caused linking errors. Is anyone aware of a practical example where this is used?
You can put common functions in separate shader. Then compile it only once, and link in multiple programs.
It's similar how you compile your cpp files only once to get static or shared library. Then you link this library into multiple executable programs thus saving compilation time.
Let's say you have complex lighting function:
vec3 ComputeLighting(vec3 position, vec3 eyeDir)
{
// ...
return vec3(...);
}
Then for each of shader where you want to use this functionality do this:
vec3 ComputeLighting(vec3 position, vec3 eyeDir);
void main()
{
vec3 light = ComputeLighting(arg1, arg2);
gl_FragColor = ...;
}
Then you compile separately common shader and your main shader. But do the compilation of common shader only once.
I found that including more than one void main() caused linking errors
For each shader stage there must be only a main entry function.
a practical example where this is used (pre-GL4)?
You can declare a function in a shader source and not define it, and at linking time you can provide a definition from another shader source (very similar to c/c++ linking).
Example:
generate_txcoord.glsl:
#version 330
precision highp float;
const vec2 madd = vec2(0.5, 0.5);
vec2 generate_txcoord(vec2 v)
{
return v * madd + madd;
}
vertex.glsl:
#version 330
precision highp float;
in vec2 vxpos;
out vec2 out_txcoord;
vec2 generate_txcoord(vec2 vxpos); // << declared, but not defined
void main()
{
// generate 0..+1 domain txcoords and interpolate them
out_txcoord = generate_txcoord(vxpos);
// interpolate -1..+1 domain vxpos
gl_Position = vec4(vxpos, 0.0, 1.0);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With