繁体   English   中英

OpenGL:关于使用多个纹理或纹理单元的一些说明

[英]OpenGL: Some clarification on using multiple textures or texture units

我需要在着色器中使用两个纹理,一个在顶点着色器中,另一个在片段着色器中。 在这两种情况下,它们在着色器中引用,如uniform sampler2D tex1; uniform sampler2D tex2; 但是,我不确定如何正确使用相关的GL调用。

初始化

首先,我如何创建两个纹理? 我是否需要使用多个纹理单元

GLuint texIdx[2] = {0, 1};
GLuint texName[2];
Grint  texUniformID[2];

// Initialize first texture
glActiveTexture (GL_TEXTURE0 + texIdx[0]);
glGenTextures   (1, &texName[0]);
glBindTexture   (GL_TEXTURE_2D, texName[0]);
glTexImage2D    (GL_TEXTURE_2D, 0, GL_R32F, xDim0, yDim0, 0, GL_RED, GL_FLOAT, someTextureData);

// Initialize second texture
glActiveTexture (GL_TEXTURE0 + texIdx[1]);
glGenTextures   (1, &texName[1]);
glBindTexture   (GL_TEXTURE_2D, texName[1]);
glTexImage2D    (GL_TEXTURE_2D, 0, GL_RGB, xDim1, yDim1, 0, GL_RGB, GL_FLOAT, someOther1TextureData);

// Set the uniforms to refer to the textures
texUniformID[0] = glGetUniformLocation (myShaderProgram, "tex1");
texUniformID[1] = glGetUniformLocation (myShaderProgram, "tex2");
glUniform1i (texUniformID[0], texIdx[0]);
glUniform1i (texUniformID[1], texIdx[1]);

或者我可以使用单个纹理单元,因为glGenTextures允许我创建多个纹理,有点像:

GLuint texName[2];
Grint  texUniformID[2];

// Activate some texture unit
glActiveTexture (GL_TEXTURE0);

// Generate two textures
glGenTextures (2, texName);

// Initialize first texture
glBindTexture   (GL_TEXTURE_2D, texName[0]);
glTexImage2D    (GL_TEXTURE_2D, 0, GL_R32F, xDim0, yDim0, 0, GL_RED, GL_FLOAT, someTextureData);

// Initialize second texture
glBindTexture   (GL_TEXTURE_2D, texName[1]);
glTexImage2D    (GL_TEXTURE_2D, 0, GL_RGB, xDim1, yDim1, 0, GL_RGB, GL_FLOAT, someOther1TextureData);

// Set the uniforms to refer to the textures
texUniformID[0] = glGetUniformLocation (myShaderProgram, "tex1");
texUniformID[1] = glGetUniformLocation (myShaderProgram, "tex2");
glUniform1i (texUniformID[0], /* what parameter here? */);
glUniform1i (texUniformID[1], /* what parameter here? */);

总而言之,我不明白一方面有多个纹理单元的意义,另一方面是通过调用glGenTextures创建多个纹理的能力,如果我需要多个纹理,那么正确的方法是什么在着色器程序中。

渲染时的用法

作为一个后续问题,如果我用正确的方式初始化了我的多个纹理,那么在调用glDrawElements期间激活两个纹理以调用活动的调用的正确顺序是什么,以及成功更新纹理的调用的正确顺序是什么在运行时glTexSubImage2D

跟进问题

现在更进一步,如果我在渲染调用中使用多个不同的着色器程序并且所有这些程序都使用纹理,那么应该如何处理? 每个着色器程序的每个纹理是否应使用唯一的纹理单元?

如果要在一个着色器程序中使用多个二维纹理,则需要将不同的纹理对象绑定到不同的纹理单元。
生成纹理名称(值)( glGenTextures )或指定纹理图像( glTexImage2D )时,没有必要选择合适的纹理单元( glActiveTexture ),但是纹理必须先绑定到适当的纹理单元通过使用着色器程序绘制对象(网格)。

通过将纹理绑定到纹理单元并将纹理单元的数量设置为均匀变量,实现着色器程序中的纹理采样器均匀与纹理对象之间的绑定。

制服的值可以由glUniform1i设置

texUniformID[0] = glGetUniformLocation(myShaderProgram, "tex1");
texUniformID[1] = glGetUniformLocation(myShaderProgram, "tex2");
glUniform1i(texUniformID[0], 0);
glUniform1i(texUniformID[1], 1);

或者通过绑定点布局限定符进行着色器:

layout(binding = 0) uniform sampler2D tex1;
layout(binding = 1) uniform sampler2D tex2;

由于绑定点为0和1,因此在使用着色器程序绘制几何体之前,纹理对象必须绑定到纹理单元0( GL_TEXTURE0 )和1( GL_TEXTURE1 ):

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texName[0]);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texName[1]);

glDrawElements(...);

但是当纹理被“创建”时,没有必要分别选择纹理单元0 1:

glGenTextures(2, texName);

// Initialize first texture
glBindTexture(GL_TEXTURE_2D, texName[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, xDim0, yDim0, 0, GL_RED, GL_FLOAT, data1);

// Initialize second texture
glBindTexture(GL_TEXTURE_2D, texName[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, xDim1, yDim1, 0, GL_RGB, GL_FLOAT, data2);

当然,您可以在创建纹理之前选择纹理单元,然后在以后绑定它们是多余的。 但请注意, glGenTextures不会创建纹理对象,它只保留可用于纹理对象的名称(值)。 glBindTexture第一次将名称(值)绑定到纹理目标时,将创建纹理。 这意味着如果glBindTexture不存在或者使用现有纹理, glBindTexture创建纹理。 glTexImage2D指定,创建和初始化绑定到当前纹理单元的指定目标的现有纹理对象的图像:

glGenTextures(2, texName);

// Initialize first texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texName[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, xDim0, yDim0, 0, GL_RED, GL_FLOAT, data1);

// Initialize second texture
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texName[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, xDim1, yDim1, 0, GL_RGB, GL_FLOAT, data2);

glTexSubImage2D更新当前绑定到当前纹理单元的指定目标的纹理对象的纹理图像的内容。 你要做的就是绑定纹理对象。

glBindTexture(GL_TEXTURE_2D, texName[0]);
glTexSubImage2D(GL_TEXTURE_2D, ...);

但请注意, glBindTexture将纹理绑定到当前选定的纹理单元,因此如果当前选择了“错误”纹理单元(当前纹理单元是全局状态),它可能会弄乱纹理对象和纹理单元的组合。 因此选择合适的纹理单元可能是有意义的。 如果纹理对象仍然绑定到纹理单元,则无需将其绑定到agian:

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texName[0]); // <-- this is possibly unnecessary
glTexSubImage2D(GL_TEXTURE_2D, ...);

当然,不同的着色器程序可以使用相同的绑定点。 但请注意,纹理单元的数量是有限的。 如果你有很多纹理,就不可能将每个纹理对象绑定到不同的纹理单元。 但是,如果你有2个纹理对象和不同的着色器程序,将2个纹理对象绑定到不同的纹理对象并在每个着色器程序中(重新)使用相同的绑定点是很方便的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM