【问题标题】:OpenGL ES 3.1 - Unable to create IMMUTABLE Textures with glTexImage2DOpenGL ES 3.1 - 无法使用 glTexImage2D 创建 IMMUTABLE 纹理
【发布时间】:2016-11-02 18:12:54
【问题描述】:

我正在尝试使用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,&amp;status) 的结果是0,这意味着纹理不是不可变

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

关于我做错了什么有什么想法吗?

提前致谢;)

编辑:

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

glTexStorage2D() 人 (khronos documentation) 的这一段让我很困惑:

glTexStorage2D 的行为取决于目标参数。当target为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 的值可以通过调用 pname 设置为 GL_TEXTURE_IMMUTABLE_FORMAT 的 glGetTexParameter 来发现。不能对纹理对象的尺寸或格式进行进一步更改。使用任何可能改变纹理对象的尺寸或格式的命令(例如 glTexImage2D 或对 glTexStorage2D 的其他调用)将导致生成 GL_INVALID_OPERATION 错误,即使它实际上不会改变纹理对象的尺寸或格式。目的。

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

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

【问题讨论】:

    标签: c++ textures immutability glteximage2d opengl-es-3.1


    【解决方案1】:

    要分配不可变纹理存储,请使用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()的规范没有提到改变值,所以它仍然是假的。

    【讨论】:

    • 感谢您的快速回复,但实际上,我正在尝试使用glTexImage2D() 代替glTexStorage2D()。确实,当我使用glTexStorage2D() 创建纹理然后绑定它时,我没有收到任何错误,但似乎在图像上写入或执行原子操作没有任何效果。所以,我认为这可能是因为纹理没有正确加载。你认为这可能是我的问题的原因还是我看错了方向?注:根据规范,像我一样使用glTexImage2D() 相当于glTexStorage2D()。提前致谢!
    • @ElouarnLaine:只有两种方法可以创建具有不可变存储的纹理:glTexStorageglTextureView。 “根据规范,像我一样使用glTexImage2D()相当于glTexStorage2D()。” 根据什么规范?因为 ES 3.1 规范非常明确 glTexStorage2D 设置不可变状态,而 glTexImage2D 没有。
    • @NicolBolas: 在glTexStorage2D() 部分的khronos documentation 上:“glTexStorage2D 的行为取决于目标参数。当目标是 GL_TEXTURE_2D 时,调用 glTexStorage2D 是等效的,假设没有错误生成,执行下面的伪代码...”。我的问题是:我们可以使用glBindImageTexture() 绑定使用glTexImage2D() 创建的纹理吗?
    • @ElouarnLaine: 1) Khronos 文档不是规范。 2)文档页面说GL_TEXTURE_IMMUTABLE_FORMAT被该函数设置为true。所以它清楚地解释了它与glTexImage2D的不同之处。
    • @NicolBolas:很抱歉我的不准确之处(我还是 Opengl 的新手)。实际上,我仍然不清楚以下段落是关于glTexImage2D() 还是glTexStorage2D():“由于实际上没有提供纹理数据,因此伪代码中使用的值用于 [...]事实上,不会改变对象的尺寸或格式。”(我以为他们在谈论glTexImage2D()
    猜你喜欢
    • 1970-01-01
    • 2012-04-09
    • 1970-01-01
    • 2018-07-12
    • 1970-01-01
    • 2014-04-22
    • 1970-01-01
    • 2017-03-19
    • 1970-01-01
    相关资源
    最近更新 更多