2015-05-27 3 views
0

Как указано в заголовке, я получаю ошибку gl_INVALID_OPERATION от glDrawElements, однако это происходит только в GL-контексте выше GL 3.1, в контексте 3.1 и ниже он корректно отображает вопросы. Моя модель загружается следующим образом:OpenTK GL.DrawElements, вызывающий ошибку GL_INVALID_OPERATION

public IModel LoadData(Shape a_Shape) { 
     int VertexStride = BlittableValueType<Vertex>.Stride; 
     int IndexStride = sizeof (uint); 

     m_Backing = a_Shape; 

     m_GLDataBuffer = GL.GenBuffer(); 
     GL.BindBuffer(BufferTarget.ArrayBuffer, m_GLDataBuffer); 
     GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr) (m_Backing.Vertices.Count * VertexStride), m_Backing.Vertices.ToArray(), BufferUsageHint.StaticDraw); 

     m_GLIndexBuffer = GL.GenBuffer(); 
     GL.BindBuffer(BufferTarget.ElementArrayBuffer, m_GLIndexBuffer); 
     GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr) (m_Backing.Indices.Count * IndexStride), m_Backing.Indices.ToArray(), BufferUsageHint.StaticDraw); 

     GL.EnableVertexAttribArray(0); 
     GL.EnableVertexAttribArray(1); 
     GL.EnableVertexAttribArray(2); 
     GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, VertexStride, 0); 
     GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, VertexStride, (sizeof (float) * 3)); 
     GL.VertexAttribPointer(2, 2, VertexAttribPointerType.Float, false, VertexStride, (sizeof (float) * 6)); 
     GL.DisableVertexAttribArray(2); 
     GL.DisableVertexAttribArray(1); 
     GL.DisableVertexAttribArray(0); 

     GL.BindBuffer(BufferTarget.ArrayBuffer, 0); 
     GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); 
     return this; 
    } 

Где a_Shape просто произвольная форма загружается из файла или определяется пользователем, он содержит список вершин, которые содержат только два VEctor3 в (Положения и Normal) и Вектор2 (TexCoords). Я тогда нарисовать модель с помощью этой функции:

void IModel.Draw() { 
     GL.BindBuffer(BufferTarget.ElementArrayBuffer, m_GLIndexBuffer); 
     GL.EnableVertexAttribArray(0); 
     GL.EnableVertexAttribArray(1); 
     GL.EnableVertexAttribArray(2); 
     GL.DrawElements(PrimitiveType.Triangles, m_Backing.Indices.Count, DrawElementsType.UnsignedInt, 0); //This is the line that's producing the Error 
     GL.DisableVertexAttribArray(2); 
     GL.DisableVertexAttribArray(1); 
     GL.DisableVertexAttribArray(0); 
     GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); 
    } 

Как я сказал, это работает отлично, пока я пытаюсь использовать GL контекст выше версии 3.1. Я действительно смущен тем, что он не будет работать выше 3.1. Я посмотрел на него, и я это говорит по ссылке OpenGL:

GL_INVALID_OPERATION генерируется, если ненулевое имя объекта буфера связывается с поддержкой массива или массива элементов и хранилище данных объекта буфера в настоящее время отображается.

Я не совсем понимаю, что это значит. Поэтому я предполагаю, что мой вопрос таков: что может заставить glDrawElements работать только в определенных контекстах и ​​как я могу его исправить? Или это проблема с чем-то в моем коде, который я просто не вижу?

Любая помощь была бы очень признательна, примерно через 5 часов, пытаясь понять ее, я подумал, что пришло время обратиться за помощью.

UPDATE

Так я переделывал свой код на следующее:

public IModel LoadData(Shape a_Shape) { 
     m_Backing = a_Shape; 

     Single[] Positions = new Single[a_Shape.Vertices.Count * 3]; 
     Single[] Normals = new Single[a_Shape.Vertices.Count * 3]; 
     Single[] TexCoords = new Single[a_Shape.Vertices.Count * 2]; 

     for (int i = 0; i < Positions.Length; i += 3) { 
      Positions[i + 0] = a_Shape.Vertices[i/3].Position.X; 
      Positions[i + 1] = a_Shape.Vertices[i/3].Position.Y; 
      Positions[i + 2] = a_Shape.Vertices[i/3].Position.Z; 

      Normals[i + 0] = a_Shape.Vertices[i/3].Normal.X; 
      Normals[i + 1] = a_Shape.Vertices[i/3].Normal.Y; 
      Normals[i + 2] = a_Shape.Vertices[i/3].Normal.Z; 
     } 

     for (int i = 0; i < TexCoords.Length; i += 2) { 
      TexCoords[i + 0] = a_Shape.Vertices[i/2].TexCoord.X; 
      TexCoords[i + 1] = a_Shape.Vertices[i/2].TexCoord.Y; 
     } 

     m_GLVertexArray = GL.GenVertexArray(); 
     GL.BindVertexArray(m_GLVertexArray); 
     m_GLIndexBuffer = GL.GenBuffer(); 
     GL.GenBuffers(3, m_GLDataBuffers); 
     GL.EnableVertexAttribArray(0); 
     GL.EnableVertexAttribArray(1); 
     GL.EnableVertexAttribArray(2); 

     GL.BindBuffer(BufferTarget.ElementArrayBuffer, m_GLIndexBuffer); 
     GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr) (sizeof (uint) * a_Shape.Indices.Count), a_Shape.Indices.ToArray(), BufferUsageHint.StaticDraw); 

     GL.BindBuffer(BufferTarget.ArrayBuffer, m_GLDataBuffers[0]); // Bind the Position Buffer 
     GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr) (sizeof (Single) * Positions.Length), Positions, BufferUsageHint.StaticDraw); 
     GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0); 

     GL.BindBuffer(BufferTarget.ArrayBuffer, m_GLDataBuffers[1]); // Bind the Normal Buffer 
     GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr) (sizeof (Single) * Normals.Length), Normals, BufferUsageHint.StaticDraw); 
     GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 0, 0); 

     GL.BindBuffer(BufferTarget.ArrayBuffer, m_GLDataBuffers[2]); // Bind the TexCoord Buffer 
     GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr) (sizeof (Single) * TexCoords.Length), TexCoords, BufferUsageHint.StaticDraw); 
     GL.VertexAttribPointer(2, 2, VertexAttribPointerType.Float, false, 0, 0); 

     GL.BindBuffer(BufferTarget.ArrayBuffer, 0); 
     GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); 
     GL.BindVertexArray(0); 
     return this; 
    } 

Для погрузки и:

void IModel.Draw() { 
     GL.BindVertexArray(m_GLVertexArray); 
     GL.DrawElements(PrimitiveType.Triangles, m_Backing.Indices.Count, DrawElementsType.UnsignedInt, 0); 
     GL.BindVertexArray(0); 
    } 

Для рисования, используя то, что я мог бы найти из комментария Reto. Я больше не получаю никаких ошибок GL, но теперь ничего не получается вообще. Я снова не вижу, где проблема.

EDIT Исправлено неправильное преобразование вершин в положение в положение, нормальный и TexCoord.

+1

Вы, вероятно, получить сердцевину контекст профиля для версий выше 3.1, и ваш код не совместит с основным профилем. См. Например: http://stackoverflow.com/questions/29336227/opengl-3-3-doesnt-draw-anything-using-glsl-330-core. –

+0

@RetoKoradi Я обновил свой код с помощью Vertex Array, но теперь ничего не делает вообще. Я обновил свой основной пост с помощью моего текущего кода. –

+0

Я просто понял, что на самом деле я не храню данные в своих массивах. Я отредактирую свой основной пост, чтобы исправить это. –

ответ

0

Решение моей первоначальной проблемы состояло в том, чтобы использовать массив вершин из-за устаревания от ядра OpenGL 3.1 до OpenGL 3.2 Core, пытаясь выполнить рендеринг без одной ошибки GL_INVALID_OPERATION. Впоследствии у меня возникла еще одна проблема, в которой ничего не выдавалось, это была простая ошибка с моей стороны, а не переустановка GL_ELEMENT_ARRAY_BUFFER. Метод сцена LoadData в основном посте работает должным образом и последний метод Draw выглядит следующим образом:

void IModel.Draw() { 
     GL.BindVertexArray(m_GLVertexArray); 
     GL.BindBuffer(BufferTarget.ElementArrayBuffer, m_GLIndexBuffer); //Rebinding the GL_ELEMENT_ARRAY_BUFFER solved the second issue. 
     GL.DrawElements(PrimitiveType.Triangles, m_Backing.Indices.Count, DrawElementsType.UnsignedInt, 0); 
     GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); 
     GL.BindVertexArray(0); 
    } 

EDIT

После дальнейшего обсуждения я узнал, что, отменяя в GL_ELEMENT_ARRAY_BUFFER (именуемая IBO здесь), прежде чем развязать VAO, VAO обратился к IBO с ID 0, а не к IBO, к которому я так хотел. Ниже приведен последний код, который я использую.

public IModel LoadData(Shape a_Shape) { 
     m_Backing = a_Shape; 

     Single[] Positions = new Single[a_Shape.Vertices.Count * 3]; 
     Single[] Normals = new Single[a_Shape.Vertices.Count * 3]; 
     Single[] TexCoords = new Single[a_Shape.Vertices.Count * 2]; 

     for (int i = 0; i < Positions.Length; i += 3) { 
      Positions[i + 0] = a_Shape.Vertices[i/3].Position.X; 
      Positions[i + 1] = a_Shape.Vertices[i/3].Position.Y; 
      Positions[i + 2] = a_Shape.Vertices[i/3].Position.Z; 

      Normals[i + 0] = a_Shape.Vertices[i/3].Normal.X; 
      Normals[i + 1] = a_Shape.Vertices[i/3].Normal.Y; 
      Normals[i + 2] = a_Shape.Vertices[i/3].Normal.Z; 
     } 

     for (int i = 0; i < TexCoords.Length; i += 2) { 
      TexCoords[i + 0] = a_Shape.Vertices[i/2].TexCoord.X; 
      TexCoords[i + 1] = a_Shape.Vertices[i/2].TexCoord.Y; 
     } 

     m_GLVertexArray = GL.GenVertexArray(); 
     GL.BindVertexArray(m_GLVertexArray); 
     m_GLIndexBuffer = GL.GenBuffer(); 
     GL.GenBuffers(3, m_GLDataBuffers); 

     GL.BindBuffer(BufferTarget.ElementArrayBuffer, m_GLIndexBuffer); 
     GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr) (sizeof (uint) * a_Shape.Indices.Count), a_Shape.Indices.ToArray(), BufferUsageHint.StaticDraw); 

     GL.BindBuffer(BufferTarget.ArrayBuffer, m_GLDataBuffers[0]); // Bind the Position Buffer 
     GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr) (sizeof (Single) * Positions.Length), Positions, BufferUsageHint.StaticDraw); 
     GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0); 
     GL.EnableVertexAttribArray(0); 

     GL.BindBuffer(BufferTarget.ArrayBuffer, m_GLDataBuffers[1]); // Bind the Normal Buffer 
     GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr) (sizeof (Single) * Normals.Length), Normals, BufferUsageHint.StaticDraw); 
     GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 0, 0); 
     GL.EnableVertexAttribArray(1); 

     GL.BindBuffer(BufferTarget.ArrayBuffer, m_GLDataBuffers[2]); // Bind the TexCoord Buffer 
     GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr) (sizeof (Single) * TexCoords.Length), TexCoords, BufferUsageHint.StaticDraw); 
     GL.VertexAttribPointer(2, 2, VertexAttribPointerType.Float, false, 0, 0); 
     GL.EnableVertexAttribArray(2); 

     GL.BindBuffer(BufferTarget.ArrayBuffer, 0); 
     GL.BindVertexArray(0); 
     GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); 
     return this; 
    } 

И:

void IModel.Draw() { 
    GL.BindVertexArray(m_GLVertexArray); 
    GL.DrawElements(PrimitiveType.Triangles, m_Backing.Indices.Count, DrawElementsType.UnsignedInt, 0); 
    GL.BindVertexArray(0); 
} 
+0

Пересылка 'GL_ELEMENT_ARRAY_BUFFER' является частью состояния VAO. Поэтому, если вы привязываете его при настройке VAO, в то время как VAO привязан, вам не придется связывать его снова в методе 'Draw()'. –

+0

Это то, что я предположил, и именно поэтому я удалил вызов, чтобы переподключить его в розыгрыше в первую очередь, поскольку буфер для GL_ELEMENT_ARRAY_BUFFER генерируется, связывается и заполняется после создания и привязки VAO, но даже тогда мне еще нужно переподтвердить его. Если я не смущен тем, что вы говорите. –

+1

Это должно было сработать. В первоначально опубликованном коде у вас также был вызов, чтобы отменить «GL_ELEMENT_ARRAY_BUFFER». Конечно, вы должны удалить это, иначе привязка, хранящаяся в состоянии VAO, будет снова сброшена. –

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