加载生成的纹理数据在 Libgdx/Lwjgl 中尚无定论
Loading generated texture data is inconclusive in Libgdx/Lwjgl
以下数据格式:
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
);
}
着色器运行正确,因为它们使用帧缓冲区对象进行了测试,并且它们显示了帧缓冲区的正确内容。
但是生成的贴图渲染出来的时候,好像和原来的有偏差color/value。
在大多数情况下,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 后端存在相同的行为
我可以用给定的代码重现这个问题,并且可以通过一行更改来解决。您的 FloatBuffer 默认为大端字节顺序,看起来 libGDX、LWJGL、and/or OpenGL 期望小端字节序。我在这里将你的例子变成了一个可执行的测试用例: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();
看起来你的其他一切都是正确的;当我绘制该纹理时,我得到了预期的泥棕色,而不是柠檬绿。
以下数据格式:
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
);
}
着色器运行正确,因为它们使用帧缓冲区对象进行了测试,并且它们显示了帧缓冲区的正确内容。
但是生成的贴图渲染出来的时候,好像和原来的有偏差color/value。
在大多数情况下,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 后端存在相同的行为
我可以用给定的代码重现这个问题,并且可以通过一行更改来解决。您的 FloatBuffer 默认为大端字节顺序,看起来 libGDX、LWJGL、and/or OpenGL 期望小端字节序。我在这里将你的例子变成了一个可执行的测试用例: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();
看起来你的其他一切都是正确的;当我绘制该纹理时,我得到了预期的泥棕色,而不是柠檬绿。