我正在使用OpenGL.net(通过NuGet提供)和C#,我正在尝试为现代OpenGL组建一个最小的工作示例。
清除屏幕和Shader Conpilation有效,但我在第158行的 Gl.DrawArrays 调用中收到 AccessViolationException 。
到目前为止我做了什么:
代码:
using System;
using System.Text;
using System.Windows.Forms;
using System.IO;
using OpenGL;
using System.Runtime.ExceptionServices;
namespace RenderEngine
{
public class RenderForm : Form
{
private Timer tmr_Render;
private System.ComponentModel.IContainer components;
private GlControl glc_screen;
MemoryLock vertexArrayLock;
uint vertexArrayID;
uint vertexbuffer;
uint shaderProgram;
private static readonly float[] _ArrayPosition = new float[] {
0.0f, 0.0f,
0.5f, 1.0f,
1.0f, 0.0f
};
private static readonly float[] _ArrayColor = new float[] {
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f
};
public RenderForm()
{
InitializeComponent();
}
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.glc_screen = new OpenGL.GlControl();
this.tmr_Render = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
//
// glc_screen
//
this.glc_screen.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
this.glc_screen.ColorBits = ((uint)(24u));
this.glc_screen.DepthBits = ((uint)(0u));
this.glc_screen.Dock = System.Windows.Forms.DockStyle.Fill;
this.glc_screen.Location = new System.Drawing.Point(0, 0);
this.glc_screen.MultisampleBits = ((uint)(0u));
this.glc_screen.Name = "glc_screen";
this.glc_screen.Size = new System.Drawing.Size(784, 561);
this.glc_screen.StencilBits = ((uint)(0u));
this.glc_screen.TabIndex = 0;
this.glc_screen.ContextCreated += new System.EventHandler<OpenGL.GlControlEventArgs>(this.glc_screen_ContextCreated);
this.glc_screen.Render += new System.EventHandler<OpenGL.GlControlEventArgs>(this.glc_screen_Render);
//
// tmr_Render
//
this.tmr_Render.Enabled = true;
this.tmr_Render.Interval = 16;
this.tmr_Render.Tick += new System.EventHandler(this.tmr_Render_Tick);
//
// RenderForm
//
this.ClientSize = new System.Drawing.Size(784, 561);
this.Controls.Add(this.glc_screen);
this.Name = "RenderForm";
this.ResumeLayout(false);
}
private void glc_screen_ContextCreated(object sender, GlControlEventArgs e)
{
GlControl glControl = (GlControl)sender;
shaderProgram = LoadShaders("../../../RenderEngine/vertex.shader", "../../../RenderEngine/fragment.shader");
vertexArrayID = Gl.GenVertexArray();
Gl.BindVertexArray(vertexArrayID);
Gl.EnableVertexAttribArray(vertexArrayID);
vertexArrayLock = new MemoryLock(_ArrayPosition);
vertexbuffer = Gl.GenBuffer();
Gl.BindBuffer(BufferTargetARB.ArrayBuffer, vertexbuffer);
Gl.BufferData(BufferTargetARB.ArrayBuffer, /*sizeof(float)*(uint)_ArrayPosition.Length*/ 100, vertexArrayLock.Address, BufferUsageARB.DynamicDraw);
int indexInShader = 0;// Gl.GetAttribLocation(shaderProgram, "vertexPosition_modelspace");
int floatsPerVertex = 2;
bool normalized = false;
int stride = floatsPerVertex*sizeof(float);
int arrayBufferOffset = 0;
Gl.VertexAttribPointer((uint)indexInShader, floatsPerVertex, Gl.FLOAT, normalized, stride, arrayBufferOffset);
Gl.BindBuffer(BufferTargetARB.ArrayBuffer, 0);
}
private uint LoadShaders(string vertexPath, string fragmentPath) {
uint vertexShaderId = Gl.CreateShader(Gl.VERTEX_SHADER);
uint fragmentShaderId = Gl.CreateShader(Gl.FRAGMENT_SHADER);
string vertexCode = File.ReadAllText(vertexPath);
string fragmentCode = File.ReadAllText(fragmentPath);
int vertexResult;
int vertexInfoLogLength;
StringBuilder vertexInfoLog = new StringBuilder(200);
Gl.ShaderSource(vertexShaderId, new string[] { vertexCode }/*vertexCode.Split(new char[] { '\r', '\n' })*/);
Gl.CompileShader(vertexShaderId);
Gl.GetShader(vertexShaderId, Gl.COMPILE_STATUS, out vertexResult);
Gl.GetShaderInfoLog(vertexShaderId, 200, out vertexInfoLogLength, vertexInfoLog);
Console.WriteLine(vertexInfoLog.Length == 0 ? "Vertex shader compiled sucessfully" : vertexInfoLog.ToString());
int fragmentResult;
int fragmentInfoLogLength;
StringBuilder fragmentInfoLog = new StringBuilder(200);
Gl.ShaderSource(fragmentShaderId, new string[] { fragmentCode }/*fragmentCode.Split(new char[] { '\r', '\n' })*/);
Gl.CompileShader(fragmentShaderId);
Gl.GetShader(fragmentShaderId, Gl.COMPILE_STATUS, out fragmentResult);
Gl.GetShaderInfoLog(fragmentShaderId, 200, out fragmentInfoLogLength, fragmentInfoLog);
Console.WriteLine(fragmentInfoLog.Length==0 ? "Fragment shader compiled sucessfully" : fragmentInfoLog.ToString());
uint programId = Gl.CreateProgram();
Gl.AttachShader(programId, vertexShaderId);
Gl.AttachShader(programId, fragmentShaderId);
Gl.LinkProgram(programId);
int programResult;
int programInfoLogLength;
StringBuilder programInfoLog = new StringBuilder(200);
Gl.GetProgram(programId, Gl.LINK_STATUS, out programResult);
Gl.GetProgramInfoLog(programId, 200, out programInfoLogLength, programInfoLog);
Console.WriteLine(programInfoLog.Length == 0 ? "Program linked sucessfully" : programInfoLog.ToString());
Gl.DetachShader(programId, vertexShaderId);
Gl.DetachShader(programId, fragmentShaderId);
Gl.DeleteShader(vertexShaderId);
Gl.DeleteShader(fragmentShaderId);
return programId;
}
private void glc_screen_Render(object sender, GlControlEventArgs e)
{
GlControl senderControl = (GlControl)sender;
Gl.BindVertexArray(vertexArrayID);
Gl.BindBuffer(BufferTargetARB.ArrayBuffer, vertexbuffer);
Gl.CheckErrors();
Console.WriteLine(Gl.GetError());
int floatsPerVertex = 2;
int start = 0;
int verticies = _ArrayPosition.Length / floatsPerVertex;
Gl.Clear(ClearBufferMask.ColorBufferBit);
Gl.ClearColor(1f, .5f, 1f, 0f);
Gl.UseProgram(shaderProgram);
Gl.DrawArrays(PrimitiveType.Triangles, start, verticies);
Gl.DisableVertexAttribArray(vertexArrayID);
}
private void tmr_Render_Tick(object sender, EventArgs e)
{
glc_screen.Invalidate();
}
}
}
顶点着色器:
#version 330 core
layout(location = 0) in vec2 vertexPosition_modelspace;
void main() {
gl_Position.xy = vertexPosition_modelspace;
gl_Position.z = 1.0;
gl_Position.w = 1.0;
}
片段着色器:
#version 330 core
out vec4 color;
void main() {
color = vec4(1, 0, 0, 0);
}
我不知道此时出了什么问题,非常感谢任何帮助。
答案 0 :(得分:1)
我怀疑
Gl.BufferData(BufferTargetARB.ArrayBuffer, /*sizeof(float)*(uint)_ArrayPosition.Length*/ 100, vertexArrayLock.Address, BufferUsageARB.DynamicDraw);
是问题的根源。您告诉OpenGL定义一个100字节的缓冲区,并从vertexArrayLock.Address
初始化内容。遗憾的是,vertexArrayLock.Address
指向一个大6 * sizeof(float)= 24字节的内存。
但是,我不明白为什么你会在DrawArrays
上获得例外;可能还有其他问题我没有看到。
---几分钟后---
知道了。删除行:
Gl.BindBuffer(BufferTargetARB.ArrayBuffer, 0);
来自glc_screen_ContextCreated
。它将以不使用缓冲区的方式改变VAO状态。 VAO状态向量的焦点,你将获得一个成功的DrawArrays。