glActiveTexture和glBindTexture之间的区别和关系 [英] Differences and relationship between glActiveTexture and glBindTexture

查看:117
本文介绍了glActiveTexture和glBindTexture之间的区别和关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据我的收集,glActiveTexture设置活动的纹理单位".每个纹理单元可以有多个纹理目标(通常是GL_TEXTURE_1D,2D,3D或CUBE_MAP).

From what I gather, glActiveTexture sets the active "texture unit". Each texture unit can have multiple texture targets (usually GL_TEXTURE_1D, 2D, 3D or CUBE_MAP).

如果我理解正确,您必须先调用glActiveTexture设置纹理单元(初始化为GL_TEXTURE0),然后将(一个或多个)纹理目标"绑定到该纹理单元?

If I understand correctly, you have to call glActiveTexture to set the texture unit first (initialized to GL_TEXTURE0), and then you bind (one or more) "texture targets" to that texture unit?

可用的纹理单位数取决于系统.我在库中最多看到32个枚举.我想这本质上意味着我可以随时降低GPU内存的限制(我认为是 16 8)和GPU内存中的32个纹理?我猜还有一个额外的限制,即我不超过GPU的最大内存(应该是1 GB).

The number of texture units available is system dependent. I see enums for up to 32 in my library. I guess this essentially means I can have the lesser of my GPU's limit (which I think is 16 8) and 32 textures in GPU memory at any one time? I guess there's an additional limit that I don't exceed my GPU's maximum memory (supposedly 1 GB).

我是否正确理解纹理目标和纹理单位之间的关系?假设我被允许16个单位和4个目标,这是否意味着16 * 4 = 64个目标有空间,还是不能那样工作?

Am I understanding the relationship between texture targets and texture units correctly? Let's say I'm allowed 16 units and 4 targets each, does that mean there's room for 16*4=64 targets, or does it not work like that?

接下来,您通常要加载纹理.您可以通过glTexImage2D执行此操作.其第一个参数是纹理目标.如果此glBufferData 一样工作,那么我们实质上将句柄"/纹理名称"绑定到纹理目标,然后将纹理数据加载到该目标中,从而将其与该手柄间接关联.

Next you typically want to load a texture. You can do this via glTexImage2D. The first argument of which is a texture target. If this works like glBufferData, then we essentially bind the "handle"/"texture name" to the texture target, and then load the texture data into that target, and thus indirectly associate it with that handle.

glTexParameter怎么样?我们必须绑定一个纹理目标,然后再次选择相同的目标作为第一个参数?还是只要我们具有正确的活动纹理单位,就不需要绑定纹理目标?

What about glTexParameter? We have to bind a texture target, and then choose that same target again as the first argument? Or does the texture target not need to be bound as long as we have the correct active texture unit?

glGenerateMipmap也在目标上运行...目标是否仍必须绑定到纹理名称才能成功?

glGenerateMipmap operates on a target too...that target has to still be bound to the texture name for it to succeed?

然后,当我们要绘制带有纹理的对象时,是否必须选择一个活动的纹理单元,然后选择一个纹理目标?还是我们选择一个纹理单位,然后可以从与该单位关联的4个目标中的任意一个获取数据?这部分确实让我感到困惑.

Then when we want to draw our object with a texture on it, do we have to both choose an active texture unit, and then a texture target? Or do we choose a texture unit, and then we can grab data from any of the 4 targets associated with that unit? This is the part that's really confusing me.

推荐答案

关于OpenGL对象的所有信息

OpenGL对象的标准模型如下.

All About OpenGL Objects

The standard model for OpenGL objects is as follows.

对象具有状态.将它们视为struct.因此,您可能有一个这样定义的对象:

Objects have state. Think of them as a struct. So you might have an object defined like this:

struct Object
{
    int count;
    float opacity;
    char *name;
};

该对象中存储有某些值,并且具有 state . OpenGL对象也具有状态.

The object has certain values stored in it and it has state. OpenGL objects have state too.

在C/C ++中,如果您具有类型为Object的实例,则可以按以下方式更改其状态:obj.count = 5;您将直接引用该对象的实例,获取要更改的特定状态,然后在其中填充一个值.

In C/C++, if you have an instance of type Object, you would change its state as follows: obj.count = 5; You would directly reference an instance of the object, get the particular piece of state you want to change, and shove a value into it.

在OpenGL中,您不要执行此操作.

In OpenGL, you don't do this.

出于遗留原因,最好不解释,要更改OpenGL对象的状态,必须首先将其 bind 绑定到上下文.这是通过glBind*调用中的某些操作完成的.

For legacy reasons better left unexplained, to change the state of an OpenGL object, you must first bind it to the context. This is done with some from of glBind* call.

与此等效的C/C ++如下:

The C/C++ equivalent to this is as follows:

Object *g_objs[MAX_LOCATIONS] = {NULL};    
void BindObject(int loc, Object *obj)
{
  g_objs[loc] = obj;
}

纹理很有趣;它们代表绑定的特例.许多glBind*调用都有一个目标"参数.这表示OpenGL上下文中可以绑定该类型对象的不同位置.例如,您可以绑定帧缓冲区对象以进行读取(GL_READ_FRAMEBUFFER)或进行写入(GL_DRAW_FRAMEBUFFER).这会影响OpenGL使用缓冲区的方式.这就是上面的loc参数代表的含义.

Textures are interesting; they represent a special case of binding. Many glBind* calls have a "target" parameter. This represents different locations in the OpenGL context where objects of that type can be bound. For example, you can bind a framebuffer object for reading (GL_READ_FRAMEBUFFER) or for writing (GL_DRAW_FRAMEBUFFER). This affects how OpenGL uses the buffer. This is what the loc parameter above represents.

纹理是特殊的,因为当您 first 将它们绑定到目标时,它们会获得特殊的信息.第一次将纹理绑定为GL_TEXTURE_2D时,实际上是在纹理中设置特殊状态.您是说该纹理是2D纹理.而且它会始终为2D纹理;此状态不能永远更改.如果您有一个首先绑定为GL_TEXTURE_2D的纹理,则必须始终将其绑定为GL_TEXTURE_2D;否则,必须将其绑定为GL_TEXTURE_2D.尝试将其绑定为GL_TEXTURE_1D会导致错误(在运行时).

Textures are special because when you first bind them to a target, they get special information. When you first bind a texture as a GL_TEXTURE_2D, you are actually setting special state in the texture. You are saying that this texture is a 2D texture. And it will always be a 2D texture; this state cannot be changed ever. If you have a texture that was first bound as a GL_TEXTURE_2D, you must always bind it as a GL_TEXTURE_2D; attempting to bind it as GL_TEXTURE_1D will give rise to an error (while run-time).

绑定对象后,即可更改其状态.这是通过特定于该对象的通用函数完成的.它们也采用代表要修改的对象的位置.

Once the object is bound, its state can be changed. This is done via generic functions specific to that object. They too take a location that represents which object to modify.

在C/C ++中,它看起来像:

In C/C++, this looks like:

void ObjectParameteri(int loc, ObjectParameters eParam, int value)
{
  if(g_objs[loc] == NULL)
    return;

  switch(eParam)
  {
    case OBJECT_COUNT:
      g_objs[loc]->count = value;
      break;
    case OBJECT_OPACITY:
      g_objs[loc]->opacity = (float)value;
      break;
    default:
      //INVALID_ENUM error
      break;
  }
}

注意此函数如何设置当前绑定的loc值中的值.

Notice how this function sets whatever happens to be in currently bound loc value.

对于纹理对象,主要的纹理状态更改功能为 glTexParameter .更改纹理状态的唯一其他功能是 glTexImage 函数及其变体( glCompressedTexImage ).各种SubImage版本都会更改纹理的内容,但是从技术上讲,它们不会更改其状态. Image函数分配纹理存储并设置纹理的格式. SubImage函数只是在周围复制像素.那不被认为是纹理的状态.

For texture objects, the main texture state changing functions are glTexParameter. The only other functions that change texture state are the glTexImage functions and their variations (glCompressedTexImage, glCopyTexImage, the recent glTexStorage). The various SubImage versions change the contents of the texture, but they do not technically change its state. The Image functions allocate texture storage and set the texture's format; the SubImage functions just copy pixels around. That is not considered the texture's state.

让我重复一遍:这些是只能修改纹理状态的功能. glTexEnv修改环境状态;它不会影响存储在纹理对象中的任何东西.

Allow me to repeat: these are the only functions that modify texture state. glTexEnv modifies environment state; it doesn't affect anything stored in texture objects.

纹理的情况更为复杂,同样出于遗留原因,最好不要公开.这是 glActiveTexture 出现的地方.

The situation for textures is more complex, again for legacy reasons best left undisclosed. This is where glActiveTexture comes in.

对于纹理,不仅有目标(GL_TEXTURE_1DGL_TEXTURE_CUBE_MAP等).还有纹理 units .就我们的C/C ++示例而言,我们所拥有的是:

For textures, there aren't just targets (GL_TEXTURE_1D, GL_TEXTURE_CUBE_MAP, etc). There are also texture units. In terms of our C/C++ example, what we have is this:

Object *g_objs[MAX_OBJECTS][MAX_LOCATIONS] = {NULL};
int g_currObject = 0;

void BindObject(int loc, Object *obj)
{
  g_objs[g_currObject][loc] = obj;
}

void ActiveObject(int currObject)
{
  g_currObject = currObject;
}

请注意,现在,我们不仅具有Object的2D列表,而且还具有当前对象的概念.我们有一个设置当前对象的函数,我们有一个最大数量的当前对象的概念,并且我们所有的对象操作函数都经过了调整,可以从当前对象中进行选择.

Notice that now, we not only have a 2D list of Objects, but we also have the concept of a current object. We have a function to set the current object, we have the concept of a maximum number of current objects, and all of our object manipulation functions are adjusted to select from the current object.

更改当前活动对象时,将更改整个目标位置集.因此,您可以绑定进入当前对象0的对象,切换到当前对象4,并将修改完全不同的对象.

When you change the currently active object, you change the entire set of target locations. So you can bind something that goes into current object 0, switch to current object 4, and will be modifying a completely different object.

这种与纹理对象的类比非常完美……

This analogy with texture objects is perfect... almost.

请参见,glActiveTexture不是整数.它需要一个枚举器.从理论上讲,这意味着可以接受从GL_TEXTURE0GL_TEXTURE31的所有内容.但是您必须了解一件事:

See, glActiveTexture does not take an integer; it takes an enumerator. Which in theory means that it can take anything from GL_TEXTURE0 to GL_TEXTURE31. But there's one thing you must understand:

这是错误的!

glActiveTexture可以采用的实际范围由GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS控制.那是一个实现允许的同时多重纹理的最大数量.这些分别针对不同的着色器阶段分为不同的分组.例如,在GL 3.x类硬件上,您可以获得16个顶点着色器纹理,16个片段着色器纹理和16个几何着色器纹理.因此,GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS将为48.

The actual range that glActiveTexture can take is governed by GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS. That is the maximum number of simultaneous multitextures that an implementation allows. These are each divided up into different groupings for different shader stages. For example, on GL 3.x class hardware, you get 16 vertex shader textures, 16 fragment shader textures, and 16 geometry shader textures. Therefore, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS will be 48.

但是没有48个枚举器.这就是为什么glActiveTexture并没有真正使用枚举数的原因.呼叫glActiveTexture正确方法如下:

But there aren't 48 enumerators. Which is why glActiveTexture doesn't really take enumerators. The correct way to call glActiveTexture is as follows:

glActiveTexture(GL_TEXTURE0 + i);

其中i是介于0和GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS之间的数字.

where i is a number between 0 and GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS.

那么所有这些与渲染有什么关系?

So what does all of this have to do with rendering?

使用着色器时,可以将采样器制服设置为纹理图像单位(glUniform1i(samplerLoc, i),其中i是图像单位).这表示您与glActiveTexture一起使用的数字.采样器将根据采样器类型选择目标.因此,sampler2D将从GL_TEXTURE_2D目标中选择.这就是采样器具有不同类型的原因之一.

When using shaders, you set your sampler uniforms to a texture image unit (glUniform1i(samplerLoc, i), where i is the image unit). That represents the number you used with glActiveTexture. The sampler will pick the target based on the sampler type. So a sampler2D will pick from the GL_TEXTURE_2D target. This is one reason why samplers have different types.

现在,这听起来令人怀疑,就像您可以拥有两个GLSL采样器一样,它们的 types 不同,它们使用相同的纹理图像单元.但是你不能; OpenGL禁止这样做,并且在尝试渲染时会给您一个错误.

Now this sounds suspiciously like you can have two GLSL samplers, with different types that use the same texture image unit. But you can't; OpenGL forbids this and will give you an error when you attempt to render.

这篇关于glActiveTexture和glBindTexture之间的区别和关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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