VA или делаем быстрее

Вы еще не используете VA? Тогда мы идем к вам!

VA - VertexArray

Это некий массив где храняться параметры вершин. Что сокращает количество вызовов передоваемых видеокарте.

И так, вы решили нарисовать что либо с помощью VA, для этого выделяют 4 шага:

  1. включить режим рисования VA

  2. загрузить меш в огл

  3. нарисовать

  4. выключить режим рисования 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, а пока что отписывайте что не так написал, что исправить, комментарии да и вобще что хотите