如何在java(endian)中渲染GL_SHORT?

问题描述 投票:1回答:1

我正在使用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为良好测量)之后进行标准化和非规范化。这给了我正确的结果,但感觉非常hacky。有没有正确的方法来呈现和解析签名的16位通过Java?

这是基本代码:

    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();
    }
java opengl endianness short
1个回答
1
投票

问题是由纹理的内部格式引起的。

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位有符号整数数据格式 - 请参阅glTexImage3DGL_R16_SNORM在接口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_SNORMGL_R8_SNORM实现了接口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浮点格式:

EG

gl2.glTexImage3D(GL2.GL_TEXTURE_3D, 0, GL2.GL_R16F,
                 nCols, nRows, nSlices, 0, GL2.GL_RED, GL.GL_SHORT, data);
© www.soinside.com 2019 - 2024. All rights reserved.