OpenGL中的多个着色器

时间:2015-11-09 18:34:07

标签: opengl opengl-es glsl webgl shader

有没有办法创建多个着色器(顶点,片段,甚至几何和曲面细分),这些着色器可以在它们的作用中复合?

例如:我在OpenGL的更高版本中看到了 out 关键字的多种用法,并将使用这些来说明我的题。

是否有一种给定着色器的方法(没有关系,但让我们说片段着色器),例如

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;
}

out 是正确的"概念"描述这种行为还是我应该寻找其他关键词?

2 个答案:

答案 0 :(得分:4)

生成着色器。这就是所有3D引擎和游戏引擎所做的事情。

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

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

if (datediff(mm,@maxdw01,@maxas48)=1) 
begin 
    select 1 as MonthFlag 
end else 
    select 0 as MonthFlag 
End 

然后在运行时预先添加一个字符串来定义#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 }

的JavaScript

USE_TEXTURE

大多数引擎虽然通过使用大量的小块GLSL并将它们与各种字符串替换相结合来进行更多的字符串操作。

答案 1 :(得分:3)

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

这是来自OpenGL 4.5规范,“7.3程序对象”一节,第88页(重点补充):

  

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

与OpenGL ES 3.2规范相比,第7章“7.3程序对象”一节(重点补充):

  

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

但是,即使在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);
}