我试图创建一个不可变的纹理与glTexImage2D()
,然后我可以使用glBindImageTexture()
绑定
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