我有两个GL_RGBA32UI FBO纹理,用于存储每个纹理的粒子位置/速度的当前状态。
第一次我只填写了一次这样的数据:
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的纹理,并渲染到第二个)如下。
顶点着色器:
#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);
}碎片着色器:
#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):
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();
}发布于 2022-03-03 17:11:37
如果您正在读取每个组件的32位纹理,则需要一个highp取样器,并且需要将结果存储在一个highp变量中。
目前,您正在为usample2D指定一个usample2D,默认的int精度也是mediump。对于整数,mediump被指定为“至少”16位,因此其中任何一个都可能导致您的32位值被截断。
请注意“至少”--实现以更高的精度存储它是合法的--因此您可能会发现“它碰巧在某些实现(比如模拟器)上工作”,因为该实现选择使用更广泛的类型。
https://stackoverflow.com/questions/71336862
复制相似问题