Буферы вершин
GLVertexBuffer — вершинный буфер
Управляет хранением и обновлением данных вершин на GPU.
Создание буфера
// Буфер для вершин
var vbo = context.CreateVertexBuffer<Vertex>(BufferTargetARB.ArrayBuffer);
// Буфер для индексов
var ebo = context.CreateVertexBuffer<uint>(BufferTargetARB.ElementArrayBuffer);
Загрузка данных
Статическая загрузка (один раз)
var vertices = new[]
{
new Vertex { Position = new FVector3(0, 1, 0) },
new Vertex { Position = new FVector3(-1, -1, 0) },
new Vertex { Position = new FVector3(1, -1, 0) }
};
var vbo = context.CreateVertexBuffer<Vertex>(BufferTargetARB.ArrayBuffer);
vbo.Load(vertices, BufferUsageARB.StaticDraw);
Динамическая загрузка (обновление)
// Начальная загрузка
vbo.Load(initialVertices, BufferUsageARB.DynamicDraw);
// Обновление части буфера
var newVertices = GetUpdatedVertices();
vbo.Update(0, newVertices);
Добавление данных (append)
var vbo = context.CreateVertexBuffer<Vertex>(BufferTargetARB.ArrayBuffer);
vbo.Load(vertices1, BufferUsageARB.DynamicDraw);
// Добавляем в конец
var vertices2 = GetMoreVertices();
vbo.Update(vertices2); // обновляет с текущей позиции
// Индекс теперь указывает на конец
uint newIndex = vbo.Index;
Управление позицией
var vbo = context.CreateVertexBuffer<Vertex>(BufferTargetARB.ArrayBuffer);
// Текущая позиция (в вершинах, не байтах)
uint pos = vbo.Index;
// Установить позицию
vbo.Index = 100;
// Вернуть в начало
vbo.ResetIndex();
vbo.Index = 0;
GLVertexAttributes (VAO)
Описывает формат данных вершин.
Создание и конфигурация
var vao = context.CreateVertexAttributes();
vao.Bind();
// Добавить описание атрибута
// AddAttribute(индекс, компоненты, тип, нормализовано, stride, offset)
vao.AddAttribute(
index: 0, // location = 0 в шейдере
size: 3, // vec3
type: VertexAttribPointerType.Float,
normalized: false,
stride: 32, // размер структуры Vertex
offset: 0 // смещение от начала структуры
);
// Текстурные координаты (обычно в offset 12 для 3 флоатов позиции)
vao.AddAttribute(1, 2, VertexAttribPointerType.Float, false, 32, 12);
// Нормали (обычно в offset 20)
vao.AddAttribute(2, 3, VertexAttribPointerType.Float, false, 32, 20);
Включение/отключение
vao.Bind();
// Включить атрибут
if (vao.EnableAttribute(0)) // успешно если атрибут был добавлен
{
// атрибут включен
}
// Отключить
vao.DisableAttribute(0);
Структура вершины
[StructLayout(LayoutKind.Sequential)]
public struct Vertex
{
// Позиция (offset 0, размер 12 байт)
public FVector3 Position;
// Текстурные координаты (offset 12, размер 8 байт)
public FVector2 TexCoord;
// Нормаль (offset 20, размер 12 байт)
public FVector3 Normal;
// Итого: 32 байта (stride)
}
Убедитесь что структура unmanaged:
- Только примитивные типы (float, int, uint)
- Вложенные структуры тоже unmanaged
- Нет ссылочных типов
Типовый цикл отрисовки
// Инициализация (один раз)
var vertices = new[]
{
new Vertex { Position = new FVector3(0, 1, 0), TexCoord = new FVector2(0.5f, 1f) },
new Vertex { Position = new FVector3(-1, -1, 0), TexCoord = new FVector2(0f, 0f) },
new Vertex { Position = new FVector3(1, -1, 0), TexCoord = new FVector2(1f, 0f) }
};
var indices = new uint[] { 0, 1, 2 };
var vbo = context.CreateVertexBuffer<Vertex>(BufferTargetARB.ArrayBuffer);
vbo.Load(vertices, BufferUsageARB.StaticDraw);
var ebo = context.CreateVertexBuffer<uint>(BufferTargetARB.ElementArrayBuffer);
ebo.Load(indices, BufferUsageARB.StaticDraw);
var vao = context.CreateVertexAttributes();
vao.Bind();
vbo.Bind();
vao.AddAttribute(0, 3, VertexAttribPointerType.Float, false, 32, 0);
vao.AddAttribute(1, 2, VertexAttribPointerType.Float, false, 32, 12);
vao.EnableAttribute(0);
vao.EnableAttribute(1);
// Отрисовка (каждый кадр)
Igdrasil.OnRender += (ctx, dt) =>
{
shader.Apply();
vao.Bind();
ebo.Bind();
ctx.DrawElements(
PrimitiveType.Triangles,
0,
(uint)indices.Length,
DrawElementsType.UnsignedInt
);
};
Обновление вершин
// Если данные меняются каждый кадр
var vbo = context.CreateVertexBuffer<Vertex>(BufferTargetARB.ArrayBuffer);
vbo.Load(vertices, BufferUsageARB.DynamicDraw);
Igdrasil.OnUpdate += dt =>
{
// Обновляем все вершины
var newVertices = CalculateNewVertices(dt);
vbo.Update(0, newVertices);
};
// Отрисовка
Igdrasil.OnRender += (ctx, dt) =>
{
vao.Bind();
ctx.DrawArrays(PrimitiveType.Triangles, 0, vertexCount);
};
Очистка
vbo.Dispose(); // освобождает GPU память
ebo.Dispose();
vao.Dispose();
Версия: 1.0