【问题标题】:Loading generated texture data is inconclusive in Libgdx/Lwjgl在 Libgdx/Lwjgl 中加载生成的纹理数据是不确定的
【发布时间】:2021-07-21 16:27:00
【问题描述】:

以下数据格式:

final int width = 256;
final int height = 256;
final float[][][] data = new float[width][height][4];
FloatBuffer dataBuf;
int textureHandle;
FrameBuffer testFrame;
@Override
public void create () {
    for (int i = 0; i < width; i++) {
        for (int j = 0; j < height; j++) {
            data[i][j][0] = 0.4f; /* r */
            data[i][j][1] = 0.38f; /* g */
            data[i][j][2] = 0.2f; /* b */
            data[i][j][3] = 0.9f; /* a */
        }
    }
    dataBuf = ByteBuffer.allocateDirect( Float.BYTES * 4 * width * height ).asFloatBuffer();
    for (float[][] dat : data) { /* Float Byte size * RGBA * width * height */
        for (float[] floats : dat) {
            dataBuf.put(floats, 0, 4);
        }
    }
    dataBuf.position(0); /* reset the caret position to the beginning of the array */
    textureHandle = Gdx.gl.glGenTexture();
    Gdx.gl.glActiveTexture(GL20.GL_TEXTURE1);
    Gdx.gl.glBindTexture(GL30.GL_TEXTURE_2D, textureHandle);
    Gdx.gl.glTexParameteri(GL30.GL_TEXTURE_2D, GL30.GL_TEXTURE_MIN_FILTER, GL30.GL_NEAREST);
    Gdx.gl.glTexParameteri(GL30.GL_TEXTURE_2D, GL30.GL_TEXTURE_MAG_FILTER, GL30.GL_LINEAR);
    Gdx.gl.glTexImage2D(
        GL30.GL_TEXTURE_2D, 0, GL30.GL_RGBA32F,
        width, height, 0, GL30.GL_RGBA, GL30.GL_FLOAT, dataBuf
    );
}

着色器的行为正确,因为它们已使用帧缓冲区对象进行测试,并且它们显示帧缓冲区的正确内容。

但是当生成的纹理被渲染时,它似乎偏离了原始的颜色/值。 在大多数情况下,FloatBuffers 提供的值会导致黑色纹理,有时会出现意想不到的颜色(例如,石灰绿色而不是米色)。

不幸的是,我无法使用glPixelStorei,因为该界面缺少大部分参数。但无论如何glGetError 总是返回0,所以我怀疑数据以某种方式错误地编译到dataBuf 字节流中。

这可能是什么问题?

编辑:一些调试细节:

  • glGetError() 始终为零
  • 各个组件似乎对数据有一个粗略的了解,但大多数值都会产生黑色纹理:
    • r: 1.0f, g: 1.0f, b: 1.0f, a: 1.0f --> 黑屏
    • r: 0.9f, g: 0.9f, b: 0.9f, a: 0.9f --> 白屏
    • r: 0.9f, g: 0.0f, b: 0.0f, a: 0.9f --> 红屏
    • r: 0.0f, g: 0.9f, b: 0.0f, a: 0.9f --> 绿屏
    • r: 0.0f, g: 0.0f, b: 0.9f, a: 0.9f --> 蓝屏
    • r: 0.5f, g: 0.5f, b: 0.5f, a: 0.5f --> 黑屏
    • r: 0.4f, g: 0.32f, b: 0.2f, a: 0.9f --> 绿屏
  • 以上我怀疑是因为上传纹理时dataBuf和openGL-s GL_FLOAT中的浮点值之间存在转换错误
  • 否则,着色器和设置工作正常,因为它已使用帧缓冲区的颜色附件进行测试,并且在所有上述值下都可以正常工作。不同的是颜色纹理不是手动生成的,而是通过glClear(GL_COLOR_BUFFER_BIT);渲染到帧缓冲区中的
  • 使用整数缓冲区也可以按预期工作(整数数组,值 0-255):
        dataBuf.position(0);
        Gdx.gl.glTexImage2D(
            GL30.GL_TEXTURE_2D, 0, GL30.GL_RGBA,
            width, height, 0, GL30.GL_RGBA, GL30.GL_UNSIGNED_INT, dataBuf
        );
  • LWJGL3 后端存在相同的行为

【问题讨论】:

  • “使用整数缓冲区也按预期工作(整数数组,值 0-255)”嗯,没有。当您使用带有GL_UNSIGNED_INT 格式数据的GL_RGBA 内部vormat 时,访问它时,范围应为04294967295 映射到标准化浮点范围[0,1]。当您使用[0,255] 输入范围时,所有内容都应该与黑色没有区别。
  • 好吧,不管它应该是什么,它在 0 - 255 的值下都能正常工作;我也有你的期望,但在我的机器上它不起作用,如果你认为这会有所帮助,我可以将完整的示例上传到 github。

标签: opengl libgdx buffer textures lwjgl


【解决方案1】:

我能够使用给定的代码复制问题,并且可以通过一行更改来解决。您的 FloatBuffer 默认为 big-endian 字节顺序,它看起来像 libGDX、LWJGL 和/或 OpenGL 期望 little-endian。我在这里把你的例子变成了一个可执行的测试用例:https://github.com/yellowstonegames/SquidLib/blob/master/squidlib/src/test/java/squidpony/gdx/tests/issues/Issue6516.java#L37(测试用例不依赖于整个库,它只是在一个已经依赖于 libGDX 并且有可用资产的项目中测试 libGDX 问题很方便) .我的解决办法是改变:

dataBuf = ByteBuffer.allocateDirect(Float.BYTES * 4 * width * height).asFloatBuffer();

到:

dataBuf = ByteBuffer.allocateDirect(Float.BYTES * 4 * width * height).order(ByteOrder.LITTLE_ENDIAN).asFloatBuffer();

看起来你所拥有的一切都是正确的;当我绘制该纹理时,我得到了预期的泥褐色,而不是石灰绿色。

【讨论】:

  • 您也可以使用 libgdx BufferUtils.newFloatBuffer(...) 代替,它们的作用相同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多