简体   繁体   English

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

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

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; 在这两种情况下,它们在着色器中引用,如uniform sampler2D tex1; or uniform sampler2D tex2; uniform sampler2D tex2; However I'm not really sure on how to use the related GL calls properly. 但是,我不确定如何正确使用相关的GL调用。

Initialization 初始化

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];
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]);

Or can I use a single texture unit, as glGenTextures allows me to create multiple textures, somewhat like that: 或者我可以使用单个纹理单元,因为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? */);

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

Usage during rendering 渲染时的用法

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

Follow up question 跟进问题

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? 每个着色器程序的每个纹理是否应使用唯一的纹理单元?

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. 生成纹理名称(值)( glGenTextures )或指定纹理图像( glTexImage2D )时,没有必要选择合适的纹理单元( glActiveTexture ),但是纹理必须先绑定到适当的纹理单元通过使用着色器程序绘制对象(网格)。

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

The value of the uniform can either be set by glUniform1i 制服的值可以由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;

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: 由于绑定点为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(...);

But it is not necessary to select the texture unit 0 respectively 1, when the texture is "created": 但是当纹理被“创建”时,没有必要分别选择纹理单元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);

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. 但请注意, glGenTextures不会创建纹理对象,它只保留可用于纹理对象的名称(值)。 The texture is created when the name (value) the first time is bound to a texturing target by glBindTexture . glBindTexture第一次将名称(值)绑定到纹理目标时,将创建纹理。 This means glBindTexture creates a texture if it doesn't exist or it use the existing texture. 这意味着如果glBindTexture不存在或者使用现有纹理, glBindTexture创建纹理。 glTexImage2D specifies, creates and initialize the image of the existing texture object which is bound to the specified target of the current texture unit: 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 updates the content of a texture image of the texture object which is currently bound to the specified target of the current texture unit. glTexSubImage2D更新当前绑定到当前纹理单元的指定目标的纹理对象的纹理图像的内容。 All you've to do is to bind the texture object. 你要做的就是绑定纹理对象。

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

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

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

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. 但是,如果你有2个纹理对象和不同的着色器程序,将2个纹理对象绑定到不同的纹理对象并在每个着色器程序中(重新)使用相同的绑定点是很方便的。

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

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