Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Attaching multiple shaders of the same type in a single OpenGL program?

Tags:

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?

like image 692
Mike E Avatar asked Feb 06 '12 22:02

Mike E


2 Answers

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.

like image 89
Mārtiņš Možeiko Avatar answered Sep 30 '22 15:09

Mārtiņš Možeiko


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);
}
like image 41
Gigi Avatar answered Sep 30 '22 15:09

Gigi