В руководстве по OpenGL 3.0+ мы создаем объект Vertex Array и объект Vertex Buffer следующим образом:
GLuint VAO, VBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
Здесь ВАО является unsigned int
(GLuint
) и мы передаем a address ̶r̶e̶f̶e̶r̶e̶n̶c̶e̶ его адрес в функцию glGenVertexArray
, Однако, согласно документации, вторым аргументом функции должен быть массив unsigned int
(GLuint*
). То же самое касается VBO и glGenBuffers
, Я не понимаю, почему приведенный выше код работает с такими аргументами.
Я попытался заменить приведенный выше код на этот (и сделать необходимые изменения в другом месте в моем коде):
GLuint VAO[1];
GLuint VBO[1];
glGenVertexArrays(1, VAO);
glGenBuffers(1, VBO);
glBindVertexArray(VAO[1]);
glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
Он компилируется и выполняется, но я получаю неожиданное поведение: мой текстурированный прямоугольник отображается с первым синтаксисом, а не со вторым. Я тоже не понимаю, почему это происходит.
РЕДАКТИРОВАТЬ: Спасибо. Как уже говорилось, во втором коде есть ошибка индексации.
Сигнатура функции в спецификации:
void glGenVertexArrays( GLsizei n, GLuint *arrays);
Так arrays
ожидает GLuint
указатель где действительно написать n * sizeof(GLuint)
байтов данных в.
Это прекрасно и правильно написать:
GLuint VAO, VBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
Так как glGenVertexArrays
хочет иметь указатель на GLuint
где действительно написать n * sizeof(GLuint)
байтов данных (в вашем случае 1
) и потому что VAO
может содержать этот объем данных, это правильно записать таким образом. И предпочтительнее, если вы создаете только один идентификатор на вызов.
Как уже было сказано другими, первый элемент в массиве имеет индекс 0
, По этому это должно быть:
GLuint VAO[1];
GLuint VBO[1];
glGenVertexArrays(1, VAO);
glGenBuffers(1, VBO);
glBindVertexArray(VAO[0]);
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
Если вы хотите создать больше элементов за один вызов, вы хотите использовать std::array
над []
,
std::array<GLuint,3> VAOs;
std::array<GLuint,3> VBOs;
glGenVertexArrays(VAOs.size(), &VAOs[0]);
glGenBuffers(VBOs.size(), &VBOs[0]);
Как примечание unsigned int
а также GLuint
не обязательно того же типа или размера, unsigned int
имеет минимальный гарантированный диапазон номеров, но размер может варьироваться на разных платформах. GLuint
с другой стороны, имеет определенный размер.
Первый индекс 0
GLuint VAO[1];
GLuint VBO[1];
glGenVertexArrays(1, VAO);
glGenBuffers(1, VBO);
glBindVertexArray(VAO[0]);
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
Массив в C и C ++ представлен в виде указателя. Иными словами, указатель эквивалентен массиву из одного элемента. Поэтому, если вы создаете один буферный объект, вы можете просто объявить одну переменную и передать на нее указатель, как в первом примере (это не ссылка, а указатель), и в этом нет ничего плохого. Я всегда так делал сам.
Почему ваш второй пример не работает, см. Ответ Джонатана Олсона выше.