2014-12-03 74 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