如何在 java(字节序)中呈现 GL_SHORT?
How to render GL_SHORT in java (endian)?
我正在使用 com.jogamp.opengl.GL2
在屏幕外渲染短裤的 3d 纹理,然后通过 glReadPixels
解析结果。当我的 3d 纹理值都是正值时,结果就是我所期望的。但是当我有负值时,我无法弄清楚如何配置 opengl 以给出正确的结果。我试过 glPixelStorei(GL2.GL_PACK_SWAP_BYTES, 1);
和 glPixelStorei(GL2.GL_UNPACK_SWAP_BYTES, 1);
。 GL_PACK/UNPACK_SWAP_BYTES 的全部 4 种组合我都试过了,结果都不正确。
数据跨度从 -1024 到 +1024(或大约该范围),因此作为替代方案,我在(+4096 然后 -4096 之后)进行归一化和非归一化。这给了我正确的结果,但感觉真的很糟糕。是否有正确的方法来通过 java 呈现和解析带符号的 16 位?
基本代码如下:
private int upload3DTexture(GL2 gl2, ShortBuffer data)
{
int texName[] = new int[1];
gl2.glPixelStorei(GL2.GL_PACK_ALIGNMENT, 2);
gl2.glPixelStorei(GL2.GL_UNPACK_ALIGNMENT, 2);
gl2.glPixelStorei(GL2.GL_PACK_SWAP_BYTES, 1);
gl2.glPixelStorei(GL2.GL_UNPACK_SWAP_BYTES, 1);
gl2.glGenTextures(1, texName, 0);
gl2.glEnable(GL2.GL_TEXTURE_3D);
gl2.glBindTexture(GL2.GL_TEXTURE_3D, texName[0]);
gl2.glTexParameteri(GL2.GL_TEXTURE_3D, GL2.GL_TEXTURE_WRAP_S, GL2.GL_CLAMP_TO_BORDER);
gl2.glTexParameteri(GL2.GL_TEXTURE_3D, GL2.GL_TEXTURE_WRAP_T, GL2.GL_CLAMP_TO_BORDER);
gl2.glTexParameteri(GL2.GL_TEXTURE_3D, GL2.GL_TEXTURE_WRAP_R, GL2.GL_CLAMP_TO_BORDER);
gl2.glTexParameteri(GL2.GL_TEXTURE_3D, GL2.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
gl2.glTexParameteri(GL2.GL_TEXTURE_3D, GL2.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
gl2.glTexEnvi(GL2.GL_TEXTURE_3D, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_MODULATE);
((java.nio.Buffer)data).rewind();
gl2.glTexImage3D(GL2.GL_TEXTURE_3D, 0, GL2.GL_R16, nCols, nRows, nSlices, 0, GL2.GL_RED, GL.GL_SHORT, data);
return texName[0];
}
private int upload3DTexture(GL2 gl2, ShortBuffer data)
{
int texName[] = new int[1];
gl2.glPixelStorei(GL2.GL_PACK_ALIGNMENT, 2);
gl2.glPixelStorei(GL2.GL_UNPACK_ALIGNMENT, 2);
gl2.glPixelStorei(GL2.GL_PACK_SWAP_BYTES, 1);
gl2.glPixelStorei(GL2.GL_UNPACK_SWAP_BYTES, 1);
gl2.glGenTextures(1, texName, 0);
gl2.glEnable(GL2.GL_TEXTURE_3D);
gl2.glBindTexture(GL2.GL_TEXTURE_3D, texName[0]);
gl2.glTexParameteri(GL2.GL_TEXTURE_3D, GL2.GL_TEXTURE_WRAP_S, GL2.GL_CLAMP_TO_BORDER);
gl2.glTexParameteri(GL2.GL_TEXTURE_3D, GL2.GL_TEXTURE_WRAP_T, GL2.GL_CLAMP_TO_BORDER);
gl2.glTexParameteri(GL2.GL_TEXTURE_3D, GL2.GL_TEXTURE_WRAP_R, GL2.GL_CLAMP_TO_BORDER);
gl2.glTexParameteri(GL2.GL_TEXTURE_3D, GL2.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
gl2.glTexParameteri(GL2.GL_TEXTURE_3D, GL2.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
gl2.glTexEnvi(GL2.GL_TEXTURE_3D, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_MODULATE);
((java.nio.Buffer)data).rewind();
gl2.glTexImage3D(GL2.GL_TEXTURE_3D, 0, GL2.GL_R16, nCols, nRows, nSlices, 0, GL2.GL_RED, GL.GL_SHORT, data);
return texName[0];
}
private short[] renderAndResolve() {
short[] volume= new short[64];
short index = 0;
for (int z = 0; z < 4; z++) {
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
volume[index] = (short)(-100*z + y);
index++;
}
}
}
ShortBuffer shortBuffer = ShortBuffer.wrap(volume);
texID = upload3DTexture(gl2, shortBuffer);
display();
ShortBuffer resultBuffer = ShortBuffer.allocate(nSlices * nRows);
resolve(resultBuffer, 4, 4);
return resolve.array();
}
private void resolveDisplay(ShortBuffer slice, int w, int h)
{
GL2 gl2 = drawable.getGL().getGL2(); // The object that contains all the OpenGL methods.
fbo.bind(gl2);
gl2.glReadBuffer(GL2.GL_COLOR_ATTACHMENT0);
((java.nio.Buffer)slice).rewind();
int xd = (frameWidth - w)/2;
int yd = (frameHeight - h)/2;
gl2.glReadPixels(xd, yd, w, h, GL2.GL_RED, GL2.GL_SHORT, slice);
fbo.unbind(gl2);
((java.nio.Buffer)slice).rewind();
}
问题是由纹理的内部格式引起的。
gl2.glTexImage3D(GL2.GL_TEXTURE_3D, 0, GL2.GL_R16,
nCols, nRows, nSlices, 0, GL2.GL_RED, GL.GL_SHORT, data);
纹理图像数据存储的内部格式GL_R16
不是单数格式,而是无符号整数16位格式。
我不知道您使用的是哪个 OpenGL 版本。
Desktop OpenGL 提供内部数据格式 GL_R16_SNORM
,这是一种 16 位有符号整数数据格式 - 请参阅 glTexImage3D
。
GL_R16_SNORM
is implemented in the interface GL2GL3
:
gl2.glTexImage3D(GL2.GL_TEXTURE_3D, 0, GL2GL3.GL_R16_SNORM,
nCols, nRows, nSlices, 0, GL2.GL_RED, GL.GL_SHORT, data);
OpenGL ES (3.0) 提供了一个单一的整数 8 位格式 GL_R8_SNORM
。
GL_R8_SNORM
is implemented interface GL2ES3
:
gl2.glTexImage3D(GL2.GL_TEXTURE_3D, 0, GL2ES3.GL_R8_SNORM,
nCols, nRows, nSlices, 0, GL2.GL_RED, GL.GL_SHORT, data);
作为替代方案,桌面 OpenGL 和 OpenGL ES 提供 16 位浮点格式:
例如
gl2.glTexImage3D(GL2.GL_TEXTURE_3D, 0, GL2.GL_R16F,
nCols, nRows, nSlices, 0, GL2.GL_RED, GL.GL_SHORT, data);
我正在使用 com.jogamp.opengl.GL2
在屏幕外渲染短裤的 3d 纹理,然后通过 glReadPixels
解析结果。当我的 3d 纹理值都是正值时,结果就是我所期望的。但是当我有负值时,我无法弄清楚如何配置 opengl 以给出正确的结果。我试过 glPixelStorei(GL2.GL_PACK_SWAP_BYTES, 1);
和 glPixelStorei(GL2.GL_UNPACK_SWAP_BYTES, 1);
。 GL_PACK/UNPACK_SWAP_BYTES 的全部 4 种组合我都试过了,结果都不正确。
数据跨度从 -1024 到 +1024(或大约该范围),因此作为替代方案,我在(+4096 然后 -4096 之后)进行归一化和非归一化。这给了我正确的结果,但感觉真的很糟糕。是否有正确的方法来通过 java 呈现和解析带符号的 16 位?
基本代码如下:
private int upload3DTexture(GL2 gl2, ShortBuffer data)
{
int texName[] = new int[1];
gl2.glPixelStorei(GL2.GL_PACK_ALIGNMENT, 2);
gl2.glPixelStorei(GL2.GL_UNPACK_ALIGNMENT, 2);
gl2.glPixelStorei(GL2.GL_PACK_SWAP_BYTES, 1);
gl2.glPixelStorei(GL2.GL_UNPACK_SWAP_BYTES, 1);
gl2.glGenTextures(1, texName, 0);
gl2.glEnable(GL2.GL_TEXTURE_3D);
gl2.glBindTexture(GL2.GL_TEXTURE_3D, texName[0]);
gl2.glTexParameteri(GL2.GL_TEXTURE_3D, GL2.GL_TEXTURE_WRAP_S, GL2.GL_CLAMP_TO_BORDER);
gl2.glTexParameteri(GL2.GL_TEXTURE_3D, GL2.GL_TEXTURE_WRAP_T, GL2.GL_CLAMP_TO_BORDER);
gl2.glTexParameteri(GL2.GL_TEXTURE_3D, GL2.GL_TEXTURE_WRAP_R, GL2.GL_CLAMP_TO_BORDER);
gl2.glTexParameteri(GL2.GL_TEXTURE_3D, GL2.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
gl2.glTexParameteri(GL2.GL_TEXTURE_3D, GL2.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
gl2.glTexEnvi(GL2.GL_TEXTURE_3D, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_MODULATE);
((java.nio.Buffer)data).rewind();
gl2.glTexImage3D(GL2.GL_TEXTURE_3D, 0, GL2.GL_R16, nCols, nRows, nSlices, 0, GL2.GL_RED, GL.GL_SHORT, data);
return texName[0];
}
private int upload3DTexture(GL2 gl2, ShortBuffer data)
{
int texName[] = new int[1];
gl2.glPixelStorei(GL2.GL_PACK_ALIGNMENT, 2);
gl2.glPixelStorei(GL2.GL_UNPACK_ALIGNMENT, 2);
gl2.glPixelStorei(GL2.GL_PACK_SWAP_BYTES, 1);
gl2.glPixelStorei(GL2.GL_UNPACK_SWAP_BYTES, 1);
gl2.glGenTextures(1, texName, 0);
gl2.glEnable(GL2.GL_TEXTURE_3D);
gl2.glBindTexture(GL2.GL_TEXTURE_3D, texName[0]);
gl2.glTexParameteri(GL2.GL_TEXTURE_3D, GL2.GL_TEXTURE_WRAP_S, GL2.GL_CLAMP_TO_BORDER);
gl2.glTexParameteri(GL2.GL_TEXTURE_3D, GL2.GL_TEXTURE_WRAP_T, GL2.GL_CLAMP_TO_BORDER);
gl2.glTexParameteri(GL2.GL_TEXTURE_3D, GL2.GL_TEXTURE_WRAP_R, GL2.GL_CLAMP_TO_BORDER);
gl2.glTexParameteri(GL2.GL_TEXTURE_3D, GL2.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
gl2.glTexParameteri(GL2.GL_TEXTURE_3D, GL2.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
gl2.glTexEnvi(GL2.GL_TEXTURE_3D, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_MODULATE);
((java.nio.Buffer)data).rewind();
gl2.glTexImage3D(GL2.GL_TEXTURE_3D, 0, GL2.GL_R16, nCols, nRows, nSlices, 0, GL2.GL_RED, GL.GL_SHORT, data);
return texName[0];
}
private short[] renderAndResolve() {
short[] volume= new short[64];
short index = 0;
for (int z = 0; z < 4; z++) {
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
volume[index] = (short)(-100*z + y);
index++;
}
}
}
ShortBuffer shortBuffer = ShortBuffer.wrap(volume);
texID = upload3DTexture(gl2, shortBuffer);
display();
ShortBuffer resultBuffer = ShortBuffer.allocate(nSlices * nRows);
resolve(resultBuffer, 4, 4);
return resolve.array();
}
private void resolveDisplay(ShortBuffer slice, int w, int h)
{
GL2 gl2 = drawable.getGL().getGL2(); // The object that contains all the OpenGL methods.
fbo.bind(gl2);
gl2.glReadBuffer(GL2.GL_COLOR_ATTACHMENT0);
((java.nio.Buffer)slice).rewind();
int xd = (frameWidth - w)/2;
int yd = (frameHeight - h)/2;
gl2.glReadPixels(xd, yd, w, h, GL2.GL_RED, GL2.GL_SHORT, slice);
fbo.unbind(gl2);
((java.nio.Buffer)slice).rewind();
}
问题是由纹理的内部格式引起的。
gl2.glTexImage3D(GL2.GL_TEXTURE_3D, 0, GL2.GL_R16, nCols, nRows, nSlices, 0, GL2.GL_RED, GL.GL_SHORT, data);
纹理图像数据存储的内部格式GL_R16
不是单数格式,而是无符号整数16位格式。
我不知道您使用的是哪个 OpenGL 版本。
Desktop OpenGL 提供内部数据格式 GL_R16_SNORM
,这是一种 16 位有符号整数数据格式 - 请参阅 glTexImage3D
。
GL_R16_SNORM
is implemented in the interface GL2GL3
:
gl2.glTexImage3D(GL2.GL_TEXTURE_3D, 0, GL2GL3.GL_R16_SNORM,
nCols, nRows, nSlices, 0, GL2.GL_RED, GL.GL_SHORT, data);
OpenGL ES (3.0) 提供了一个单一的整数 8 位格式 GL_R8_SNORM
。
GL_R8_SNORM
is implemented interface GL2ES3
:
gl2.glTexImage3D(GL2.GL_TEXTURE_3D, 0, GL2ES3.GL_R8_SNORM,
nCols, nRows, nSlices, 0, GL2.GL_RED, GL.GL_SHORT, data);
作为替代方案,桌面 OpenGL 和 OpenGL ES 提供 16 位浮点格式:
例如
gl2.glTexImage3D(GL2.GL_TEXTURE_3D, 0, GL2.GL_R16F,
nCols, nRows, nSlices, 0, GL2.GL_RED, GL.GL_SHORT, data);