2014-12-03 77 views
1

我有一個正常運行的OpenGL ES 3程序(iOS),但我很難理解OpenGL紋理。我試圖在屏幕上渲染幾個四邊形,所有這些都具有不同的紋理。這些紋理都是256色的彩色圖像,並帶有特殊調色板。OpenGL ES 3(iOS)紋理奇怪 - 想知道爲什麼

這是C++代碼,發送紋理着色器

// THIS CODE WORKS, BUT I'M NOT SURE WHY 
    glActiveTexture(GL_TEXTURE1); 
    glBindTexture(GL_TEXTURE_2D, _renderQueue[idx]->TextureId); 
    glUniform1i(_glShaderTexture, 1); // what does the 1 mean here 

    glActiveTexture(GL_TEXTURE2); 
    glBindTexture(GL_TEXTURE_2D, _renderQueue[idx]->PaletteId); 
    glUniform1i(_glShaderPalette, 2); // what does the 2 mean here? 

    glDrawElements(GL_TRIANGLES, sizeof(Indices)/sizeof(Indices[0]), GL_UNSIGNED_BYTE, 0); 

這是片段着色器

uniform sampler2D texture; // New 
uniform sampler2D palette;      // A palette of 256 colors 
varying highp vec2 texCoordOut; 
void main() 
{ 
    highp vec4 palIndex = texture2D(texture, texCoordOut);  
    gl_FragColor = texture2D(palette, palIndex.xy); 
} 

正如我所說的,代碼工作,但我不確定它爲什麼起作用。幾個看似微小的變化打破了它。例如,在C++代碼中使用GL_TEXTURE0GL_TEXTURE1將其分解。將glUniform1i中的數字更改爲0,並將其分解爲1。我猜我不明白OpenGL 3+中的紋理(可能是紋理單元???),但需要一些指導來弄清楚什麼。

回答

3

因爲新手的OpenGL程序員經常會感到困惑,所以我會嘗試在非常基本的層面上解釋紋理單元的概念。一旦你掌握了術語,這不是一個複雜的概念。

整個事情的動機是提供在着色器中採樣多個紋理的可能性。由於OpenGL傳統上使用與glBind*()調用綁定的對象進行操作,這意味着需要綁定多個紋理的選項。因此,具有綁定紋理的概念被擴展到具有綁定紋理的表格。 OpenGL稱之爲紋理單元是該表中的一個條目,由索引指定。

如果要以C/C++風格的表示法描述此狀態,可以將綁定紋理表定義爲紋理ids數組,其中size是實現支持的最大綁定紋理數(查詢與glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, ...)):

GLuint BoundTextureIds[MAX_TEXTURE_UNITS]; 

如果您綁定的紋理,它被綁定到當前的活動紋理單元。這意味着最後一次調用glActiveTexture()可以確定綁定紋理表中的哪個條目被修改。在一個典型的呼叫序列,其結合一個紋理紋理單元i

glActiveTexture(GL_TEXTUREi); 
glBindTexture(GL_TEXTURE_2D, texId); 

這將對應於通過修改我們的假想的數據結構:

BoundTextureIds[i] = texId; 

覆蓋設置。現在,着色器可以訪問此表中的所有紋理。類型sampler2D的變量用於訪問GLSL代碼中的紋理。要確定每個sampler2D變量訪問哪個紋理,我們需要指定每個使用哪個表項。這是通過統一的值設置爲表的索引進行:

glUniform1i(samplerLoc, i); 

規定,在位置samplerLoc採樣統一由表項i讀取,這意味着樣品ID BoundTextureIds[i]質感。

在該問題的具體情況下,第一個紋理綁定到紋理單元1,因爲glActiveTexture(GL_TEXTURE1)glBindTexture()之前被調用。要從着色器訪問此紋理,着色器制服也需要設置爲1。第二個紋理與紋理單元2相同。

(上面的描述略有簡化,因爲它沒有考慮到不同的紋理目標,實際上,可以綁定具有不同目標的紋理,例如GL_TEXTURE_2DGL_TEXTURE_3D

2

GL_TEXTURE1和GL_TEXTURE2指紋理單元。 glUniform1i爲採樣器的第二個參數提供紋理單元ID。這就是爲什麼它們是1和2。

從OpenGL的網站:

在程序採樣均勻的值是不是一個紋理對象, 但紋理圖像單元索引。因此,您在程序中爲每個採樣器設置 的紋理單元索引。

+0

@sevensevens ...並且'GL_TEXTURE0'是第一個紋理單元,而不是'GL_TEXTURE1';此外,枚舉'GL_TEXTUREn'保證爲'GL_TEXTURE0 + n'。所以如果你想將'2'分解爲一個單獨的變量或常量,你的代碼可以表示爲'glActiveTexture(GL_TEXTURE0 + 2)... glUniform1i(_glShaderPalette,2)'。但Mobile Ben的回答涵蓋了重要的一點。 – Tommy 2014-12-03 02:46:28