OpenGL着色器:如何单独移动每个顶点?

时间:2012-07-17 11:00:40

标签: android opengl-es shader rajawali

我正在尝试用于Android的Rajawali库在场景中绘制一些基本的3D对象。 有一个样本2000个平面,它展示了如何使用一个着色器非常“廉价”地渲染大量顶点。我可以将顶点数组传递给着色器并绘制它们。

我想升级此示例并相互独立地移动一些顶点。

我已经尝试了glBufferSubData,但我无法改变场景中的任何内容。我发现的一种方法是更改​​数据并重新创建缓冲区,但我希望有一种更简单的方法来只更改必要的数据。

例如,我只想从已创建和绑定的缓冲区中更改某些位置。

初始化职位

    float[] planePositions = new float[numVertices * 3];
    ....

创建缓冲区

    mGeometry.createBuffer(mPlanePositionsBufferInfo, BufferType.FLOAT_BUFFER, mPlanePositions,     GLES20.GL_ARRAY_BUFFER);
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);

设置职位

    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, planePosBufferHandle);
    GLES20.glEnableVertexAttribArray(maPlanePositionHandle);
    fix.android.opengl.GLES20.glVertexAttribPointer(maPlanePositionHandle, 3, GLES20.GL_FLOAT,
            false, 0, 0);   

如何修改第一个平面的第一个顶点的位置? (planePositions [0] = a; planePositions [1] = b; planePositions [1] = c ...现在我必须将这个修改后的数组传递给opengl,但不知道如何)。

1 个答案:

答案 0 :(得分:3)

您需要做的就是修改缓冲区数据,然后从PlanesGalore类中调用mGeometry.changeBufferData()。我将以下代码放在我的Renderer类的onDrawFrame()事件期间调用的更新方法中。

for (int i = 0; i < vertices.length; i += 3) {
   mPlanePositions= mPlanePositions.put(i, mPlanePositions.get(i) - 0.01f);
}

mGeometry.changeBufferData(mCubePositionsBufferInfo, mPlanePositions, 0);

这是我完成动作的最好方法。另外,我已经提议对此issue进行更改,以便您指定缓冲区的哪些部分已更改,从而提高性能。

修改

我对引擎的更改已经获得批准,因此您现在可以进一步优化它。

// The offset position should be vertices.length * object #. In my use case this is 72*x
// allowing me to update the XYZ coordinates of all 24 vertices of a cube.
int offsetPosition = 0;
mGeometry.changeBufferData(mCubePositionsBufferInfo, mPlanePositions, offsetPosition, offsetPosition + vertices.length);