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])
v
和 i
只是指向托管数组第一个元素的指针。
您必须创建 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);
(我是一个非常新的编码员(至少在图形编程方面),所以不要对我太苛刻:( )
今天我尝试使用 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])
v
和 i
只是指向托管数组第一个元素的指针。
您必须创建 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);