Reputation: 1313
I am using OpenGL.net (Available through NuGet) with C# and I am trying to put together a minimal working example for modern OpenGL.
Clearing the screen and Shader Conpilation works, however I am getting an AccessViolationException in the Gl.DrawArrays call on line 158.
What I have done so far:
Code:
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();
}
}
}
Vertex Shader:
#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;
}
Fragment Shader:
#version 330 core
out vec4 color;
void main() {
color = vec4(1, 0, 0, 0);
}
I have no clue what is wrong at this point, any help is greatly appreciated.
Upvotes: 2
Views: 761
Reputation: 11981
I suspect that
Gl.BufferData(BufferTargetARB.ArrayBuffer, /*sizeof(float)*(uint)_ArrayPosition.Length*/ 100, vertexArrayLock.Address, BufferUsageARB.DynamicDraw);
is the root of the problem. You are telling to OpenGL to define a buffer of 100 bytes, and initialize the content from vertexArrayLock.Address
. Sadly, vertexArrayLock.Address
points to a memory large 6 * sizeof(float) = 24 bytes.
However, I don't understand why you're getting exception on DrawArrays
; probably there are other issues I didn't see.
--- Few minutes later ---
Got it. Remove the line:
Gl.BindBuffer(BufferTargetARB.ArrayBuffer, 0);
from glc_screen_ContextCreated
. It will alter the VAO state in a way that no buffer is used. Focus of VAO state vector, and you'll get a successfull DrawArrays.
Upvotes: 2