Reputation: 3255
The following data format:
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
);
}
The Shaders are behaving correctly, as they were tested with Framebuffer objects, and they display the correct contents of the Framebuffers.
However when the generated texture is rendered, it seems to deviate from the original color/value.
In most cases the values provided by the FloatBuffers
result in a black texture, sometimes there is an unexpected color(e.g. lime-green instead of beige).
Unfortunately I couldn't play with glPixelStorei
much, because the interface is missing most of its parameters. But in any case glGetError
is always returning with 0, so I suspect the data is somehow incorrectly compiled into the dataBuf
byte-stream.
What could be the problem here?
Edit: Some debugging details:
glGetError()
is always zerodataBuf
and openGL-s GL_FLOAT when uploading the textureglClear(GL_COLOR_BUFFER_BIT);
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
);
Upvotes: 2
Views: 187
Reputation: 88
I am able to replicate the issue with the given code, and it can be fixed with a one-line change. Your FloatBuffer defaults to big-endian byte order, and it looks like libGDX, LWJGL, and/or OpenGL expect little-endian. I made your example into an executable test case here: https://github.com/yellowstonegames/SquidLib/blob/master/squidlib/src/test/java/squidpony/gdx/tests/issues/Issue6516.java#L37 (the test case doesn't depend on the library as a whole, it just is handy to test libGDX issues in a project that already depends on libGDX and has assets available). My fix is to change:
dataBuf = ByteBuffer.allocateDirect(Float.BYTES * 4 * width * height).asFloatBuffer();
to:
dataBuf = ByteBuffer.allocateDirect(Float.BYTES * 4 * width * height).order(ByteOrder.LITTLE_ENDIAN).asFloatBuffer();
It looks like everything else you had is correct; I get the intended muddy brown color when I draw that texture, instead of lime green.
Upvotes: 1