具有纹理对象和采样器的多重纹理理论 [英] Multitexturing theory with texture objects and samplers

查看:80
本文介绍了具有纹理对象和采样器的多重纹理理论的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我找不到关于如何仅使用纹理对象或纹理对象加采样器来编码多纹理的良好理论文章.我只是不知道如何管理glActiveTexture函数及其确切功能.

I couldn't find any good theory articles on how to code multitexturing with either only texture objects or texture objects plus samplers. I just don't know how to manage the glActiveTexture function and what it exactly does.

glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE0 + 0); // Number between 0 and GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, img.getSize().x, img.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.getPixelsPtr()); // Not in sampler
glGenerateMipmap(GL_TEXTURE_2D); // Not in sampler

/* Values associated with the texture and not with sampler (sampler has priority over texture).
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);*/

glGenSamplers(1, &textureSampler);
glBindSampler(0, textureSampler);
glSamplerParameteri(textureSampler, GL_TEXTURE_WRAP_S, GL_REPEAT);
glSamplerParameteri(textureSampler, GL_TEXTURE_WRAP_T, GL_REPEAT);
glSamplerParameteri(textureSampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glSamplerParameteri(textureSampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

glUniform1i(glGetUniformLocation(colorShader->program, "textureSampler"), 0); // 0 pour GL_TEXTURE0

对于多纹理处理是要在片段代码中将多个采样器链接到多个纹理,还是只有一个采样器具有多个纹理,我有些困惑?

I'm a little bit confused about if multitexturing is about having multiple samplers in the fragment code linked to multiple textures or if it is possible to have only have one sampler with multiple textures?

推荐答案

其中许多内容已经在前面进行了解释,但是让我尝试给出一个概述,以期使所有这些不同的部分如何变得更加清晰.我将从分别解释每个部分开始,然后解释它们的连接方式.

Much of this must have been explained before, but let me try and give an overview that will hopefully make it clearer how all the different pieces fit together. I'll start by explaining each piece separately, and then explain how they are connected.

这是指不同类型的纹理(2D,3D等).您可以同时将多个纹理(每种纹理类型之一)绑定到同一纹理单元.例如,之后:

This refers to the different types of textures (2D, 3D, etc). You can have multiple textures, one of each texture type, bound to the same texture unit at the same time. For example, after:

glBindTexture(GL_TEXTURE_2D, texId1);
glBindTexture(GL_TEXTURE_3D, texId2);

两者 texId1texId2将绑定到相同的纹理单元,这是可能的,因为它们绑定到了不同的目标.

BothtexId1 and texId2 will be bound to the same texture unit, which is possible because they are bound to different targets.

有关此问题的细节有些令人费解且令人困惑,在本答案的其余部分中,我将不予考虑.我建议您始终将不同的纹理绑定到不同的纹理单元.它将使您免于头痛和意外.

The details of this are somewhat convoluted and confusing, and I won't consider it in the rest of this answer. I would recommend that you always bind different textures to different texture units. It will save you from headaches and surprises.

纹理对象的名称是用glGenTextures()创建的,它们用glBindTexture()绑定,依此类推.纹理对象自己的:

Names for texture objects are created with glGenTextures(), they are bound with glBindTexture(), etc. Texture objects own:

  • 纹理数据.
  • 定义纹理数据采样方式的状态,例如过滤使用glTexParameteri()设置的属性.
  • Texture data.
  • State that defines how the texture data is sampled, like filtering attributes set with glTexParameteri().

它们还包含有关与数据一起指定的纹理格式/类型的信息.

They also contain information about the texture format/type that was specified together with the data.

作为当前OpenGL状态的一部分,您可以绘制一张当前绑定的纹理表的图片.我们需要同时绑定多个纹理,以支持多重纹理.纹理单元可以看作是此状态表中的一个条目.

As part of the current OpenGL state, you can picture a table of textures that are currently bound. We need more than a single texture bound at the same time to support multi-texturing. A texture unit can be seen as an entry in this state table.

您使用glActiveTexture()指定当前活动的纹理单位.然后,需要在特定纹理单元上进行操作的调用将在活动纹理单元上进行操作.例如:

You use glActiveTexture() to specify the currently active texture units. Calls that need to operate on a specific texture unit will then operate on the active texture unit. For example:

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

texId绑定到纹理单元3.再次为绑定的纹理表绘制图像,第4个条目(编号从0开始)现在指向纹理texId.

Will bind texId to texture unit 3. Picturing the table of bound textures again, the 4th entry (numbering starts at 0) now points at the texture texId.

这是OpenGL 3.3及更高版本中可用的一种较新的对象.对于大多数用例,即使它们涉及从多个纹理采样,您也将不需要.为了完整起见,我将它们包括在这里,但是在您牢牢掌握纹理对象和纹理单位之前,无需担心采样器.

This is a newer kind of object available in OpenGL 3.3 and later. You will not need this for most use cases, even if they involve sampling from multiple textures. I'm including them here for completeness, but there's no need to worry about samplers until you have a firm grasp of texture objects and texture units.

还记得上面如何解释纹理对象拥有纹理数据以及定义数据采样方式的状态吗?采样器本质上所做的就是将这两个方面分离.采样器对象包含的状态可以覆盖纹理对象中与采样相关的状态.

Remember how I explained above that texture objects own the texture data, as well as state that defines how the data is sampled? What samplers essentially do is decouple these two aspects. The sampler object contains state that can override the sampling related state in the texture object.

这可以让您在同一着色器中对具有不同采样参数的单个纹理进行采样.假设您要在单个着色器中对相同纹理进行线性采样和NEAREST采样.如果没有采样器对象,那么没有相同纹理的多个副本(即数据的多个副本)就无法做到这一点.采样器对象启用了这种功能.

What this allows you to do is sample one single texture with different sampling parameters in the same shader. Say you wanted to do LINEAR and NEAREST sampling of the same texture in a single shader. Without sampler objects, you can't do that without having multiple copies of the same texture (with multiple copies of the data). Sampler objects enable this kind of functionality.

这是OpenGL 4.3中引入的功能.甚至比纹理采样器更多,我只是为了完整性而提到它.

This is a feature introduced in OpenGL 4.3. Even more than texture samplers, I'm only mentioning it for completeness.

在采样器将纹理数据(及其关联格式)与采样参数解耦的情况下,纹理视图将原始纹理数据与格式解耦.它们使得可以使用具有不同格式的相同原始纹理数据.我怀疑您可以在不使用此功能的情况下走很长一段路.

Where samplers decouple the texture data (with its associated format) from the sampling parameters, texture views decouple the raw texture data from the format. They make it possible to use the same raw texture data with different formats. I suspect that you can go a very long way without ever using this feature.

您最终想要做的是指定着色器应从中采样的纹理.纹理单元是在着色器和纹理之间建立连接的关键.

What you ultimately want to do is specify which textures a shader should sample from. Texture units are the critical pieces in making the connection between shaders and textures.

从着色器的侧面看,着色器知道它从中采样的纹理单元.这由采样器统一变量的值给出.例如,如果"MyFirstTexture"是着色器代码中采样器变量的名称,则以下指定该变量与纹理单元3相关联:

Looking at it from the side of the shader, the shader knows which texture units it samples from. This is given by the value of the sampler uniform variables. For example, if "MyFirstTexture" is the name of a sampler variable in the shader code, the following specifies that the variable is associated with texture unit 3:

GLint loc = glGetUniformLocation(prog, "MyFirstTexture");
glUniform1i(loc, 3);

纹理单元和纹理对象之间的关联是通过上面已经显示的代码片段建立的:

The association between texture unit and a texture object is established with the code fragment that was already shown above:

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

这两部分是将纹理连接到着色器代码中的采样器变量的关键部分.请注意,统一变量的值是纹理单位的索引(3),而glActiveTexture()的参数是相应的枚举(GL_TEXTURE3).我认为这是不幸的API设计,但是您只需要习惯它即可.

These two pieces are the critical parts in connecting a texture to a sampler variable in your shader code. Note that the value of the uniform variable is the index of the texture unit (3), while the argument of glActiveTexture() is the corresponding enum (GL_TEXTURE3). I would argue that this is unfortunate API design, but you'll just have to get used to it.

一旦您了解了这一点,就可以很清楚地知道如何在着色器中使用多个纹理(又称为多重纹理"):

Once you understand this, it will hopefully be very obvious how you use multiple textures in your shader (aka "multi-texturing"):

  • 着色器代码中有多个采样器变量.
  • 您进行glUniform1i()调用,以将采样器变量的值设置为不同纹理单位的索引.
  • 您将纹理绑定到每个匹配的纹理单元.
  • You have multiple sampler variables in your shader code.
  • You make the glUniform1i() calls to set the values of the sampler variables to indices of different texture units.
  • You bind a texture to each of the matching texture units.

使用纹理单位0和1为两个纹理显示此图片

Showing this for two texture, using texture units 0 and 1:

glUseProgram(prog);

GLint loc = glGetUniformLocation(prog, "MyFirstTexture");
glUniform1i(loc, 0);
loc = glGetUniformLocation(prog, "MySecondTexture");
glUniform1i(loc, 1);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texId0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texId1);

查看此问题的另一种方法是,着色器中的采样器变量与纹理对象之间存在一定程度的间接性.着色器与纹理对象没有直接连接.相反,它在纹理对象表中有一个索引(此索引是统一变量的值),并且该表又包含纹理对象的指针"(在其中表项填充有glActiveTexture()/ glBindTexture( )`.

One other way of looking at this is that there's a level of indirection between samplers variables in shaders, and texture objects. The shader does not have a direct connection to the texture objects. Instead, it has an index into a table of texture objects (where this index is the value of the uniform variable), and this table in turn contains "pointers" to texture objects (where the table entries are populated with glActiveTexture()/glBindTexture()`.

或者使用通信术语对同一事物进行最后的类比:您可以将纹理单位视为端口.您告诉着色器从哪个端口读取数据(统一变量的值).然后,将纹理插入端口(通过将其绑定到纹理单元).现在,着色器将从您插入端口的纹理中读取数据.

Or one final analogy for the same thing, using communication terminology: You can look at the texture units as ports. You tell the shader which ports to read data from (value of uniform variable). Then you plug a texture into the port (by binding it to the texture unit). The shader will now read data from the texture you plugged into the port.

这篇关于具有纹理对象和采样器的多重纹理理论的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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