OpenGL:关于使用多个纹理或纹理单元的一些说明 [英] OpenGL: Some clarification on using multiple textures or texture units

查看:224
本文介绍了OpenGL:关于使用多个纹理或纹理单元的一些说明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to use two textures in my shader, one in the vertex shader, another in the fragment shader. In both cases they are referenced in the shaders like uniform sampler2D tex1; or uniform sampler2D tex2; However I'm not really sure on how to use the related GL calls properly.

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

First of all, how do I create the two textures? Do I need to use multiple texture units like so

GLuint texIdx[2] = {0, 1};
GLuint texName[2];
GLint  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 允许我创建多个纹理,有点像这样:

Or can I use a single texture unit, as glGenTextures allows me to create multiple textures, somewhat like that:

GLuint texName[2];
GLint  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 来创建多个纹理的能力以及什么是如果我需要在着色器程序中使用多个纹理,这是正确的方法.

So to summarize, I don't understand what's the point on having multiple texture units on the one hand and the ability to create multiple textures with a call to glGenTextures on the other hand and what is the right way to go if I need multiple textures in a shader program.

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

As a follow up question, If I have initialized my multiple textures with the correct way, what is the right order of calls to activate both textures to become active during a call to glDrawElements and what is the right order of calls to successfully update a texture at runtime glTexSubImage2D?

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

Now one step further, if I use multiple different shader programs in a render call and all of them use textures, how should that be handled? Should each texture for each shader program use a unique texture unit?

推荐答案

如果您想在一个着色器程序中使用多个二维纹理,那么您必须将不同的纹理对象绑定到不同的纹理单元.
没有必要选择正确的纹理单元(glActiveTexture) 生成纹理名称(值)时(glGenTextures) 或指定纹理图像时 (glTexImage2D),但是在对象(网格)被绘制之前,纹理必须绑定到适当的纹理单元使用着色器程序.

If you want to use multiple 2 dimensional textures in one shader program, then you've to bind the different texture objects to different texture units.
It is not necessary that the proper texture unit is selected (glActiveTexture) when the texture name (value) is generated (glGenTextures) or when the texture image is specified (glTexImage2D), but the texture has to be bound to the proper texture unit before the object (mesh) is drawn by the use of the shader program.

着色器程序中的纹理采样器uniform与纹理对象的绑定,通过将纹理绑定到一个纹理单元,并将纹理单元的编号设置为uniform变量来实现.

The binding between the texture sampler uniform in the shader program and the texture object is achieved, by binding the texture to a texture unit and setting the number of the texture unit to uniform variable.

uniform 的值可以通过 <代码>glUniform1i

The value of the uniform can either be set by glUniform1i

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

或通过 绑定点 布局限定符的着色器:

or in-shader by a Binding point layout qualifier:

layout(binding = 0) uniform sampler2D tex1;

layout(binding = 1) uniform sampler2D tex2;

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

Since the binding points are 0 and 1, the texture objects have to be bound to the texture units 0 (GL_TEXTURE0) and 1 (GL_TEXTURE1), before drawing the geometry with the shader program:

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

glDrawElements(...);

但是没有必要在创建"纹理时分别选择纹理单元0和1:

But it is not necessary to select the texture unit 0 respectively 1, when the texture is "created":

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 会在纹理不存在或使用现有纹理时创建该纹理.glTexImage2D 指定,创建并初始化绑定到当前纹理单元指定目标的现有纹理对象的图像:

Of course you can select a texture unit before creating the textures, then it is superfluous to bind them later. But note, glGenTextures doesn't create a texture object, it just reserves names (values) which can be used for texture objects. The texture is created when the name (value) the first time is bound to a texturing target by glBindTexture. This means glBindTexture creates a texture if it doesn't exist or it use the existing texture. glTexImage2D specifies, creates and initialize the image of the existing texture object which is bound to the specified target of the current texture unit:

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 更新当前绑定到当前纹理单元的指定目标的纹理对象的纹理图像的内容.您所要做的就是绑定纹理对象.


glTexSubImage2D updates the content of a texture image of the texture object which is currently bound to the specified target of the current texture unit. All you've to do is to bind the texture object.

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

但请注意,glBindTexture 将纹理绑定到当前选定的纹理单元,因此,如果当前选择了错误"的纹理单元,则可能会弄乱您的纹理对象和纹理单元的组合(当前纹理单元是一个全局状态).所以选择合适的纹理单元可能是有意义的.如果纹理对象仍然绑定到纹理单元,则不需要重新绑定:

But note that glBindTexture binds the texture to the currently selected texture unit, so it may mess up your combinations of texture objects and texture units, if the "wrong" texture unit is currently selected (The current texture unit is a global state). So it may make sense to select the proper texture unit. If the texture object is still bound to the texture unit, it is unnecessary to bind it agian:

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

<小时>

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


Of course different shader programs can use the same binding points. But note that the number of texture units is limited. If you've a lot of textures it is not possible to bind each texture object to a different texture unit. But, if you've 2 texture objects and different shader programs it is handy to bind the 2 texture objects to different texture inits and to (re)use the same binding points in each shader program.

这篇关于OpenGL:关于使用多个纹理或纹理单元的一些说明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆