#opengl-es #3d
#opengl-es #3D
Вопрос:
У меня есть несколько треугольных полигонов, и я рисую их традиционным способом: (код Android-java)
gl.glDrawArrays(GL10.GL_TRIANGLES, i, j);
Я хочу обновить координаты вершин треугольников. Во всех руководствах, которые я нашел, используются исходные данные вершины, а затем применяются преобразования только к ним. Мне нужно изменить координату каждой вершины независимо.
Я изменяю содержимое массива, который используется для создания связанного vertexbuffer, но это не вносит никаких изменений на экран. Мне кажется, что перестраивать vertexbuffer на каждом кадре неправильно.
Можете ли вы указать хотя бы какой-нибудь пример исходного кода, если вы его знаете?
Ответ №1:
Вы, кажется, ищете glBufferSubData
. По сути, вы обновляете содержимое своего массива точно так, как вы описали, затем вызываете glBufferSubData
, чтобы обновить объект vertexbuffer новыми значениями.
Предполагается, что вы изменяете только относительно небольшое подмножество данных. Если вы изменяете большую часть данных, обычно лучше просто вызвать glBufferData
еще раз вместо этого.
Комментарии:
1. Возможно, вы правы, но мне не удалось с этим справиться. Знаете ли вы, требуется ли выполнить некоторые приготовления для glgenbuffers и glbindbuffer перед использованием glbuffersubdata?
2. @emre: Нет, я не помню, чтобы делал что-то необычное / особенное для использования
glbufferSubData
.3. Я делаю что-то похожее на это (если это кажется понятным) public void draw(GL11 gl) { gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10. GL_TEXTURE_COORD_ARRAY); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, VertexBuffer); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer); gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3); gl. glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10. GL_TEXTURE_COORD_ARRAY); вершины[0] = 5; gl.glBufferSubData(GL11. GL_ARRAY_BUFFER, 0, 4, VertexBuffer); } Я продолжу бороться и сообщу, смогу ли я справиться
4. @JerryCoffin Вы не указали на тот факт, что
glBufferSubData
это рекомендуется только тогда, когда небольшая часть буфера требует обновления. В противном случае следует использоватьglBufferData
. Источник: opengl.org/wiki /…5. @b1nary.atr0phy: По крайней мере, когда я читал это, в этом был весь смысл вопроса. Он уже отправил данные, изменяет несколько конкретных фрагментов и хочет избежать повторной отправки всех данных.
Ответ №2:
Я обнаружил, что большая часть моей проблемы связана с java-Android. @jerry предложил правильное решение основной идеи в моем вопросе, но я остановлюсь на проблемах, связанных с java-Android:
Во-первых, сигнатуры методов в интерфейсе рендеринга Android предлагают вам объект GL10 в качестве параметра, но некоторые из необходимых вам методов находятся в opengl-es1.1, поэтому вам нужно преобразовать объект gl.
public void onDrawFrame(GL10 gl) {
GL11 gl11 = (GL11)gl;
Конечно, если устройство не поддерживает opengl-es1.1, ваш код не будет работать, но это не входит в нашу тему.
Моя другая проблема заключалась в различиях в java-реализации opengl-es. В java вы создаете связанный объект Buffer, который является собственным классом java в пакете java.nio, и заполняете внутри этого буфера указанный вами массив.
public static FloatBuffer createFloatBuffer(float[] array){
ByteBuffer byteBuf = ByteBuffer.allocateDirect(array.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
FloatBuffer fbuf = byteBuf.asFloatBuffer();
fbuf.put(array);
fbuf.position(0);
return fbuf;
}
После этой части вы не имеете ничего общего с объектом array. Вам необходимо обновить объект buffer. Вы можете обновить содержимое буфера, используя put(index, value)
метод соответствующего класса buffer.
Вот метод draw() объекта, который мы хотим нарисовать. vertexBuffer
является FloatBuffer
объектом. Вы можете понять, о чем я думаю, из этого фрагмента.
public void draw(GL11 gl) {
vertexBuffer.put(index, floatValue);
gl.glBufferSubData(GL11.GL_ARRAY_BUFFER, 0, vertexBuffer.capacity(),vertexBuffer);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
Вы можете поправить меня, если есть вводящие в заблуждение моменты..
Ответ №3:
Я думаю, что вы хотите создать несколько вершинных буферов при инициализации, а затем просто привязать к разным с помощью glBindBuffer()
Комментарии:
1. Я не понял, как это будет работать. Я хочу изменить содержимое каждой вершины, а не переключаться между массивами.
2. Для этого нет причин. Если у него возникли проблемы только с одним VBO, то указание ему использовать несколько ничего не решит.