2

我找不到有关在 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 个属性。

4

2 回答 2

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 内存传输正在进行,并且每减少一点大小都会有所帮助。

于 2013-09-06T23:16:28.437 回答
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);
}

我希望这可以帮助其他人尝试做同样的事情。

于 2016-12-27T11:50:11.513 回答