2017-03-14 152 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() 

現在一切正常!