OpenGL ES 3.1 -无法用glTexImage2D创建不可变纹理

OpenGL ES 3.1 - Unable to create IMMUTABLE Textures with glTexImage2D

本文关键字:glTexImage2D 创建 不可变 纹理 ES OpenGL      更新时间:2023-10-16

我试图创建一个不可变的纹理与glTexImage2D(),然后我可以使用glBindImageTexture()绑定

下面是我的c++代码:
GLuint id;
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);

GLint width = 2046;
GLint height = 1086;
// Not sure what to put here 1, 2, 4 or 8 ?
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
GLint levels;
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, &levels);
for (int i = 0; i < levels + 1; i++)
{
    glTexImage2D(GL_TEXTURE_2D, i, GL_R32UI, width, height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL);
    width = glm::max(1, (width / 2));
    height = glm::max(1, (height / 2));
    // check OpenGL error
    GLenum err;
    while ((err = glGetError()) != GL_NO_ERROR) {
        ALOGE("ERROR_GL_TEXTURE_INIT: %i", err);
    }
}
GLint status;
glGetTexParameteriv(GL_TEXTURE_2D,GL_TEXTURE_IMMUTABLE_FORMAT,&status);
ALOGE("IMMUTABLE_TEXTURE: %i", status);
glBindTexture(GL_TEXTURE_2D, 0);
glBindImageTexture(0, id, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
// check OpenGL error
GLenum err;
while ((err = glGetError()) != GL_NO_ERROR) {
    ALOGE("ERROR_GL_TEXTURE_IMG-USE: %i", err);
}

由于我不需要Mipmap级别,我将GL_TEXTURE_MAX_LEVEL设置为0
然后我调用glTexImage2D()来设置所有纹理的级别(这里只有一个),我没有错误。

不幸的是,
glGetTexParameteriv(GL_TEXTURE_2D,GL_TEXTURE_IMMUTABLE_FORMAT,&status)的结果是0,这意味着纹理不是不可变的

现在,当我尝试调用glBindImageTexture()时,错误1282被引发,因为它是在khronos文档中编写的,这个opengl函数需要一个不可变的纹理。

你知道我哪里做错了吗?

提前感谢;)

EDIT:

感谢你们两位的时间和提供的所有信息,但有些事情我不明白。

glTexStorage2D() man (khronos文档)的这一段让我感到困惑:

glTexStorage2D的行为取决于目标参数。当目标是GL_TEXTURE_2D时,调用glTexStorage2D相当于执行以下伪代码,假设没有生成错误:

for (i = 0; i < levels; i++)
{
    glTexImage2D(target, i, internalformat, width, height, 0, format, type, NULL);
    width = max(1, (width / 2));
    height = max(1, (height / 2));
}

由于实际上没有提供纹理数据,因此pseudo-code中用于格式和类型的值是不相关的,可以认为是所选内部格式枚举的任何合法值。internalformat必须是表1中给出的大小的内部格式之一,或者是下面表2中给出的压缩内部格式之一。设置成功后,"GL_TEXTURE_IMMUTABLE_FORMAT"的值变为"GL_TRUE"。GL_TEXTURE_IMMUTABLE_FORMAT的值可以通过调用glGetTexParameter (pname设置为GL_TEXTURE_IMMUTABLE_FORMAT)来发现。不能对纹理对象的尺寸或格式进行进一步更改。使用任何可能改变纹理对象的尺寸或格式的命令(例如glTexImage2D或对glTexStorage2D的另一个调用)将导致生成GL_INVALID_OPERATION错误,即使它实际上不会改变对象的尺寸或格式。

我仍然不清楚上面的段落是关于glTexImage2D()还是glTexStorage2D()

此外,我的潜在问题是:我们可以使用glBindImageTexture()绑定glTexImage2D()创建的纹理吗?(我看到了这两个函数实际一起使用的代码示例,例如这里)

要分配不可变的纹理存储,请使用glTexStorage2D()而不是glTexImage2D()。所以你分配纹理内存的调用变成:

glTexStorage2D(GL_TEXTURE_2D, levels, GL_R32UI, width, height);

在这个例子中,你用这个调用分配了所有的mipmap级别,所以你不需要当前的循环。

还有,我不确定你对这个的期望是什么:

GLint levels;
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, &levels);

在你的代码中,你只是创建了纹理,当你做这个调用。所以查询层数是没有意义的。如果你想要一个mipmap纹理,你必须根据大小计算你需要的mipmap的数量。如果不需要mipmapping,只需将第二个参数1传递给glTexStorage2D()


因为有一些后续的问题是否有其他方法来创建一个不可变的纹理,例如与glTexImage2D(),答案是否定的。ES 3.1规范的第8.17节"不可变格式纹理图像",从第190页开始,解释了如何创建不可变纹理。该部分中列出的唯一调用是glTexStorage2D()glTexStorage3D()。它还特别提到,这些调用将GL_TEXTURE_IMMUTABLE_FORMAT属性设置为true。

唯一提到它创建不可变纹理的调用是171页8.8节的glTexStorage2DMultisample()

这意味着glTexImage2D()创建的纹理不是不可变。确认这一点是在第194页的8.18节标题为"纹理状态",其中列出了各种纹理属性的默认值:

初始状态下,[…]TEXTURE_IMMUTABLE_FORMAT的值为FALSE。

由于glTexImage2D()的规范没有提到改变值,所以它将保持false