在阅读OpenGL规范时,我注意到它提到你可以在一个程序中包含多个相同类型的着色器(即多个GL_VERTEX_SHADER附带glAttachShader)。特别是在OpenGL 4.2,§2.11.3,程序对象:“相同类型的多个着色器对象可以附加到单个程序对象......”。
OpenGL管道程序和子程序可能适用于此处,但这是在存在之前定义的(实际上它可以追溯到2.1规范,§2.15.2)所以我正在寻找这个想法的前GL4示例。当我做一些简单的测试时,我发现包含多个void main()
会导致链接错误。有人知道使用它的实用示例吗?
答案 0 :(得分:27)
您可以将常用功能放在单独的着色器中。然后只编译一次,并在多个程序中链接。
类似于编译cpp文件一次以获取静态或共享库的方式类似。然后将此库链接到多个可执行程序,从而节省编译时间。
假设你有复杂的照明功能:
vec3 ComputeLighting(vec3 position, vec3 eyeDir)
{
// ...
return vec3(...);
}
然后,对于要使用此功能的每个着色器,请执行以下操作:
vec3 ComputeLighting(vec3 position, vec3 eyeDir);
void main()
{
vec3 light = ComputeLighting(arg1, arg2);
gl_FragColor = ...;
}
然后分别编译常用着色器和主着色器。但是只编译一次普通着色器。
答案 1 :(得分:7)
我发现包含多个void main()导致链接错误
对于每个着色器阶段,必须只有主条目功能。
使用它的实际例子(GL4之前)?
您可以在着色器源中声明一个函数而不是定义它,并且在链接时您可以从另一个着色器源提供定义(非常类似于c / c ++链接)。
示例:
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);
}