JOGL中的交错数据

时间:2013-09-06 22:57:24

标签: java opengl jogl

我无法找到有关在JOGL中渲染交错顶点数组(而不是VBO)的正确方法的任何信息。具体来说,使用glVertexAttribPointer()似乎不允许在交错数据(FloatBuffer)中指定偏移量。在C,C ++或Objective-C中,我确切地知道如何做到这一点,但在Java中似乎没有明确的胜利之路。

我尝试过的唯一可能有效的方法是在使用glVertexAttribPointer()之前设置缓冲区的位置,但这没有效果。

为清楚起见,这里是渲染函数中的代码示例:

gl.glEnableVertexAttribArray( POSITION_ATTRIB );
gl.glEnableVertexAttribArray( NORMAL_ATTRIB );
gl.glVertexAttribPointer( POSITION_ATTRIB, 4, GL.GL_FLOAT, false, 32, vertexBuffer );
// vertexBuffer.position( 4 );  if I try to specify an offset
gl.glVertexAttribPointer( NORMAL_ATTRIB, 4, GL.GL_FLOAT, false, 32, vertexBuffer );
gl.glDrawArrays( GL.GL_TRIANGLES, 0, nummy );
gl.glDisableVertexAttribArray( NORMAL_ATTRIB );
gl.glDisableVertexAttribArray( POSITION_ATTRIB );

我为每个属性使用4个浮点数。我选择了基于

的32步

每个浮点数4个字节*每个属性4个浮点数*每个顶点2个属性。

2 个答案:

答案 0 :(得分:2)

我怀疑设置FloatBuffer位置的原因并不能为您提供所需的行为,因为您通过引用传递了FloatBuffer。您可能想要创建另一个FloatBuffer,它基本上只是相同数据的不同视图(例如,包装一个float [])并将此其他 FloatBuffer中的位置设置为4 ...

例如:

// Somewhere in your class
private float [] verts;


// You can fill this with actual data yourself, I did the hard part :P
verts = new float [] { 0.0f, 0.0f, 0.0f, 1.0f,     0.0f, 0.0f, 0.0f, 1.0f,
                       0.0f, 0.0f, 0.0f, 1.0f,     0.0f, 0.0f, 0.0f, 1.0f,
                       0.0f, 0.0f, 0.0f, 1.0f,     0.0f, 0.0f, 0.0f, 1.0f,
                       0.0f, 0.0f, 0.0f, 1.0f,     0.0f, 0.0f, 0.0f, 1.0f };
                    // ^^^^^^^^^ POS ^^^^^^^^      ^^^^^^^ NORMAL ^^^^^^^

//
// When it comes time to supply the vertex pointers, use this:
//
FloatBuffer vtx_base  = FloatBuffer.wrap (verts);
FloatBuffer norm_base = FloatBuffer.wrap (verts, 4, verts.length () - 4);

gl.glVertexAttribPointer (POSITION_ATTRIB, 4, GL.GL_FLOAT, false, 32, vtx_base);
gl.glVertexAttribPointer (NORMAL_ATTRIB,   4, GL.GL_FLOAT, false, 32, norm_base);

免责声明:我多年没有使用过Java,所以不要指望它可以直接编译。基本理论应该是合理的。


我不得不怀疑你是否真的需要4D顶点位置和法线? w有非常实际的用途,但如果你实际上不需要它,可以节省一些存储/带宽并使用3D。我提出这个问题是因为当你使用客户端内存而不是VBO时,会有更多的CPU-> GPU内存传输正在进行,并且每一点尺寸的减小都会有所帮助。

答案 1 :(得分:1)

我有点卡住,所以使用直接缓冲区共享另一个解决方案,如Nathan所提到的OpenGL所需。另外,在这个例子中,我用浮点数和字节/整数交错(颜色表示为4个字节):

// vertex position: 3 floats; vertex color: 4 bytes 
static final int COORDS_PER_VERTEX = 4;
static final int VERTS_PER_SPRITE = 4;
static final int MAX_NUM_SPRITES = 1000;
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
private FloatBuffer vertexBuffer;
private ByteBuffer colorBuffer;
public void init() {
    ByteBuffer bb = ByteBuffer.allocateDirect(
            // (# of coordinate values * 4 bytes per float)
            COORDS_PER_VERTEX * VERTS_PER_SPRITE * 4 * MAX_NUM_SPRITES);
    bb.order(ByteOrder.nativeOrder());
    vertexBuffer = bb.asFloatBuffer();
    bb.position(3 * 4);
    colorBuffer = bb.slice();
}

现在,在绘制顶点时,只需执行

public void draw() {
    GLES20.glUseProgram(myProgram);
    // Enable a handle to the sprite vertices
    GLES20.glEnableVertexAttribArray(mPositionHandle);
    GLES20.glEnableVertexAttribArray(mColorHandle);
    // Prepare the triangle coordinate data
    GLES20.glVertexAttribPointer(mPositionHandle, 3,
            GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
    GLES20.glVertexAttribPointer(mColorHandle, 4,
            GLES20.GL_UNSIGNED_BYTE, false, vertexStride, colorBuffer);
    // Draw the sprites GL_SHORT DOES NOT WORK!!!! Use UNSIGNED_SHORT
    GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6 * numSprites, GLES20.GL_UNSIGNED_SHORT, indexBuffer);
}

当我需要更新缓冲区时,我只准备一个浮点缓冲区,然后将4色字节转换为浮点数,

private void updateSpriteBuffer() {
    float[] vData = new float[COORDS_PER_VERTEX * VERTS_PER_SPRITE * MAX_NUM_SPRITES];
    for (int i = 0; i<numSprites; i++) {
        // ... x, y, z
        byte[] colorBytes = sprite.getColorBytes(); // {r, g, b, 1}
        float colorAsFloat = ByteBuffer.wrap(colorBytes).order(ByteOrder.nativeOrder()).getFloat();
        for (int k = 0; k < 4; k++) {
            int j = COORDS_PER_VERTEX * 4 * i + COORDS_PER_VERTEX * k;
            vData[j] = x[k];
            vData[j + 1] = y[k];
            vData[j + 2] = z[k];
            vData[j + 3] = colorAsFloat;
        }
    }
    vertexBuffer.put(vData);
    vertexBuffer.position(0);
}

我希望这有助于其他人尝试这样做。