2015-11-09 62 views
0

有没有办法创建多个着色器(包括顶点,片段,偶数几何和曲面细分),这些着色器可以在他们所做的事情中进行复合?OpenGL中的多个着色器

例如:我见过了一批的用途和关键字在OpenGL的更新版本,并使用这些来说明我的问题。

有没有给着色器的方式(并不重要,但是我们要说片段着色器),如

in inVar; 
out outVar; 
void man(){ 
    var varOne = inVar; 
    var varTwo = varOne; 
    var varThr = varTwo; 
    outVar = varThr; 
} 

把它变成片段着色器

in inVar; 
out varOne; 
void main(){ 
    varOne = inVar; 
} 

其次是片段着色器

in varOne; 
out varTwo; 
void main(){ 
    varTwo = varOne; 
} 

其次片段着色器

in varTwo(
out varThr; 
void main(){ 
    varThr = varTwo 
} 

最后由片段着色器

in varThr; 
out outVar; 
void main(){ 
    outVar = varThr; 
} 

其次是在正确的“概念”来形容这种行为或我应该寻找另一个关键字?

+0

一旦创建,glUsePogram(pgmID)允许您在程序之间切换 –

+0

@ j-p:你是什么意思?我没有试图切换程序。我试图结合来自同一类型的多个着色器的效果。 – WoodMath

+0

有GL'子程序',允许组合... https://www.opengl.org/wiki/Shader_Subroutine –

回答

3

在OpenGL中,您可以将多个相同类型的着色器附加到程序对象。在OpenGL ES中,这不受支持。

这是从OpenGL的4.5规范,部分“7.3程序对象”,88页(强调):

相同类型的多个着色器对象可以是连接到单个程序对象,并且一个着色器对象可以附加到多个程序对象。

符合OpenGL ES 3.2规范,部分“7.3程序对象”,第72页(强调)相比:

同一类型的多个着色器对象可以不连接到单个程序对象。但是,单个着色器对象可能会附加到多个程序对象。

但是,即使在OpenGL中,使用多个相同类型的着色器也不能用它们的方式在您的问题中勾勒出它。只有其中一个着色器可以有main()。其他着色器通常只包含函数。因此,将多个相同类型的着色器链接到管道中的想法不适用于此形式。

有时使用的方式是有一个(或多个)着色器包含一个通用函数集合,只需要编译一次,然后就可以用于多个着色器程序。这相当于一般编程中的函数库。你可以用非官方的术语来称呼这个“库着色器”。

然后每个着色器程序都有一个包含main()的每个类型的着色器,并且该着色器包含该程序的特定逻辑和控制流,同时从“库着色器”调用泛型函数。

按照您的问题提纲,您可以在每个着色器中定义一个函数来实现类似的功能。例如,第一个片段着色器可以包含这些代码:

void shaderOne(in vec4 varIn, out vec4 varOut) { 
    varOut = varIn; 
} 

二着色器:

void shaderTwo(in vec4 varIn, out vec4 varOut) { 
    varOut = varIn; 
} 

第三着色器:

void shaderThr(in vec4 varIn, out vec4 varOut) { 
    varOut = varIn; 
} 

然后,你需要一个着色器与main(),在那里你可以链接其他着色器:

in vec4 varOne; 
out vec4 outVar; 

void main() { 
    vec4 varTwo, varThr; 
    shaderOne(varOne, varTwo); 
    shaderTwo(varTwo, varThr); 
    shaderThr(varThr, outVar); 
} 
+0

我更关心的是从客户端启用/禁用个别着色器(选择哪一个应用)。按照你所描述的做法,将需要添加一堆** uniform **变量,并在** if/then **语句前添加每个着色器调用。而且我认为我不能说**禁用** shaderTwo **调用,而不影响** shaderThr **。简而言之,我想知道是否可以修改您给出的代码示例来禁用shaderCalls,从而改变效果,但在调用后续着色器调用时不会产生错误 – WoodMath

+1

我不知道OpenGL支持同一类型的多个着色器单个程序对象。你能指出这个功能吗?据我所知最多OpenGL支持传递多个字符串,但这些字符串只是连接在一起。没有理由不要自己连接它们,这是WebGL要求的要求 – gman

+0

@gman我在帖子的顶部添加了规格引号。我已经检查过2.1规格,它一直是这样。我已经看到这在非常成功的游戏中使用。 –

1

生成着色器。这几乎是所有3D引擎和游戏引擎所做的。

换句话说,他们使用代码处理文本并在运行时或构建时生成源代码。

有时他们使用GLSL的预处理器。实施例

#ifdef USE_TEXTURE 
    uniform sampler2D u_tex; 
    varying vec2 v_texcoord; 
#else 
    uniform vec4 u_color; 
#endif 

void main() { 
    #ifdef USE_TEXTURE 
    gl_FragColor = texture2D(u_tex, v_texcoord); 
    #else 
    gl_FragColor = u_color; 
    #endif 
} 

然后在运行时添加前置串来定义USE_TEXTURE

的JavaScript

var prefix = useLighting ? '#define USE_TEXTURE' : ''; 
var shaderSource = prefix + originalShaderSource; 

大多数发动机通过采用大量的GLSL的一小块一小块的,并与各种字符串替换结合,虽然做了很多的字符串操作。

+0

但预处理器将不允许更改应用的着色器或命令j。在实际着色器编译完成后应用它们。我的主要目标是在客户端程序和单个着色器编译完成后(例如通过输入选择)完成这些事情。 – WoodMath

+0

现在,着色器是如何工作的。生成着色器。无论您是否使用预处理器来帮助解决这个问题,都取决于您。 – gman