VBO

Сначала нужно создать имена буферным объектам:

VBOid = new int[2];
GL.GenBuffers(2, VBOid);

Существует два буферных объекта: для хранения массива вершин (ArrayBuffer) и для хранения массива индексов (ElementArrayBuffer).

Для этих буферов мы создали два имени.

Теперь связываем имена с буферными объектами:

GL.BindBuffer(BufferTarget.ArrayBuffer, VBOid[0]); //связываем VBO
GL.BindBuffer(BufferTarget.ElementArrayBuffer, VBOid[1]); //связываем IBO

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

В массиве для вершин минимально требуется только координаты вершин (x, y, z). Но, если требуются нормали и текстурные координаты, то обычно можно увидеть данные в таком виде:

vertex array format

sizeof(float) * 3 для указания позиции вершины, sizeof(float) * 3 на вектор нормали и sizeof(float) * 2 на текстурные координаты. Если на машине размер типа float равен 4 байтам, то на описание точки требуется 4*3 + 4*3 + 4*2 = 4*8 =32 байта. Всего размер массива будет (sizeof(float) * 8) * vertex_count.

Массив индексов состоит из целочисленных данных типа int. Каждый элемент индекса указывает на блок данных из массива вершин. Т.к. массив вершин одномерный, то позиция блока с нужными данными находится по адресу index * sizeof(float) * 8.

Передаём буферу вершин указатель на массив вершин, в котором находятся данные в нашем формате (массив с именем, например, "vertexes"):

GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertexes.Length * sizeof(float)), vertexes, BufferUsageHint.StaticDraw); //записываем в память VBO

Данные из массива вершин перемещаются в т.н. "хранилище данных". Параметр-подсказка BufferUsageHint со значением StaticDraw "подсказывает" машине, что данные будут меняться редко.

Точно также передаём буферу индексов указатель на массив индексов (с именем, например, "indexes"):

GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(indexes.Length * sizeof(int)), indexes, BufferUsageHint.StaticDraw); //записываем в память IBO

Данные переданы в буфер. Обходя буфер индексов, OpenGL будет искать данные в буфере вершин, и теперь нужно указать, по какому адресу искать данные о позициях точек, нормалей и текстурных координат:

GL.VertexPointer(3, VertexPointerType.Float, sizeof(float) * 8, 0); //координаты точек идут первыми, смещение 0
GL.NormalPointer(NormalPointerType.Float, sizeof(float) * 8, sizeof(float) * 3); //вектор нормали идет после данных о позиции
GL.TexCoordPointer(2, TexCoordPointerType.Float, sizeof(float) * 8, sizeof(float) * 6); //текстурные координаты после вектора нормали

Эти функции указывают расстояние между данными и начальную позицию данных в буфере вершин. Расстояние одинаковое sizeof(float) * 8 (длина блока данных о вершине), а начальная позиция зависит от положения внутри блока.

Осталось указать OpenGL, что мы в данный момент хотим вывести на экран всю информацию о точках:

GL.EnableClientState(ArrayCap.VertexArray);
GL.EnableClientState(ArrayCap.NormalArray);
GL.EnableClientState(ArrayCap.TextureCoordArray);

Эти команды можно давать в каждом кадре.

И в каждом кадре даем команду рисования:

GL.DrawElements(BeginMode.Triangles, indexes.Length, DrawElementsType.UnsignedInt, IntPtr.Zero);

Эта функция находит буфер индексов, берет каждые 3 индекса для рисования треугольников (т.к. мы указали BeginMode.Triangles), находит по ним 3 блока данных из буфера вершин, по данным о позициях (из функций VertexPointer, NormalPointer и TexCoordPointer) берет нужные данные из буфера вершин, рисует.


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Sandro's picture

Этот перевод ещё более непонятный, чем источник. Цель какая преследовалась, запутать ещё больше?

RomanKositsyn's picture

/