2016-05-08 7 views
1

Я пытаюсь изучить LWJGL (OpenGL), и я должен сказать, что мне тяжело.OpenGL Vertex Array Buffer

Я пытался нарисовать треугольник и квадрат на окне, и я, наконец, смог это сделать.

Но у меня все еще есть вопрос.
Извините, если вопрос звучит глупо для вас, но я не смог найти очень подробный учебник в Интернете, поэтому его трудно понять, так как это первый раз, когда я использую OpenGL.

Это, как говорится, это соответствующая часть кода:

public void init() { 
    vertexCount = indices.length; 

    vaoId = GL30.glGenVertexArrays(); 
    GL30.glBindVertexArray(vaoId); 

    vboId = GL15.glGenBuffers(); 
    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboId); 
    GL15.glBufferData(GL15.GL_ARRAY_BUFFER, coords, GL15.GL_STATIC_DRAW); 
    GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0); 
    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); 

    idxVboId = GL15.glGenBuffers(); 
    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, idxVboId); 
    GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indices, GL15.GL_STATIC_DRAW); 

    GL30.glBindVertexArray(0); 
} 

public void render() { 
    GL30.glBindVertexArray(vaoId); 
    GL20.glEnableVertexAttribArray(0); 
    GL11.glDrawElements(GL11.GL_TRIANGLES, vertexCount, GL11.GL_UNSIGNED_INT, 0); 

    GL20.glDisableVertexAttribArray(0); 
    GL30.glBindVertexArray(0); 
} 

Допустим, что программа работает на 60 кадров в секунду.
Это означает, что метод визуализации вызывается игровым циклом 60 раз в секунду.

рендер этапы способа являются:

  1. glBindVertexArray(vaoId)
  2. glEnableVertexAttribArray(0)
  3. Нарисуйте четырехугольник
  4. glDisableVertexAttribArray(0)
  5. glBindVertexArray(0)

Мой вопрос: Необходимо ли каждый раз вызывать шаги 1, 2, 4 и 5? Если да, то почему?

И тот же вопрос относится к последней строке метода init() (glBindVertexArray(0)).

Извините за мой английский, это не мой родной язык.
Спасибо заранее.

+1

Должно быть много предыдущих вопросов, которые охватывают работу VAO. Например, здесь: http://stackoverflow.com/questions/26552642/when-is-what-bound-to-a-vao. Короче говоря: нет, вам это не нужно. Вам нужно всего лишь связать VAO в начале метода рендеринга. И если вы используете только один VAO, вы можете просто привязать его. Состояние не изменяется спонтанно, поэтому, если вы никогда не связываете другое VAO (включая 0), нет необходимости связывать его снова. –

ответ

1

Мой вопрос: необходимо ли каждый раз вызывать шаги 1, 2, 4 и 5? Если да, то почему?

Нет, это не так. OpenGL разработан как конечный автомат. У вас есть контекст GL, который содержит глобальное состояние и объекты, которые вы создаете (например, VAO, VBOs). Сами объекты могут содержать данные и состояние каждого объекта. Важно то, что состояние, которое задано во время какого-то определенного вызова функции GL, которое каким-то образом зависит от некоторых из этих значений состояния.

В случае glDrawElements() указатели массива вершин и разрешающие биты, а также привязка GL_ELEMENT_ARRAY_BUFFER имеют отношение к предоставлению входных данных для вызова рисования. (Все остальные состояния, влияющие на рисунок, такие как привязки текстур, шейдерные программы, настройка глубины, ... также актуальны, но не позволяют сосредоточиться на них здесь.). Все это состояние фактически инкапсулировано в объект вершинного массива (VAO).

С дизайном государственного устройства OpenGL состояние остается неизменным, если оно не изменено. Поскольку вы, кажется, рисуете только один объект и никогда не нуждаетесь в разных указателях ссылок или массивах элементов, вы просто можете установить их один раз и уменьшить свой метод render() только до вызова glDrawElements(). Это, конечно, предполагает, что никакой другой код в вашем цикле рендеринга не влияет на какое-либо влияющее состояние.

Следует отметить одну вещь: VAO хранит разрешения для каждого массива атрибутов, поэтому ваш шаг 2 принадлежит к инициализации VAO, а шаг 4 совершенно бесполезен в этой схеме.

Это также означает, что если вы хотите управлять разными объектами, вы можете создать VAO, VBO и EBO для каждого объекта, а ваш mothod будет просто перебирать объекты, устанавливать соответствующие VAO и выдавать призыв рисования:

for every object obj 
    glBindVertexArray(obj.vao); 
    glDrawElements(...values depending on obj...); 

Binding VAO 0 на самом деле никогда не требуется в современных OpenGL. Вы всегда должны будете иметь привязку к VAO во время вызова ничьей, так что в итоге вам все равно придется связать не-0 VAO позже. Единственное значение, которое unbinding обеспечивает то, что оно предотвращает случайные изменения некоторых объектов. Поскольку традиция OpenGL API всегда использует косвенность ожидающих целей, чтобы изменить объект, можно создать ситуации, когда объекты привязаны, которые не должны быть привязаны в то время, в результате чего трудно отлаживать неправильное поведение между явно несвязанными частями кода.

+0

Спасибо за очень четкий ответ, теперь я понял. – CtrlAltDel

 Смежные вопросы

  • Нет связанных вопросов^_^