Связь между буферами и glVertexAttribPointer - PullRequest
0 голосов
/ 11 декабря 2018

Я пытаюсь понять отношения между [glGenBuffers, glBindData, glBufferData, glBufferSubData] и glVertexAttribPointer.

Я видел, что вам на самом деле не нужноиспользуйте метод buffers (по крайней мере, не в Android), а вызывайте glVertexAttribPointer напрямую, передавая указатель на объект буфера в качестве последнего параметра.(в данном случае это буферы FloatBuffer)

например

GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 12, vertexBuffer);
GLES20.glVertexAttribPointer(colorHandle, 4, GLES20.GL_FLOAT, false, 16, colorBuffer);
GLES20.glVertexAttribPointer(normalHandle, 3, GLES20.GL_FLOAT, false, 12, normalsBuffer);
GLES20.glVertexAttribPointer(textureHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer);

1) Зачем мне использовать методы буфера?Только если мои данные оказались вместе в одном массиве?

2) Как openGL обрабатывает эти прямые (не буферные) функции за кулисами?Я видел, что он вызывает glVertexAttribPointerBounds - действительно ли он складывает его вместе в один массив байтов?

3) Если я связываю массив с GL_ARRAY_BUFFER - это означает, что я должен использовать сложенныйверсия массива, и я больше не смогу передавать прямые объекты, верно?то есть я не могу сделать это:

int[] bufferVertices = new int[1];
GLES20.glGenBuffers(1, bufferVertices, 0);
vertexBufferId = bufferVertices[0];
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferId);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, cubeCoords.length * 4 , vertexBuffer, GLES20.GL_STATIC_DRAW);

GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride,0);
GLES20.glVertexAttribPointer(colorHandle, 4, GLES20.GL_FLOAT, false, 16, colorBuffer);
GLES20.glVertexAttribPointer(normalHandle, 3, GLES20.GL_FLOAT, false,12, normalsBuffer);
GLES20.glVertexAttribPointer(textureHandle, 2, GLES20.GL_FLOAT, false,8, textureBuffer);

Ответы [ 2 ]

0 голосов
/ 15 января 2019

1) Предпочтительным способом является использование буферных объектов при любой возможности.Это обеспечивает выделение необходимых ресурсов графического процессора заранее.Однако для динамической геометрии иногда удобнее вызывать методы без буфера.По моему опыту, некоторые драйверы показали лучшую производительность при использовании безбуферных методов даже по сравнению с использованием буфера с GLES20.GL_DYNAMIC_DRAW.Но для статической геометрии лучшим подходом является использование буфера GL.Таким образом, драйвер может избежать необходимости копировать данные вершин перед каждым вызовом отрисовки.

2) Общеизвестно, что когда вы передаете массив со стороны ЦП в glVertexAttribPointer, он должен быть скопирован драйвером во времяпоследующий вызов glDraw *.Затем вы можете изменить массив, и он будет скопирован во время следующего вызова glDraw * снова.Что касается размещения вершинных данных в памяти, я бы поспорил, что они остались без изменений, поскольку графические процессоры AFAIK могут обрабатывать потоки без чередования.Таким образом, реорганизация их перед вызовом отрисовки GL потребует бессмысленной операции сбора.

3) Смешивание потоков буфера GL и массива ЦП должно работать нормально.Это распространенный сценарий, когда одна часть данных вершин является статической (например, texcoords), а другая - динамической (например, позиции), причем последняя преобразуется, например, CPU.

0 голосов
/ 12 декабря 2018

Вы можете иметь несколько буферных объектов.Если буфер массива вершин связан, когда вызывается glVertexAttribPointer, то последний параметр glVertexAttribPointer обрабатывается как смещение к этому буферу, но если объект буфера вершин не привязан, то последний параметртрактуется как указатель на данные:

См. Спецификация OpenGL ES 2.0;2,8.Решетки VERTEX;21 :

void VertexAttribPointer( uint index, int size, enum type, 
                          boolean normalized,  sizei stride, 
                          const void *pointer );

... Для каждой команды pointer указывает местоположение в памяти первого значения первого элемента указанного массива.

См. спецификация OpenGL ES 2.0;2.9.БУФЕРНЫЕ ОБЪЕКТЫ;25 :

... Когда массив получен из объекта буфера, значение pointer этого массива используется для вычисления смещения в базовых единицах машиныв хранилище данных объекта буфера....

Это означает, что можно сделать:

int[] bufferVertices = new int[4];
GLES20.glGenBuffers(4, bufferVertices, 0);

vertexBufferId = bufferVertices[0];
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferId);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, cubeCoords.length * 4, vertexBuffer, GLES20.GL_STATIC_DRAW);

colorBufferId = bufferVertices[1];
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, colorBufferId);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, cubeCoords.length * 4, colorBuffer, GLES20.GL_STATIC_DRAW);

normlBufferId = bufferVertices[2];
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, normlBufferId);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, cubeCoords.length * 4, normalsBuffer, GLES20.GL_STATIC_DRAW);

textureBufferId = bufferVertices[3];
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, textureBufferId);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, cubeCoords.length * 4, textureBuffer, GLES20.GL_STATIC_DRAW);

GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferId);
GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, 0);

GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, colorBufferId);
GLES20.glVertexAttribPointer(colorHandle, 4, GLES20.GL_FLOAT, false, 0, 0);

GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, normlBufferId);
GLES20.glVertexAttribPointer(normalHandle, 3, GLES20.GL_FLOAT, false, 0, 0);

GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, textureBufferId);
GLES20.glVertexAttribPointer(textureHandle, 2, GLES20.GL_FLOAT, false, 0, 0);
...