OPENGL (GLFW),glDrawElements 给出 "Acces.ViolationException"

OPENGL (GLFW), glDrawElements gives out "Acces.ViolationException"

(我是一个非常新的编码员(至少在图形编程方面),所以不要对我太苛刻:( )

今天我尝试使用 OpenGL (GLFW) 的 C# 实现来渲染一个简单的三角形,我遵循了来自“LearnOpenGL.com”的网络教程,特别是 hello triangle 教程。

我已经完成了整个教程,希望程序能够 运行 并向我展示一个漂亮的三角形,但它给出了错误消息:

_glDrawElements(mode, count, type, indices)
System.AccessViolationException: 'Attempted to read or write protected memory. 
This is often an indication that other memory is corrupt.'"

我搜索了一个解决方案,但遗憾的是没有找到,我完全按照教程检查了我的代码 (这可能是错误所在,因为我需要将它从 C++“转换”为 C#)并且找不到任何错误。

这是我的代码:

class Implementation : App.Game
{

    uint VBO;
    uint VAO;
    uint EBO;
    uint VertexShader;
    uint FragmentShader;
    uint ShaderProgram;

    float[] vertices =
    {
        -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f,
        0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f,
        0.0f,  0.5f, 0.0f, 1.0f, 0.0f, 0.0f
    };

    uint[] indices =
    {
            0, 1, 2,
            1, 2, 3
    };

    public Implementation(int windowWidth, int windowHeight, string windowTitle) : base(windowWidth, windowHeight, windowTitle)
    {
        // StartUp Code hier
    }

    protected override void Initialize()
    {
        // Startet Komponenten und das Spiel
    }

    protected unsafe override void LoadResources()
    {
        // Lädt die hier angegebene Ressourcen

        // ShaderProgram initiieren
        // -
        // Vertex Shader
        VertexShader = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(VertexShader, Shader.vertexShader);
        glCompileShader(VertexShader);
        // Shader-Kompilationsfehler Check
        int[] succes = glGetShaderiv(VertexShader, GL_COMPILE_STATUS, 1);
        if (succes[0] == 0)
        {

            string Error = glGetShaderInfoLog(VertexShader);
            Debug.WriteLine("VERTEX SHADER COMPILATION ERROR | " + Error);

        }
        // -
        // Fragment Shader
        FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(FragmentShader, Shader.fragmentShader);
        glCompileShader(FragmentShader);
        // Shader-Kompilationsfehler Check
        succes = glGetShaderiv(FragmentShader, GL_COMPILE_STATUS, 1);
        if (succes[0] == 0)
        {

            string Error = glGetShaderInfoLog(FragmentShader);
            Debug.WriteLine("FRAGMENT SHADER COMPILATION ERROR | " + Error);

        }
        // -
        // Shader zusammenlinken
        ShaderProgram = glCreateProgram();
        glAttachShader(ShaderProgram, VertexShader);
        glAttachShader(ShaderProgram, FragmentShader);
        glLinkProgram(ShaderProgram);
        // Linker-Fehler Check
        succes = glGetProgramiv(ShaderProgram, GL_LINK_STATUS, 1);
        if (succes[0] == 0)
        {

            string Error = glGetProgramInfoLog(ShaderProgram);
            Debug.WriteLine("SHADER PROGRAM LINKING ERROR | " + Error);

        }
        // Unbenutzte Variablen entfernen
        glDeleteShader(VertexShader);
        glDeleteShader(FragmentShader);

        // Vertex- u. Bufferdaten laden und die Vertex Attribute konfigurieren
        

        glGenVertexArrays(1, (uint*)VAO);
        glGenBuffers(1, (uint*)VBO);
        glGenBuffers(1, (uint*)EBO);

        glBindVertexArray(VAO);

        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        fixed (float* v = &vertices[0])
        { 
            glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.Length, v, GL_STATIC_DRAW);
        }

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
        fixed (uint* i = &indices[0])
        {
            glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint) * indices.Length, i, GL_STATIC_DRAW);
        }

        glVertexAttribPointer(0, 3, GL_FLOAT, false, 3 * sizeof(float), (void*)0);
        glEnableVertexAttribArray(0);

        glBindBuffer(GL_ARRAY_BUFFER, 0);

        glBindVertexArray(0);

    }

    protected unsafe override void Render()
    {
        // Render Code hier
        // -
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        // -
        // Erstes Dreieck
        glUseProgram(ShaderProgram);
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)0);

        Glfw.SwapBuffers(WindowManager.Window);
        Glfw.PollEvents();

    }

    protected override void Update()
    {
        // Führt auf allen Komponenten und auf dem Spiel die Update funktion durch
    }
}

这是着色器代码:

public static string vertexShader = @"#version 330 core
                                layout (location = 0) in vec3 aPosition;
                                void main() 
                                {
                                    gl_Position = vec4(aPosition.x, aPosition.y, aPosition.z, 1.0);
                                }";

    public static string fragmentShader = @"#version 330 core
                                out vec4 FragColor;
                                void main() 
                                {
                                    FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
                                }";

澄清一下,后台代码(LoadResources、Update、Render、Init)都可以正常工作,我检查了很多次。

问题是线条

fixed (float* v = &vertices[0])
fixed (uint* i = &indices[0])

vi 只是指向托管数组第一个元素的指针。

您必须创建 Fixed Size Buffers to transfer the data arrays to the GPU. For instance use Marshal.StructureToPtr 以将数据从托管对象编组到非托管内存块:

using System.Runtime.InteropServices;
int vertexSize = sizeof(float) * vertices.Length;
IntPtr vertexPtr = Marshal.AllocHGlobal(vertexSize);
Marshal.StructureToPtr(vertices, vertexPtr, false);

glBufferData(GL_ARRAY_BUFFER, vertexSize, vertexPtr, GL_STATIC_DRAW);

Marshal.FreeHGlobal(vertexPtr);

int indexSize = sizeof(float) * vertices.Length;
IntPtr indexPtr = Marshal.AllocHGlobal(indexSize);
Marshal.StructureToPtr(indices, indexPtr, false);

glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexSize, indexPtr, GL_STATIC_DRAW);

Marshal.FreeHGlobal(indexPtr);