2015-11-09 80 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