首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法在GL_RGBA32UI ES上写入OpenGL FBO纹理

无法在GL_RGBA32UI ES上写入OpenGL FBO纹理
EN

Stack Overflow用户
提问于 2022-03-03 12:00:39
回答 1查看 101关注 0票数 0

我有两个GL_RGBA32UI FBO纹理,用于存储每个纹理的粒子位置/速度的当前状态。

第一次我只填写了一次这样的数据:

代码语言:javascript
复制
Gdx.gl.glTexImage2D(GL20.GL_TEXTURE_2D, 0, GL30.GL_RGBA32UI, width, height, 0, GL30.GL_RGBA_INTEGER, GL20.GL_UNSIGNED_INT, buffer);

每个渲染循环,第二个被写入通过一个着色器,而第一个被用作纹理和第二个作为目标。我这样做的方法是在[-1, -1][textureSize, textureSize]之间设置视图端口时,从[0, 0][textureSize, textureSize]绘制一个四角图。这样,在片段着色器中,我有一个每个纹理的着色器运行。每次运行时,我都会将第一个纹理作为输入,更新它并将其写入第二个纹理。

然后,我使用不同的着色器和网格将第二个FBO的纹理呈现到屏幕上,其中每个纹理将由网格中的一个顶点表示。通过这种方法,我可以从纹理中提取粒子位置,并相应地在顶点着色器中设置gl_Position

之后,我切换第一个和第二个FBO,并继续下一个呈现循环。这意味着这两个FBO被用作基于GPU的呈现数据存储。

在桌面应用程序上,甚至在安卓仿真器中都能很好地工作。然而,它在真正的Android设备上失败了:第二个FBO的特定循环的纹理总是值,,,只在真正的Android设备上更新之后。不过,当只呈现来自第一个缓冲区的数据时,它完全可以正常工作。

有什么想法吗?

我的更新着色器(获取第一个FBO的纹理,并渲染到第二个)如下。

顶点着色器:

代码语言:javascript
复制
#version 300 es

precision mediump float;

in vec2 a_vertex;
out vec2 v_texCoords;

void main()
{
    v_texCoords = a_vertex / 2.0 + 0.5;
    gl_Position = vec4(a_vertex, 0, 1);
}

碎片着色器:

代码语言:javascript
复制
#version 300 es

precision mediump float;
precision mediump usampler2D;

uniform usampler2D u_positionTexture;
uniform float u_delta;

in vec2 v_texCoords;
out uvec4 fragColor;

void main()
{
    uvec4 position_raw = texture(u_positionTexture, v_texCoords);

    vec2 position = vec2(
        uintBitsToFloat(position_raw.x),
        uintBitsToFloat(position_raw.y)
    );
    vec2 velocity = vec2(
        uintBitsToFloat(position_raw.z),
        uintBitsToFloat(position_raw.w)
    );

    // Usually I would alter position and velocity vector here and write it back
    // like this:
    // position += (velocity * u_delta);
    //
    // fragColor = uvec4(
    //  floatBitsToUint(position.x),
    //  floatBitsToUint(position.y),
    //  floatBitsToUint(velocity.x),
    //  floatBitsToUint(velocity.y));

    // Even with this the output is 0 on all channels:
    fragColor = uvec4(
        floatBitsToUint(50.0),
        floatBitsToUint(50.0),
        floatBitsToUint(0.0),
        floatBitsToUint(0.0));

    // Even writing the input directly would not make the correct values appear in the texture pixels:
    // fragColor = position_raw;
}

如何更新纹理(从fbo1到fbo2):

代码语言:javascript
复制
private void updatePositions(float delta) {
  fbo2.begin();
  updateShader.bind();
  Gdx.gl20.glViewport(0, 0, textureSize, textureSize);
  fbo1.getColorBufferTexture().bind(0);
  updateShader.setUniformf("u_delta", delta);
  updateShader.setUniformi("u_positionTexture", 0);
  Gdx.gl20.glDisable(GL20.GL_BLEND);
  Gdx.gl20.glBlendFunc(GL20.GL_ONE, GL20.GL_ZERO);
  updateMesh.render(updateShader, GL20.GL_TRIANGLE_STRIP);
  fbo2.end();
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-03-03 17:11:37

如果您正在读取每个组件的32位纹理,则需要一个highp取样器,并且需要将结果存储在一个highp变量中。

目前,您正在为usample2D指定一个usample2D,默认的int精度也是mediump。对于整数,mediump被指定为“至少”16位,因此其中任何一个都可能导致您的32位值被截断。

请注意“至少”--实现以更高的精度存储它是合法的--因此您可能会发现“它碰巧在某些实现(比如模拟器)上工作”,因为该实现选择使用更广泛的类型。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71336862

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档