gpt4 book ai didi

opengl - glActiveTexture 和 glBindTexture 的区别和关系

转载 作者:行者123 更新时间:2023-12-03 04:30:27 47 4
gpt4 key购买 nike

据我所知,glActiveTexture设置事件的“纹理单元”。每个纹理单元可以有多个纹理目标(通常是 GL_TEXTURE_1D、2D、3D 或 CUBE_MAP)。

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

可用纹理单元的数量取决于系统。我在我的库中看到了多达 32 个的枚举。我想这基本上意味着我可以在任何时候在 GPU 内存中拥有 GPU 的限制(我认为是 16 8 个)和 32 个纹理中的较小者?我想还有一个额外的限制,即我不超过 GPU 的最大内存(假设为 1 GB)。

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

接下来,您通常要加载纹理。您可以通过 glTexImage2D 执行此操作.其中的第一个参数是纹理目标。如果这个 works like glBufferData ,然后我们本质上将“句柄”/“纹理名称”绑定(bind)到纹理目标,然后将纹理数据加载到该目标中,从而间接将其与该句柄相关联。

怎么样glTexParameter ?我们必须绑定(bind)一个纹理目标,然后再次选择相同的目标作为第一个参数?还是只要我们有正确的事件纹理单元就不需要绑定(bind)纹理目标?
glGenerateMipmap也对目标进行操作...该目标仍必须绑定(bind)到纹理名称才能成功?

那么当我们想要绘制带有纹理的对象时,我们是否必须同时选择一个事件纹理单元,然后选择一个纹理目标?还是我们选择一个纹理单元,然后我们可以从与该单元关联的 4 个目标中的任何一个获取数据?这是真正让我感到困惑的部分。

最佳答案

所有关于 OpenGL 对象

OpenGL 对象的标准模型如下。

对象有状态。将它们视为 struct .所以你可能有一个像这样定义的对象:

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

该对象具有存储在其中的某些值并且具有状态。 OpenGL 对象也有状态。

改变状态

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

在 OpenGL 中,您不会这样做。

出于遗留原因最好不要解释,要更改 OpenGL 对象的状态,您必须首先将其绑定(bind)到上下文。这是通过来自 glBind* 的一些文件完成的。打电话。

与此等效的 C/C++ 如下:
Object *g_objs[MAX_LOCATIONS] = {NULL};    
void BindObject(int loc, Object *obj)
{
g_objs[loc] = obj;
}

纹理很有趣;它们代表了一种特殊的绑定(bind)情况。许多 glBind*调用有一个“目标”参数。这表示 OpenGL 上下文中可以绑定(bind)该类型对象的不同位置。例如,您可以绑定(bind)一个帧缓冲区对象用于读取( GL_READ_FRAMEBUFFER )或用于写入( GL_DRAW_FRAMEBUFFER )。这会影响 OpenGL 使用缓冲区的方式。这是什么 loc上面的参数代表。

纹理很特别,因为当您第一次将它们绑定(bind)到目标时,它们会获得特殊信息。当您第一次将纹理绑定(bind)为 GL_TEXTURE_2D 时,您实际上是在纹理中设置特殊状态。你是说这个纹理是一个 2D 纹理。它永远是 2D 纹理;这种状态永远无法改变。如果您的纹理首先绑定(bind)为 GL_TEXTURE_2D ,您必须始终将其绑定(bind)为 GL_TEXTURE_2D ;试图将其绑定(bind)为 GL_TEXTURE_1D会引起错误(在运行时)。

一旦对象被绑定(bind),它的状态就可以改变。这是通过特定于该对象的通用函数完成的。它们也采用代表要修改的对象的位置。

在 C/C++ 中,这看起来像:
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;
}
}

注意这个函数如何设置当前绑定(bind)中的任何内容 loc值(value)。

对于纹理对象,主要的纹理状态变化函数是 glTexParameter .唯一改变纹理状态的其他函数是 glTexImage 函数及其变体( glCompressedTexImage glCopyTexImage 、最近的 glTexStorage )。各种 SubImage版本会更改纹理的内容,但在技术上不会更改其状态。 Image函数分配纹理存储并设置纹理的格式; SubImage函数只是复制周围的像素。这不被视为纹理的状态。

请允许我重复一遍:这些是 只有修改纹理状态的函数。 glTexEnv修改环境状态;它不会影响存储在纹理对象中的任何内容。

事件纹理

纹理的情况更加复杂,同样出于遗留原因,最好不要公开。这是 glActiveTexture 进来。

对于纹理,不仅有目标( GL_TEXTURE_1DGL_TEXTURE_CUBE_MAP 等)。还有纹理单元。就我们的 C/C++ 示例而言,我们拥有的是:
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 的二维列表。 s,但我们也有当前对象的概念。我们有一个函数来设置当前对象,我们有当前对象的最大数量的概念,我们所有的对象操作函数都被调整为从当前对象中选择。

当您更改当前事件对象时,您将更改整个目标位置集。所以你可以绑定(bind)一些进入当前对象 0 的东西,切换到当前对象 4,并且将修改一个完全不同的对象。

这种与纹理对象的类比是完美的......几乎。

见, glActiveTexture不取整数;它需要一个枚举器。这在理论上意味着它可以从 GL_TEXTURE0 中获取任何东西。至 GL_TEXTURE31 .但是你必须明白一件事:

这是假的!
glActiveTexture的实际范围可以服用受 GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS管辖.这是实现允许的最大同时多纹理数。对于不同的着色器阶段,它们每个都分为不同的组。例如,在 GL 3.x 类硬件上,您将获得 16 个顶点着色器纹理、16 个片段着色器纹理和 16 个几何着色器纹理。因此, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS将是 48。

但是没有 48 个枚举器。这就是为什么 glActiveTexture并不真正需要枚举器。 正确 拨打方式 glActiveTexture如下:
glActiveTexture(GL_TEXTURE0 + i);

哪里 i是介于 0 和 GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 之间的数字.

渲染

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

使用着色器时,将采样器统一设置为纹理图像单元( glUniform1i(samplerLoc, i) ,其中 i 是图像单元)。那代表您与 glActiveTexture 一起使用的数字.采样器将根据采样器类型选择目标。所以一个 sampler2D将从 GL_TEXTURE_2D 中挑选目标。这是采样器具有不同类型的原因之一。

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

关于opengl - glActiveTexture 和 glBindTexture 的区别和关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8866904/

47 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com