VA или делаем быстрее
Вы еще не используете VA? Тогда мы идем к вам!
VA - VertexArray
Это некий массив где храняться параметры вершин. Что сокращает количество вызовов передоваемых видеокарте.
И так, вы решили нарисовать что либо с помощью VA, для этого выделяют 4 шага:
-
включить режим рисования VA
-
загрузить меш в огл
-
нарисовать
-
выключить режим рисования VA
И так погнали
Для Того что бы включить режим VA нужно написать следкющее
glEnableClientState(mode);
mode может принимать
GL_VERTEX_ARRAY
GL_COLOR_ARRAY
GL_NORMAL_ARRAY
GL_FOG_COORDINATE_ARRAY
GL_TEXTURE_COORD_ARRAY
GL_EDGE_FLAG_ARRAY
GL_SECONDARY_COLOR_ARRAY
GL_INDEX_ARRAY
из названия понятно какие опции они включают
Для того что бы выключить режим (после рисования) мы пишем
glDisableClientState(mode);
mode принимает тоже самое что и при enableclientstate (логично =))
после того как мы активировали VA надо передать параметры ему это делается с помощью gl * Pointer(argc);
- может принимать
Vertex
Color
SecondaryColor
и тд, как и в mode glEnableClientState
параметры у каждого поинтера разные
glVertexPointer( size, type, stride, pointer);
glColorPointer( size, type, stride, pointer);
glSecondaryColorPointer( size, type, stride, pointer);
glTexCoordPointer( size, type, stride, pointer);
glNormalPointer( type, stride, pointer);
glFogCoordPointer( type, stride, pointer);
glEdgeFlagPointer( stride, pointer);
теперь что делают параметры
size - это размерность, например если у нас вершины имеют 3 координаты (xyz) то требуется установить 3 на size
type - тип переменных лежащих в массиве, тут все ясно, главное, что бы они были переведены в gl’овские, например float - GL_FLOAT и тд
stride - смещение (в байтах) до следующего параметра (если массив с данными однородный то 0)
pointer - ссылка на первый элемент (0 если массив однородный)
Теперь перейдем к этапу отрисовки нашего массива
Есть несколько комманд для этого:
——glArrayElement(i);
С помощью ее мы может нарисовать какую нибуть(i) точку из массива
Внимание, команда не рисует точку, она просто возврощяет соотвецтвующий вызов glVertex glTexCoord glNormal и тд, для конкретного индекса, что бы нарисовать надо будет сделать цикл по всем элементам и обернуть в стандартный glBegin/glEnd
——glDrawRangeElements(mode, start, end, count, type, indices);
тоже что и glDrawElements только может выводиьт не с начала и не до конца
——glDrawElements(mode, count, type, indices);
с помощью этой команды мы можем рисовать по индексам передоваемым в indices, count и type должны быть понятны
все же напомню count - количество вершин которые нужно отрисовать, type - тип данных массива indices
mode - GL_POLYGON, GL_TRIANGLES, и тд
——glMultiDrawElements(mode, count, type, indices, pcount);
эта команда вызывает glDrawElements pcount раз
тут есть особенность в отличии от drawelements параметр count должен быть не числом а одномерным массивом размером pcount (от туда будут браться количество точек) и параметр indices должен быть массивом указателей на список вершин
——glDrawArrays(mode, first, count);
mode уже понятен, first - с какого элемента начинать, count сколько рисовать
эта команда выводит активированный массив (glEnable * State)
——glMultiDrawArrays(mode, first, count, pcount);
так же как и glMultiDrawElements только вызывает glDrawArrays
ну вот и все, комбинируйте параметрами что бы получить нужный результат
Пример использования
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <iostream>
using namespace std;
void init()
{
glClearColor(0, 0, 0, 0);
glClearDepth(1);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1, 1, -1, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
}
void free()
{}
void render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
static float mesh[] = {
-1, -1, 0, 1, 0, 0,
0, 1, 0, 1, 0, 1,
1, -1, 0, 1, 1, 0
};
glVertexPointer(3, GL_FLOAT, 6*sizeof(float), &mesh[0]);
glColorPointer(3, GL_FLOAT, 6*sizeof(float), &mesh[3]);
glDrawArrays(GL_TRIANGLES, 0, 3);
static float mesh2[] = {
-0.1, -1, 0, 1, 0, 0,
0.3 , 1, 0, 1, 0, 0,
1, -1, 0, 1, 0, 0
};
glVertexPointer(3, GL_FLOAT, 6*sizeof(float), &mesh2[0]);
glColorPointer(3, GL_FLOAT, 6*sizeof(float), &mesh2[3]);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glutSwapBuffers();
}
void kb(unsigned char key, int x, int y)
{
if(key == 27)
exit(0);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(640, 480);
glutCreateWindow("VBO");
init();
glutKeyboardFunc(kb);
glutDisplayFunc(render);
glutMainLoop();
free();
}
В следующей статье будет про использование VBO, а пока что отписывайте что не так написал, что исправить, комментарии да и вобще что хотите