2017-03-14 105 views
1

在VB.Net中使用OpenTK。OpenGL:glDrawElements给出未处理的异常:System.AccessViolationException

我的渲​​染方法:

' clear the screen 
    GL.ClearColor(Color4.Purple) 
    GL.Clear(ClearBufferMask.ColorBufferBit Or ClearBufferMask.DepthBufferBit) 

    ' activate shader program and set uniforms 
    shaderProgram.Use() 
    projectionMatrix.Set(shaderProgram) 

    ' bind vertex buffer and array objects 
    vertexBuffer.Bind() 
    vertexArray.Bind() 

    ' upload vertices to GPU and draw them 
    vertexBuffer.BufferData() 
    vertexArray.enableAll() 
    vertexBuffer.Draw() 

    ' reset state for potential further draw calls (optional, but good practice) 
    vertexArray.DisableAll() 
    GL.BindVertexArray(0) 
    GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0) 
    GL.BindBuffer(BufferTarget.ArrayBuffer, 0) 
    GL.UseProgram(0) 

    ' swap backbuffer 
    SwapBuffers() 

所有这些功能都是抽象的,可以在原来GL {任何}在他们的命令(是的,我无耻地从here复制的代码。)

我vertexbuffer的。绘制代码:

Public Sub Bind() 
    ' make this the active array buffer 
    GL.BindBuffer(BufferTarget.ArrayBuffer, Me.handle) 
End Sub 

Public Sub BufferData() 
    ' copy contained vertices to GPU memory 
    GL.BufferData(BufferTarget.ArrayBuffer, New IntPtr(Me.vertexSize * Me.count), Me.vertices, BufferUsageHint.StreamDraw) 
End Sub 

Public Sub Draw() 
    ' draw buffered vertices as triangles 
    'GL.DrawArrays(PrimitiveType.Triangles, 0, Me.count)  <--commented 
    GL.DrawElements(PrimitiveType.Triangles, 6, DrawElementsType.UnsignedInt, 0) '<--line 44 
End Sub 

这给我的错误:

Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. at OpenTK.Graphics.OpenGL.GL.DrawElements(PrimitiveType mode, Int32 count, DrawElementsType type, Int32 indices) at VertexBuffer`1.Draw() in C:\Users\Tushar\Desktop\genericgamedev-opentk-intro-master\vb\src\Ver texBuffer.vb:line 44

我在某处读到你需要在每次绘制后禁用vertexarrays,所以我也这样做了,但没有效果。 我看到this question但它并没有帮助我(新手)。

相反,在顶点缓冲区的绘制方法中使用glDrawArrays完美呈现。但我不想使用glDrawArrays。

Public Sub Draw() 
    ' draw buffered vertices as triangles 
    GL.DrawArrays(PrimitiveType.Triangles, 0, count) 
    ' commented line --> GL.DrawElements(PrimitiveType.Triangles, 5, DrawElementsType.UnsignedInt, 0) 
End Sub 

回答

0

Got it!

感谢这位先生:DeathByAlgorithm

glDrawElements需要你指定一个索引缓存,是缺乏这我的代码。所以,我创建了一个简单的IBO包装:

Class IndexBuffer 
    Private handle% 
    Private data As UInteger() 
    Sub New(ParamArray Indices As UInteger()) 
     handle = GL.GenBuffer() 
     data = Indices 
    End Sub 
    Public Sub Bind() 
     GL.BindBuffer(BufferTarget.ElementArrayBuffer, handle) 
    End Sub 
    Public Sub BufferData() 
     GL.BufferData(Of UInteger)(BufferTarget.ElementArrayBuffer, CType(Marshal.SizeOf(New UInteger) * data.Length, System.IntPtr), data, BufferUsageHint.StaticDraw) 
    End Sub 
End Class 

,提出在gamewindow类中的字段 “indexbuffer”,并inititalised它:

indexbuffer = New IndexBuffer({0, 1, 2, 3, 4, 5}) 

然后绑定,并在indexbuffer缓冲的数据。我的最终渲染代码:

 ' clear the screen 
    GL.ClearColor(Color4.Purple) 
    GL.Clear(ClearBufferMask.ColorBufferBit Or ClearBufferMask.DepthBufferBit) 

    ' activate shader program and set uniforms 
    shaderProgram.Use() 
    projectionMatrix.Set(shaderProgram) 

    ' bind vertex buffer and array objects 
    vbo.Bind() 
    vertexArray.Bind() 
    indexbuffer.Bind() 

    ' upload vertices to GPU and draw them 
    vbo.BufferData() 
    indexbuffer.BufferData() 

    GL.EnableClientState(ArrayCap.VertexArray) 'works without this line 

    vbo.Draw() 

    ' reset state for potential further draw calls (optional, but good practice) 
    GL.BindVertexArray(0) 
    GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0) 
    GL.BindBuffer(BufferTarget.ArrayBuffer, 0) 
    GL.DisableClientState(ArrayCap.VertexArray) 'works without this line 
    GL.UseProgram(0) 

    ' swap backbuffer 
    SwapBuffers() 

现在一切正常!