2013-08-23 2 views
1

Мое приложение разбивается на «glDrawElements» (и glDrawArrays).Crash on glDrawElements

Я хотел бы знать, что может быть причиной аварии?

В настоящее время у меня есть что:

Foreach mesh 

    - Bind VBO/VAO 

      if(VAO empty) 

       - bind VAO(id) 
       - bind VBO(id) 

       Foreach attribs 
        - glEnableVertexAttribArray 
        - glVertexAttribPointer 
       End foreach 

       - unbindVAO(0) 
       - unbindVBO(0) 

       Foreach attribs 
        - glDisableVertexAttribArray 
       End foreach 

      endif 

    - Bind IBO(id) 

    - Bind program/shader(id) 
     -> send uniforms 

    -> glDrawElements 

End foreach 
  • Мое приложение аварии на glDrawElements, когда у меня есть много VBO/ВАО/IBO
  • с различными устройствами, у меня странный артефакт когда у меня много VAO/VBO/IBO

Я думаю, что есть что-то странное с моими буферами (например, конфликт), каков правильный порядок привязок? Где мне нужно развязать VAO, VBO, IBO, программу, текстуру, ...?

EDIT:

Это выглядеть аварии появляются при удалении геометрии, его буферы удаляются из OpenGL (потому что я не использую их больше). Поэтому я думаю, что мои буферы всегда ограничены Oo.

OpenGL трассировки:

glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 8) 
glEnableVertexAttribArray(index = 2) 
glVertexAttribPointer(indx = 2, size = 3, type = GL_FLOAT, normalized = false, stride = 20, ptr = 0x0) 
glEnableVertexAttribArray(index = 0) 
glVertexAttribPointer(indx = 0, size = 4, type = GL_UNSIGNED_BYTE, normalized = true, stride = 20, ptr = 0xc) 
glEnableVertexAttribArray(index = 4) 
glVertexAttribPointer(indx = 4, size = 2, type = GL_UNSIGNED_SHORT, normalized = true, stride = 20, ptr = 0x10) 
glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 0) 
glBindBuffer(target = GL_ELEMENT_ARRAY_BUFFER, buffer = 7) 
glUseProgram(program = 0) 
glUseProgram(program = 6) 
glUniformMatrix4fv(location = 2, count = 1, transpose = false, value = [1.6974937, 0.0, 0.0, 0.0, 0.0, 2.100419, -0.49304545, -0.49301255, 0.0, -1.1902374, -0.87008023, -0.8700222, -9.582167, -2.1815264, 15.627364, 15.64632]) 
glActiveTexture(texture = GL_TEXTURE0) 
glBindTexture(target = GL_TEXTURE_2D, texture = 1) 
glUniform1i(location = 8, x = 0) 
glDisable(cap = GL_BLEND) 
glBlendFunc(sfactor = GL_LINES, dfactor = GL_POINTS) 
glEnable(cap = GL_DEPTH_TEST) 
glUniformMatrix4fv(location = 7, count = 1, transpose = false, value = [50.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 50.0, 0.0, 0.0, -0.1, -150.0, 1.0]) 
glUniform3fv(location = 3, count = 1, v = [0.8235294, 0.8235294, 0.8235294]) 
glUniform2fv(location = 0, count = 1, v = [0.0, 0.0]) 
glUniform2fv(location = 1, count = 1, v = [1.0, 1.0]) 
glDrawElements(mode = GL_TRIANGLE_STRIP, count = 4, type = GL_UNSIGNED_BYTE, indices = 0x0) 
+2

Что вы загружаете на свой VBO, какие аргументы вы передаете glVertexAttribPointer и какие аргументы вы передаете в призывы рисования? Делают (glDrawArrays! = NULL) и (glDrawElements! = NULL)? – thokra

+0

Спасибо за ваш ответ! Я думаю, что все это нормально, потому что я могу нарисовать свою сцену без проблем в большинстве случаев (на устройствах вроде nexus 10, какой-то элемент не появляется Oo). Я видел, что авария произошла, когда я удаляю геометрию/буферы. (Я отредактировал свой пост, чтобы получить трассировку OpenGL) – LongDuZboub

+0

Подождите, вы фактически удалите один из VBOs, с которого вы пытаетесь извлечь данные? Что значит, вам больше не нужна геометрия? – thokra

ответ

0

Если буфер связан с GL_ARRAY_BUFFER при вызове glVertexAttribPointer, указатель берется смещение в буфере. В противном случае это будет указатель на системную память. Таким образом, если нет привязки буфера, и вы передаете недопустимый указатель, такой как нуль (ожидая, что буфер привязан), GL пытается выполнить недопустимое чтение и сбой программы.

То же самое для glDrawElements, если буфер привязан к GL_ELEMENT_ARRAY_BUFFER, аргумент указателя принимается за смещение в буфере.

Здесь буферы GL_ARRAY_BUFFER должны быть связаны только во время вызовов gl * Pointer() и GL_ELEMENT_ARRAY_BUFFER во время вызовов glDrawElements().

Включение состояния клиента Вызов glEnableVertexAttribArray и не предоставление указателя также приведет к сбою.

редактировать

Я считаю, что ВАО просто записывает конфигурацию вершинных атрибутов массивов, связанных буферов и указатели на эти буферы. Чтобы использовать, привяжите VAO, прежде чем настраивать все так, как если бы вы собирались сделать призыв к призыву, а затем отвязать. Теперь, когда вы связываете это VAO, состояние восстанавливается, и вы можете просто сделать призыв к призыву без огромной группы вызовов GL.

bind VAO 
for each attrib, 
    call glEnableVertexAttribArray //in the next draw call, use the VBO I'm about to set up. 
    bind VBO 
    call glVertexAttribPointer //use data in bound VBO with size,stride,offset 
    unbind VBOconfig 
end for 
unbind VAO 
//not certain but are attrib arrays still enabled after unbinding VAO (maybe disabling is unnecessary) 

сейчас для вызова ничьей, свяжите VAO, draw(), отвяжите.

Наконец, для glEnableVertexAttribArray и glVertexAttribPointer Я не знаю, но должен ли индекс быть равномерным местом переменной?

+0

Передача 0 в glVertexAttribPointer всегда работает, независимо от того, привязан ли буфер к ARRAY_BUFFER или нет. Кроме того, в C++ NULL часто определяется как 0. Кроме того, если вы говорите о состоянии клиента, вы пренебрегаете тем, что разрешенные атрибуты являются состояниями VAO, которые предназначены для ядра GL 3.2+ и определенно не являются клиентом. – thokra

+0

Хорошо, спасибо за информацию. Я неограниченную мой VBO после glVertexAttribPointer, но проблема уже здесь :( Это похоже, что сейчас:. glBindBuffer (GL_ARRAY_BUFFER, vertexBuffer-> GetId()) для (...) { glEnableVertexAttribArray (...); glVertexAttribPointer (...);} glBindBuffer (GL_ARRAY_BUFFER, 0); Я использую OpenGL ES 2, так что я не получил glEnableClientState (я редактировал свой пост, чтобы дать свой след OPENGL) – LongDuZboub

+0

@thokra Passing. 0 в качестве указателя, в то время как буфер не связан, но когда выполняется обратный вызов, и OpenGL пытается прочитать данные в местоположении 0 в системной памяти, программа wil l авария. Мой плохой я имел в виду возможность создания массива атрибутов, спасибо (аналогичное следствие, хотя я считаю). Я обновлю ответ. – jozxyqk

3

Вы не должны отключать массивы атрибутов вершины после unbinding a VAO.В основном контексте OpenGL 3, во втором вы отвязываете VAO, у вас больше нет контекста для команд массива вершин, к которым нужно применить; вы всегда должны иметь привязку VAO или эти команды будут недействительными.

Кроме того, VAOs store vertex array state настойчиво. Идея заключается не в том, чтобы включать и отключать состояния каждый раз, когда вы что-то рисуете, а просто связываете VAO, у которого уже установлены все необходимые состояния.

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

Этап 1: GL Vertex Initialization Array/Buffer Object

 
When Mesh is Constructed: 

    - Generate VAO, VBO, IBO 
    - Bind  VAO, VBO, IBO 

    -> Upload Vertex Data to VBO 
    -> Upload Index Array to IBO 

    Foreach Attribute <n> 
    - Setup Attrib Pointer (n) 
    - Enable Attrib Array (n) 
    End Foreach 

Этап 2: Рисунок сетки Instance

 
When an Object (instance of Mesh) is Rendered: 

    - Bind Mesh's VAO 

    - Bind program/shader(id) 
    -> send uniforms 

    -> glDrawElements 

Кроме того, отменяя в ВАО действительно не нужно, если ваше программное обеспечение (например, все, что рисует с использованием вершинных массивов, имеет собственное VAO для управления состоянием). Подумайте о применении текстур, вы редко отвязываете текстуру после того, как рисуете что-то. Вы рассчитываете на следующую партию, которую вы рисуете, зная, какие именно состояния (состояния) текстуры нужны; если ему нужна другая текстура (или вообще ничего), то это должно быть, чтобы изменить состояние текстуры. Восстановление состояния текстуры после каждой партии - это трата ресурсов, и поэтому восстанавливается состояние массива вершин.


На боковой ноте я смотрел ваш след OpenGL и наткнулся на то, о чем вы, возможно, и не подозреваете. Вы используете индексы GL_UNSIGNED_BYTE, которые предоставляются API, но не обязательно поддерживаются аппаратным обеспечением. На большом количестве аппаратных средств (например, на любом настольном графическом процессоре) GL_UNSIGNED_SHORT является предпочтительным типом индекса (даже для очень небольших наборов вершин). Заманчиво предположить, что использование GL_UNSIGNED_BYTE позволит сэкономить место и, следовательно, увеличить пропускную способность, когда у вас будет менее 256 вершин, но это может фактически избавить вас от «быстрого пути». Если аппаратное обеспечение не поддерживает 8-разрядные индексы, то драйвер неизбежно должен будет преобразовать ваши индексы в 16-разрядный после, который вы им отправляете. В таких случаях он увеличивает нагрузку на драйверы и, к сожалению, не сохраняет память графического процессора.