Позвольте мне провести вас через явные ошибки, которые я сразу вижу в этом коде.
Прежде всего очевидная первая ошибка: вы утверждаете, что рисуете 100
точек, но ваш массив dots_vert
только99
элементов длиной.Это повторяется в следующем цикле, где вы переходите от 0
к 98
всего 99
раз.
Итак, прежде всего:
GLfloat dots_vert[100];
for (int i = 0; i < 100; ++i)
{
[...]
}
ЕстьЭто еще одна огромная ошибка, но мы ее оставим на потом, а теперь давайте двигаться дальше.
Вторая ошибка связана со знанием API OpenGL и компьютерной графики.Прежде всего, ваша цель состоит в том, чтобы передавать очки в GPU, поэтому вам нужна функция glVertexAttribPointer
, которую вы так сильно разобрались.Абсолютно первое, что вы хотите сделать, это посмотреть справочную документацию glVertexAttribPointer
, чтобы вы имели представление о том, что вам нужно.Вам нужны index
, size
, type
, normalized
флаг, stride
и offset
.
Давайте посмотрим, что в справочной документации говорится о size
параметр:
размер
Указывает количество компонентов на общий атрибут вершины.Должно быть 1, 2, 3, 4. Кроме того, символическая константа GL_BGRA принимается glVertexAttribPointer.Начальное значение равно 4.
Это сразу же очевидно, чтобы иметь решающее значение при определении того, какие данные вы пытаетесь передать в графический процессор.Вы устанавливаете параметр на 3
, что означает, что у вас есть x
, y
и z
.Но предыдущий код противоречит этому.Для начала, ваш массив dots_vert
имеет длину 100
элементов, и вы хотите нарисовать 100
точек, так что вам достаточно для 100/100 = 1
компонента на точку, а не 3
.Но что еще хуже, внутренняя часть цикла for
противоречит этому еще больше, поэтому давайте вернемся и проверим ошибку, о которой я упоминал ранее.
Ошибка номер три: ваш цикл for
состоит из if {} else {}
оператор, в котором для текущего элемента массива dots_vert
установлено значение 0.0f
, если индекс цикла четный (if (i % 2 == 0)
), и случайное значение между -50.0f
и 50.0f
в противном случае.Предполагая 1
компонента на точку, это означает, что вы генерируете только x
координаты, поэтому вы работаете в одном измерении.
Очевидно, что это не то, что вы намеревались сделать, также потому, чтополовина ваших очков будет 0.0f
, и поэтому все они будут перекрываться.Поэтому я предполагаю, что вы пытались сгенерировать случайное значение для x
и y
и установить z
на 0.0f
, что имело бы гораздо больше смысла.Прежде всего, у вас есть 3
компонентов на точку, и поэтому вам понадобится массив с 100*3 = 300
элементами.Итак, прежде всего, давайте исправим предыдущий код:
GLfloat dots_vert[300];
for (int i = 0; i < 300; ++i)
{
[...]
}
Намного лучше.Теперь нам нужно сгенерировать случайное значение x
и y
для каждой точки и установить z
в 0.0f
, поскольку нам это не нужно.Вы хотите выполнить все компоненты одновременно в одном цикле, поэтому вы хотите, чтобы ваш цикл шагал по 3
, а не 1
, поэтому еще раз исправим предыдущий код:
GLfloat dots_vert[300];
for (int i = 0; i < 300; i += 3)
{
[...]
}
Теперьмы можем создать x
, y
и z
вместе в одном цикле.Это критически важная часть понимания работы компьютерной графики, особенно в контексте API OpenGL.OpenGL использует систему координат, где начало координат находится в середине экрана, ось x
движется горизонтально (положительные x
точки направо), ось y
движется вертикально (положительные y
точки вверх),и ось z
идет прямо через экран (положительные z
указывают за пределы экрана к вам).Теперь это очень важная часть: x
, y
и z
обрезаются до определенного диапазона значений;все, что находится за пределами этого диапазона, игнорируется.Для всех координат диапазон изменяется от -1.0f
до 1.0f
.Все, что ниже, выше, вообще не нарисовано.
Итак, если вы хотите, чтобы 100
точек находились внутри экрана, игнорируя проекцию, выходящую за рамки этого упражнения, вы хотите сгенерировать x
и y
в -1.0f
до 1.0f
диапазон, а не -50.0f
до 50.0f
, как вы делаете там.Вы можете оставить от z
до 0.0f
, в данном случае это не имеет значения.Вот почему большинство ваших точек находятся за пределами экрана: с этой точки зрения, по статистике, около 98% ваших точек будут выходить за пределы пространства клипа и будут игнорироваться.
Так что в конечном итоге это то, что выwant:
GLfloat dots_vert[300];
for (int i = 0; i < 300; i += 3)
{
dots_vert[i] = ((GLfloat)rand() / (GLfloat)RAND_MAX)*2.0f - 1.0f; // this is x
dots_vert[i+1] = ((GLfloat)rand() / (GLfloat)RAND_MAX)*2.0f - 1.0f; // this is y
dots_vert[i+2] = 0.0f; // this is z
}
Напоследок напоминание: когда вы делаете glDrawArrays(GL_POINTS, 0, 100);
, вы говорите графическому процессору рисовать 100 очков.Каждая точка состоит из множества компонентов, указанных вами в параметре size
функции glVertexAttribPointer
.В этом случае вы хотите нарисовать 100
точек, каждая точка состоит из 3
компонентов, поэтому графический процессор ожидает массив 100*3 = 300
с плавающей точкой.номера.Все, что меньше, может привести либо к ошибке сегментации, либо, что еще хуже, к неопределенному поведению (что означает, что все может произойти), поэтому внимательно следите за тем, что вы делаете, и убедитесь, что вы точно знаете, какие данные вы передаете в графический процессор.потому что у вас может получиться бессмысленный результат, и вы застрянете, пытаясь понять, что пошло не так.В этом случае у вас практически нет кода для проверки, поэтому его легко исправить, но когда вы получите приличный объем кода (и вы в конечном итоге), такая ошибка может привести к потере часов или даже днейпытаясь найти ошибку.
В качестве бонуса, не стесняйтесь игнорировать это: технически точка состоит из 4
компонентов.Этот компонент называется w
, и его использование выходит за рамки данного упражнения, поэтому не беспокойтесь об этом, просто помните, что для него всегда должно быть установлено значение 1.0f
, если только вы не выполняете проецирование.
Так что технически вы могли бы сделать это тоже:
GLfloat dots_vert[400];
for (int i = 0; i < 400; i += 4)
{
dots_vert[i] = ((GLfloat)rand() / (GLfloat)RAND_MAX)*2.0f - 1.0f; // this is x
dots_vert[i+1] = ((GLfloat)rand() / (GLfloat)RAND_MAX)*2.0f - 1.0f; // this is y
dots_vert[i+2] = 0.0f; // this is z
dots_vert[i+3] = 1.0f; // this is w
}
Затем вы устанавливаете параметр size
для glVertexAttribPointer
равным 4
вместо 3
, результат должен быть точно таким же.