Шаблон игры OpenGL найден в xcode 4.2 (что происходит в этом коде? !!) - PullRequest
4 голосов
/ 06 декабря 2011

Здравствуйте, я пытался понять, что происходит в этой части кода, сколько мог, но мне не повезло.

glGenVertexArraysOES(1, &_vertexArray);
glBindVertexArrayOES(_vertexArray);

glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW);

glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));
glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));

glBindVertexArrayOES(0);

Это относится к шаблону для создания игр OpenGLна xcode 4.2.Тем не менее, я полностью сбит с толку, и я был бы рад, если бы кто-то мог мне это объяснить.

Во-первых, как я могу сгенерировать и связать массив _vertexArray, ничего не добавляя к нему?

Во-вторых, если gCubeVertexData являетсямассив из 216 со следующим:

GLfloat gCubeVertexData[216] = 
{
    // Data layout for each line below is:
    // positionX, positionY, positionZ,     normalX, normalY, normalZ,
    0.5f, -0.5f, -0.5f,        1.0f, 0.0f, 0.0f,
    0.5f, 0.5f, -0.5f,         1.0f, 0.0f, 0.0f,

Я бы предположил, что я обрабатываю этот массив для следующей команды, где я включаю атрибуты GLK, и это то, для чего я использую указатели (все еще используя предварительно связанный),Но если я не ошибаюсь, синтаксис (атрибут для установки, размер вершины, тип, ложь, размер структуры (который, я думаю, не 24) и смещение от данных (откуда эти 12 получены ?!))

и последний вопрос, почему я теперь привязываю 0 к массиву вершин?

РЕДАКТИРОВАТЬ: Честно говоря, я пытался исследовать OpenGL на разных сайтах, но я мог только встретитьсятеория не практика.Вот почему я задавал этот вопрос.

1 Ответ

21 голосов
/ 06 декабря 2011

Хорошо, шаг за шагом:

glGenVertexArraysOES(1, &_vertexArray);
glBindVertexArrayOES(_vertexArray);

Это связывает и генерирует объект массива вершин (VAO). Теперь ВАО не содержит никаких данных. Он просто содержит все состояния, связанные с массивами / атрибутами вершин, такими как включенные атрибуты или настройки, сделанные с помощью glVertexAttribPointer.

glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW);

Теперь это создает и связывает объект буфера вершин (VBO), который по существу представляет собой простой буфер данных, управляемый OpenGL, и копирует в него данные вершин.

Давайте посмотрим на эти данные:

GLfloat gCubeVertexData[216] = 
{
    // Data layout for each line below is:
    // positionX, positionY, positionZ,     normalX, normalY, normalZ,
    0.5f, -0.5f, -0.5f,        1.0f, 0.0f, 0.0f,

Ваши данные представлены в виде набора чисел с плавающей запятой (32-разрядного / 4-байтового каждого), причем каждые шесть значений представляют вершину, которая, в свою очередь, состоит из позиции (3 числа с плавающей запятой) и нормального значения (3 числа с плавающей запятой) .

glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));

Здесь указывается первый атрибут (позиция), который содержит 3 значения с плавающей запятой для каждой вершины с шагом 24 байта между каждой вершиной. Это означает, что это 24 байта от начала значений атрибута (в данном случае позиции) одной вершины до начала данных атрибута следующей вершины. И действительно, 24 байта - это размер 6 чисел с плавающей запятой и, следовательно, данных одной вершины в наших данных вершин, так что это точно соответствует. Последний параметр говорит, что данные о местоположении начинаются с начала текущего связанного VBO (который содержит наши данные вершин), так как это первый атрибут в наших данных вершин.

glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));

Указывает второй атрибут (нормальный), который должен содержать 3 значения с плавающей точкой на вершину, опять же с шагом 24 байта, как это было получено из тех же данных. Таким образом, от одного нормального до следующего это также 24 байта (6 операций с плавающей запятой). Теперь последний параметр говорит, что нормальные данные начинаются через 12 байтов (3 числа с плавающей запятой) после начала текущего связанного VBO (которое содержит наши данные вершин). Это необходимо, потому что нормаль является вторым атрибутом в наших данных вершин, поэтому нам нужно «перепрыгнуть» первые три значения (которые являются позицией), чтобы добраться до нормальных данных. Если бы мы снова использовали 0, мы бы взяли те же данные, что и для позиций.

glEnableVertexAttribArray(GLKVertexAttribPosition);
glEnableVertexAttribArray(GLKVertexAttribNormal);

Наконец, включаются атрибуты рендеринга.

glBindVertexArrayOES(0);

Так что теперь это привязывает VAO по умолчанию (нет), так как мы закончили с его определением. Я предполагаю, что весь этот фрагмент кода является частью некоторой процедуры инициализации. Поэтому теперь всякий раз, когда мы хотим рендерить наши данные вершин, возможно, используя glDrawArrays, нам нужно только связать VAO, используя glBindVertexArray, перед вызовом метода рисования, и каждое состояние массива вершин, сделанное с помощью glEnableVertexAttribArray или glVertexAttribPointer, получает значения устанавливаются, когда VAO был привязан последним, как в нашей процедуре инициализации. Если вы не будете использовать VAO, вам придется вызывать glBindBuffer и два вызова glEnableVetrexAttribArray и glVertexAttribPointer каждый раз, когда вы хотите нарисовать эти данные вершины.

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

...