Шейдеры OpenGL: как перемещать каждую вершину отдельно?

Я пытаюсь использовать библиотеку Rajawali для Android, чтобы нарисовать некоторые основные 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, но не знаю как).


person dilix    schedule 17.07.2012    source источник
comment
Нужно ли блокировать буфер перед его изменением? Я тоже очень новичок в этом и использую Ogre3d с С++, однако принцип должен оставаться тем же. Вы должны иметь возможность получить текущий буфер вершин, заблокировать его, изменить, а затем разблокировать. Я не думаю, что вам нужно делать что-то еще, но я могу быть совершенно неправ. Извините, я не очень помогу.   -  person Jon Taylor    schedule 17.07.2012
comment
glBufferSubData должен работать нормально, можете ли вы показать, что из того, что вы пробовали, не сработало?   -  person Tim    schedule 17.07.2012


Ответы (1)


Все, что вам нужно сделать, это изменить данные буфера, а затем вызвать mGeometry.changeBufferData() из класса PlanesGalore. Я помещаю следующий код в метод обновления, который вызывается во время события onDrawFrame() моего класса Renderer.

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

mGeometry.changeBufferData(mCubePositionsBufferInfo, mPlanePositions, 0);

Это лучший способ, который я мог найти для выполнения движений. Кроме того, я предложил внести изменение в этот выпуск, который позволит указать, какая часть буфер изменен, что должно обеспечить повышенную производительность.

РЕДАКТИРОВАТЬ

Мое изменение в движке было одобрено, так что теперь вы можете оптимизировать его еще больше, вот так.

// 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);
person ian.shaun.thomas    schedule 06.09.2012