2012-02-06 92 views
18

在阅读OpenGL规范时,我始终注意到它提到您可以在单个程序中包含多个相同类型的着色器(即,使用glAttachShader附加多个GL_VERTEX_SHADER)。特别是在OpenGL 4.2中,§2.11.3,程序对象:“多个相同类型的着色器对象可能会附加到单个程序对象...”。在单个OpenGL程序中附加多个相同类型的着色器?

OpenGL流水线程序和子程序可能适用于这里,但这是在存在之前定义的(实际上它回到2.1规范,第2.15.2节),所以我正在寻找一个GL4之前的例子。当我做了一些简单的测试时,发现包含多个void main()导致链接错误。有没有人知道实际例如哪里使用?

+0

我不确定这是否可行,但我猜你可以使用具有常用功能(但没有主要功能)的着色器,因此可以将这些着色器附加到porgram中,并可以从主着色器访问这些功能。这样你只需要编译这些函数一次。 – 2012-02-06 22:34:12

回答

26

您可以把常用的功能在不同的着色器。然后只编译一次,并链接多个程序。

这与你如何编译你的cpp文件只有一次,以获得静态或共享库类似。然后,将此库链接到多个可执行程序,从而节省编译时间。

比方说,你有复杂的照明功能:

vec3 ComputeLighting(vec3 position, vec3 eyeDir) 
{ 
    // ... 
    return vec3(...); 
} 

然后对于每个着色器要使用此功能,请这样的:

vec3 ComputeLighting(vec3 position, vec3 eyeDir); 

void main() 
{ 
    vec3 light = ComputeLighting(arg1, arg2); 
    gl_FragColor = ...; 
} 

然后编译单独共同着色和你的主着色器。但是只做一次通用着色器的编译。

+0

当然,这是完全合理的。谢谢! – 2012-02-06 22:40:16

7

我发现,包括多于一个无效的主要()引起的链接错误

对于每个着色器级必须只有一个条目的功能。

这是一个实用的例子(pre-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); 
}