OpenTK OpenGL GL.DrawElements Crash - c#

I'm using OpenTK's GLFW wrapper and OpenGL wrapper. I've run it with both x86 and x64 builds just in case. Installed nuget packages are OpenTK.Graphics and OpenTK.Windowing.GraphicsLibraryFramework and whatever dependencies Visual Studio installs with them.
When I run the code a window opens but is unresponsive. The window crashes a few seconds after opening. OpenGL outputs no debug information to the console nor does C#.
If I comment out GL.DrawElements the window doesn't crash and will properly clear to a black screen and respond to input, but nothing draws to the screen.
This issue persists whether I set the profile to OpenGlProfile.Core or OpenGlProfile.Compat.
GL.DrawArrays does work (in comapat only).
Code
using Engine2D;
namespace Sandbox;
public static class Program
{
public static void Main()
{
var app = new Application();
app.Run();
}
}
using OpenTK.Windowing.GraphicsLibraryFramework;
using OpenTK.Graphics.OpenGL;
namespace Engine2D;
public unsafe sealed class Application
{
private readonly Window* _window;
private static readonly float[] _vertices =
{
-0.5f, -0.5f,
-0.5f, 0.5f,
0.5f, 0.5f,
0.5f, -0.5f
};
private static readonly int[] _indices =
{
0, 1, 2,
3, 0, 2
};
public Application()
{
GLFW.Init();
GLFW.WindowHint(WindowHintOpenGlProfile.OpenGlProfile, OpenGlProfile.Core);
GLFW.WindowHint(WindowHintInt.ContextVersionMajor, 4);
GLFW.WindowHint(WindowHintInt.ContextVersionMinor, 3);
_window = GLFW.CreateWindow(1200, 800, "Engine2D", null, null);
GLFW.MakeContextCurrent(_window);
GL.LoadBindings(new GLFWBindingsContext());
GL.Enable(EnableCap.DebugOutput);
GL.DebugMessageCallback((source, type, id, severity, length, message, userParam) =>
{
if (severity != DebugSeverity.DebugSeverityMedium || severity != DebugSeverity.DebugSeverityHigh)
{
return;
}
string msg = System.Text.Encoding.Default.GetString((byte*)message.ToPointer(), length);
Console.WriteLine(msg);
}, IntPtr.Zero);
}
public void Run()
{
var vao = GL.GenVertexArray();
GL.BindVertexArray(vao);
GL.EnableVertexAttribArray(0);
GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, sizeof(float) * 2, 0);
var vbo = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
GL.BufferData(BufferTarget.ArrayBuffer, sizeof(float) * _vertices.Length, _vertices, BufferUsageHint.StaticDraw);
var ibo = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo);
GL.BufferData(BufferTarget.ElementArrayBuffer, sizeof(int) * _indices.Length, _indices, BufferUsageHint.StaticDraw);
var vertShader = GL.CreateShader(ShaderType.VertexShader);
GL.ShaderSource(vertShader, File.ReadAllText(#"C:\Dev\Engine2D\Sandbox\Standard.vert"));
GL.CompileShader(vertShader);
GL.GetShaderInfoLog(vertShader, out var info);
if (!string.IsNullOrWhiteSpace(info))
{
Console.WriteLine(info);
Console.Read();
}
var fragShader = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(fragShader, File.ReadAllText(#"C:\Dev\Engine2D\Sandbox\Standard.frag"));
GL.CompileShader(fragShader);
GL.GetShaderInfoLog(fragShader, out info);
if (!string.IsNullOrWhiteSpace(info))
{
Console.WriteLine(info);
Console.Read();
}
var program = GL.CreateProgram();
GL.AttachShader(program, vertShader);
GL.AttachShader(program, fragShader);
GL.LinkProgram(program);
GL.ValidateProgram(program);
GL.GetProgramInfoLog(program, out info);
if (!string.IsNullOrWhiteSpace(info))
{
Console.WriteLine(info);
Console.Read();
}
GL.DeleteShader(vertShader);
GL.DeleteShader(fragShader);
while (!GLFW.WindowShouldClose(_window))
{
if (GLFW.GetKey(_window, Keys.Escape) == InputAction.Press)
{
GLFW.SetWindowShouldClose(_window, true);
}
GL.ClearColor(0f, 0f, 0f, 1f);
GL.Clear(ClearBufferMask.ColorBufferBit);
GL.BindVertexArray(vao);
GL.UseProgram(program);
GL.DrawElements(PrimitiveType.Triangles, _indices.Length, DrawElementsType.UnsignedInt, 0);
GLFW.SwapBuffers(_window);
GLFW.PollEvents();
}
GLFW.Terminate();
GL.DeleteVertexArray(vao);
GL.DeleteBuffer(vbo);
GL.DeleteBuffer(ibo);
GL.DeleteProgram(program);
}
}
Shaders
#version 330 core
layout (location = 0) in vec2 aPos;
void main()
{
gl_Position = vec4(aPos, 0.0, 1.0);
}
#version 330 core
out vec4 oColor;
void main()
{
oColor = vec4(1.0, 1.0, 0.0, 1.0);
}
I've been stuck on this for 2 days now. Some help, even a lead, would be greatly appreciated.
Edit
I needed to set the vertex attributes after generating the buffers. For some reason I thought the order didn't matter.

You invoked VertexAttribPointer before creating buffers.
From the document,
If pointer is not NULL, a non-zero named buffer object must be bound to the GL_ARRAY_BUFFER target
Just change the order.
GL.BindVertexArray(vao);
var vbo = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
GL.BufferData(BufferTarget.ArrayBuffer, sizeof(float) * _vertices.Length, _vertices, BufferUsageHint.StaticDraw);
var ibo = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo);
GL.BufferData(BufferTarget.ElementArrayBuffer, sizeof(int) * _indices.Length, _indices, BufferUsageHint.StaticDraw);
GL.EnableVertexAttribArray(0);
GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, sizeof(float) * 2, 0);

Related

OpenTK doesn't render the color of my triangle

I am learning to program a game engine which is why I followed a tutorial, with that tutorial I have gotten this far and even though my code is identical to theirs (theirs did work in the videos) its not working the way it is meant to. The triangle stays black no matter what. There is not any errors.
Main Program Script:
using System;
using OpenTK.Mathematics;
using OpenTK.Windowing.Desktop;
using OpenTK.Windowing.Common;
using System.Drawing;
using OpenTK.Graphics.OpenGL4;
using System.IO;
namespace Game_Engine
{
public static class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
GameWindowSettings gws = GameWindowSettings.Default;
NativeWindowSettings nws = NativeWindowSettings.Default;
gws.IsMultiThreaded = false;
gws.RenderFrequency = 60;
gws.UpdateFrequency = 60;
nws.APIVersion = Version.Parse("4.1.0");
nws.AutoLoadBindings = true;
nws.Size = new Vector2i(1280, 720);
nws.Title = "Horizon";
GameWindow window = new GameWindow(gws, nws);
window.UpdateFrame += (FrameEventArgs args) => {
};
ShaderProgram shaderProgram = new ShaderProgram(){id = 0};
window.Load += () =>
{
Console.WriteLine("Hello");
ShaderProgram shaderProgram = LoadShaderProgram("../../../../vertex_shader.glsl", "../../../../fragment_shader.glsl");
};
window.RenderFrame += (FrameEventArgs args) =>
{
GL.UseProgram( shaderProgram.id );
GL.ClearColor(1.0f, 0.0f, 0.0f, 0.0f);
GL.Clear(ClearBufferMask.ColorBufferBit);
float[] verts = { -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f };
float[] color = { 1f, 0, 0, 0, 1f ,0 ,0, 0, 1f };
int vao = GL.GenVertexArray();
int vertices = GL.GenBuffer();
int colors = GL.GenBuffer();
GL.BindVertexArray(vao);
GL.BindBuffer(BufferTarget.ArrayBuffer, vertices);
GL.BufferData( BufferTarget.ArrayBuffer, verts.Length * sizeof(float), verts, BufferUsageHint.StaticCopy);
GL.EnableVertexAttribArray( 0 );
GL.VertexAttribPointer( 0, 3, VertexAttribPointerType.Float, false, 0, 0 );
GL.BindBuffer(BufferTarget.ArrayBuffer, colors);
GL.BufferData(BufferTarget.ArrayBuffer, color.Length * sizeof(float), color, BufferUsageHint.StaticCopy);
GL.EnableVertexAttribArray(1);
GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 0, 0);
GL.DrawArrays(PrimitiveType.Triangles, 0, 3);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
GL.BindVertexArray(0);
GL.DeleteBuffer(vertices);
GL.DeleteBuffer(colors);
GL.DeleteVertexArray( vao );
window.SwapBuffers();
};
window.Run();
}
private static Shader LoadShader(string shaderLocation, ShaderType type)
{
int shaderId = GL.CreateShader( type );
GL.ShaderSource( shaderId, File.ReadAllText( shaderLocation ) );
GL.CompileShader( shaderId );
string infoLog = GL.GetShaderInfoLog( shaderId );
if (!string.IsNullOrEmpty(infoLog))
{
throw new Exception(infoLog);
}
return new Shader() { id = shaderId };
}
private static ShaderProgram LoadShaderProgram( string vertextShaderLocation, string fragmentShaderLocation)
{
int shaderProgramId = GL.CreateProgram();
Shader vertextShader = LoadShader(vertextShaderLocation, ShaderType.VertexShader);
Shader fragmentShader = LoadShader(fragmentShaderLocation, ShaderType.FragmentShader);
GL.AttachShader(shaderProgramId, vertextShader.id);
GL.AttachShader(shaderProgramId, fragmentShader.id);
GL.LinkProgram(shaderProgramId);
GL.DetachShader(shaderProgramId, vertextShader.id);
GL.DetachShader(shaderProgramId, fragmentShader.id);
GL.DeleteShader(vertextShader.id);
GL.DeleteShader(fragmentShader.id);
string infoLog = GL.GetProgramInfoLog(shaderProgramId);
if (!string.IsNullOrEmpty(infoLog))
{
throw new Exception(infoLog);
}
return new ShaderProgram() { id = shaderProgramId };
}
public struct Shader
{
public int id;
}
public struct ShaderProgram
{
public int id;
}
}
}
Fragment Shader (in glsl):
#version 400
in vec3 color_in;
out vec4 color_out;
void main(){
color_out = vec4(color_in.r, color_in.g, color_in.b, 1);
}
VertexShader (in glsl):
#version 330
layout(location = 0) in vec3 vPosition;
layout(location = 1) in vec3 vColors;
out vec3 color_in;
void main() {
color_in = vColors;
gl_Position = vec4( vPosition, 1.0 );
}
I have tried everything I could with my very limited knowledge of OpenTK and nothing has changed. I have searched on the web and for answer they still have not helped
You actually assign the shader program to a local variable in the event callback function's scope. You need to assign it to the variable in scope of Main:
ShaderProgram shaderProgram = new ShaderProgram() { id = 0 };
window.Load += () =>
{
Console.WriteLine("Hello");
// ShaderProgram shaderProgram = LoadShaderProgram("../../../../vertex_shader.glsl", "../../../../fragment_shader.glsl");
shaderProgram = LoadShaderProgram("../../../../vertex_shader.glsl", "../../../../fragment_shader.glsl");
};

Is this the way to go to render meshes?

I'm learning OpenGL with the openTK librairy in c#.
I've managed to successefuly renderer triangles on my window,
and things are running properly.
However, the performance is terrible (running at half a fps with only 100k triangles).
My question is, is there anything that I am doing badly ?
how could I improve performances ?
for the most part, I've followed this tutorial translated from c++.
Here is the render method, called each frame :
public static void Render()
{
//render the mesh render queue to the screen and clear it
GL.UseProgram(shaderProgram.id);
//meshRenderQueue is a List<Mesh>
foreach(Mesh mesh in meshRenderQueue)
{
mesh.Draw();
}
meshRenderQueue.Clear();
}
Here is my Mesh class :
public class Mesh
{
private Vertex[] vertices;
private uint[] triangles;
private int VAO;
private int VBO;
private int EBO;
public Mesh()
{
//create lots of unoptimized triangles to test performances
int triCount = 100000;
vertices = new Vertex[3 * triCount];
for(int i = 0; i < triCount; i++)
{
vertices[3 * i + 0] = new Vertex(new Vector3(-0.5f, -0.5f, 0f));
vertices[3 * i + 1] = new Vertex(new Vector3(0.5f, -0.5f, 0f));
vertices[3 * i + 2] = new Vertex(new Vector3(0, 0.5f, 0f));
};
triangles = new uint[3 * triCount];
for (int i = 0; i < triCount; i++)
{
triangles[3 * i + 0] = 0;
triangles[3 * i + 1] = 1;
triangles[3 * i + 2] = 2;
};
SetUpMesh();
}
private void SetUpMesh()
{
//initialize the openGL buffers
VAO = GL.GenVertexArray();
VBO = GL.GenBuffer();
EBO = GL.GenBuffer();
GL.BindVertexArray(VAO);
GL.BindBuffer(BufferTarget.ArrayBuffer, VBO);
GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * 8 * 4, vertices, BufferUsageHint.StaticDraw);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, EBO);
GL.BufferData(BufferTarget.ElementArrayBuffer, triangles.Length * sizeof(int), triangles, BufferUsageHint.StaticDraw);
//vertex positions
GL.EnableVertexAttribArray(0);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 8 * 4, 0);
//vertex normals
GL.EnableVertexAttribArray(1);
GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 8 * 4, 3 * 4);
//vertex texture coords
GL.EnableVertexAttribArray(2);
GL.VertexAttribPointer(2, 2, VertexAttribPointerType.Float, false, 8 * 4, 6 * 4);
//unbind vertex array (what for ?)
GL.BindVertexArray(0);
}
public void Draw()
{
//render the mesh with the given shader
GL.BindVertexArray(VAO);
GL.DrawElements(BeginMode.Triangles, triangles.Length, DrawElementsType.UnsignedInt, 0);
GL.BindVertexArray(0);
}
}
And finally the Vertex struct, if usefull :
public struct Vertex
{
public Vector3 position;
public Vector3 normal;
public Vector2 textureCoords;
public Vertex(Vector3 pos, Vector3 norm, Vector2 textCoords)
{
position = pos;
normal = norm;
textureCoords = textCoords;
}
public Vertex(Vector3 pos)
{
position = pos;
normal = Vector3.zero;
textureCoords = new Vector2(0, 0);
}
}
Thanks in advance for any help. cheers !

OpenGL 4.2 LookAt matrix only works with -z value for eye position

I am trying to understand and apply modern OpenGL matrix transformations. I already read a lot of different sources but I am not sure what I am actually doing wrong.
The issue I have is also commented in the code: If I set the eye coordinates of the Matrix4.LookAt to a z value that is greater or equal 0 or lower -2 the triangle is not visible anymore.
Can someone explain why? As far as I understood the method the triangle should just be visible just from the other side (explicitly disabling face culling does not change anything).
Another thing is strange: if i rotate the triangle it seems to get clipped if I use eye-z = -2; if I use -1 it looks "smoother". Any ideas?
Here is the complete program:
using System;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL4;
namespace OGL420_Matrices
{
// OpenTK version 3.1.0
internal class Program
{
public static void Main(string[] args)
{
var program = new Program();
program.Run();
}
private GameWindow _gameWindow;
private Matrix4 _projectionMatrix;
private Matrix4 _viewMatrix;
private Matrix4 _viewProjectionMatrix;
private Matrix4 _modelMatrix;
private int _vbaId, _programId, _viewProjectionUniformId, _modelMatrixUniformId;
private void Run()
{
// 4, 2 is OpenGL 4.2
using (_gameWindow = new GameWindow(800, 600, GraphicsMode.Default, "", GameWindowFlags.Default,
DisplayDevice.Default, 4, 2, GraphicsContextFlags.Default))
{
_gameWindow.Load += OnLoad;
_gameWindow.Resize += OnResize;
_gameWindow.RenderFrame += OnRenderFrame;
_gameWindow.Run();
}
}
private void OnResize(object sender, EventArgs e)
{
var clientArea = _gameWindow.ClientRectangle;
GL.Viewport(0, 0, clientArea.Width, clientArea.Height);
}
private void OnLoad(object sender, EventArgs e)
{
_projectionMatrix = Matrix4.CreateOrthographic(3, 3, 0.001f, 50);
// change -1 to -2.1f you dont see anything
// change -1 to -2f you still see the same
// change -1 to >= 0 you dont see anything; of course 0 doesn't make sense but 1 would
_viewMatrix = Matrix4.LookAt(
new Vector3(0, 0, -1f), // eye
new Vector3(0, 0, 0), // target
new Vector3(0, 1, 0)); // up
_modelMatrix = Matrix4.Identity;
var data = new float[]
{
0, 0, 0,
1, 0, 0,
0, 1, 0
};
var vboId = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, vboId);
GL.BufferData(BufferTarget.ArrayBuffer, data.Length * sizeof(float), data, BufferUsageHint.StaticDraw);
_vbaId = GL.GenVertexArray();
GL.BindVertexArray(_vbaId);
GL.BindBuffer(BufferTarget.ArrayBuffer, vboId);
GL.EnableVertexAttribArray(0);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
var vertexShaderId = GL.CreateShader(ShaderType.VertexShader);
GL.ShaderSource(vertexShaderId, #"#version 420
layout(location = 0) in vec3 position;
uniform mat4 viewProjection;
uniform mat4 model;
out vec3 outColor;
void main()
{
gl_Position = viewProjection * model * vec4(position, 1);
outColor = vec3(1,1,1);
}");
GL.CompileShader(vertexShaderId);
GL.GetShader(vertexShaderId, ShaderParameter.CompileStatus, out var result);
if (result != 1)
throw new Exception("compilation error: " + GL.GetShaderInfoLog(vertexShaderId));
var fragShaderId = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(fragShaderId, #"#version 420
in vec3 outColor;
out vec4 fragmentColor;
void main()
{
fragmentColor = vec4(outColor, 1);
}");
GL.CompileShader(fragShaderId);
GL.GetShader(fragShaderId, ShaderParameter.CompileStatus, out result);
if (result != 1)
throw new Exception("compilation error: " + GL.GetShaderInfoLog(fragShaderId));
_programId = GL.CreateProgram();
GL.AttachShader(_programId, vertexShaderId);
GL.AttachShader(_programId, fragShaderId);
GL.LinkProgram(_programId);
GL.GetProgram(_programId, GetProgramParameterName.LinkStatus, out var linkStatus);
if (linkStatus != 1) // 1 for true
throw new Exception("Shader program compilation error: " + GL.GetProgramInfoLog(_programId));
GL.DeleteShader(vertexShaderId);
GL.DeleteShader(fragShaderId);
_viewProjectionUniformId = GL.GetUniformLocation(_programId, "viewProjection");
_modelMatrixUniformId = GL.GetUniformLocation(_programId, "model");
}
private void OnRenderFrame(object sender, FrameEventArgs e)
{
GL.Clear(ClearBufferMask.ColorBufferBit);
_viewProjectionMatrix = _projectionMatrix * _viewMatrix;
GL.UniformMatrix4(_viewProjectionUniformId, false, ref _viewProjectionMatrix);
GL.UniformMatrix4(_modelMatrixUniformId, false, ref _modelMatrix);
GL.UseProgram(_programId);
GL.BindVertexArray(_vbaId);
GL.DrawArrays(PrimitiveType.Triangles, 0, 3);
_gameWindow.SwapBuffers();
}
}
}
First I'll quote a comment to the OpenTK issue: Problem with matrices #687:
Because of how matrices are treated in C# and OpenTK, multiplication order is inverted from what you might expect in C/C++ and GLSL. This is an old artefact in the library, and it's too late to change now, unfortunately.
In compare to glsl, where column major order matrices have to be multiplied form the right to the left, where the right matrix is the matrix which is applied "first", in OpenTK the matrices have to be multiplied from the left to the right.
This means, if you want to calculate the viewProjectionMatrix in glsl, which does the view transformation followed by the projection, then in glsl it is (for column major order matrices):
mat4 viewProjectionMatrix = projectionMatrix * viewMatrix;
If you want to do the same in in OpenTK, by the use of Matrix4, then you've to do:
_viewProjectionMatrix = _viewMatrix * _projectionMatrix;

OpenTK triangle is always white

I want to draw a colored triangle in OpenTK using a simple fragment shader with a fixed output color. However, the triangle always stays white. What causes this problem?
Here is the init and render code:
game.Load += (sender, e) =>
{
game.VSync = VSyncMode.On;
float[] vertexPositions = {
0.75f, 0.75f, 0.0f, 1.0f,
0.75f, -0.75f, 0.0f, 1.0f,
-0.75f, -0.75f, 0.0f, 1.0f,
};
GL.GenBuffers(1, out vbo);
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(
vertexPositions.Length * sizeof(float)), vertexPositions, BufferUsageHint.StaticDraw);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
// load shaders, create and link shader program
string shaderPath = #"K:\VisualProjects\ArcSynthesis\Tut2\Tut2\shaders\";
shVertex = new VertexShader(new System.IO.FileInfo(shaderPath + "vertex.glsl"));
shFragment = new FragShader(new System.IO.FileInfo(shaderPath + "fragment.glsl"));
spMain = new ShaderProgram(shVertex, shFragment);
spMain.Link();
};
and
game.RenderFrame += (sender, e) =>
{
GL.ClearColor(0f, 0f, 0f, 0f);
GL.Clear(ClearBufferMask.ColorBufferBit);
spMain.Use();
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
GL.EnableVertexAttribArray(0);
GL.VertexAttribPointer(0, 4, VertexAttribPointerType.Float, false, 0, 0);
GL.DrawArrays(PrimitiveType.Triangles, 0, 3);
GL.DisableVertexAttribArray(0);
GL.UseProgram(0);
game.SwapBuffers();
};
Vertex shader:
#version 130
in vec4 position;
void main()
{
gl_Position = position;
}
Fragment shader:
#version 130
out vec4 outputColor;
void main()
{
outputColor = vec4(0.2f, 0.5f, 0.8f, 1.0f);
}
So I found out that the problem was the line
GL.UseProgram(0);
The shader program class I use (found in some forum) implements the glUseProgram() function like this:
public IDisposable Use()
{
IDisposable r = new ShaderProgram.Handle(curr_program);
if (curr_program != ID)
{
GL.UseProgram(ID);
curr_program = ID;
}
return r;
}
It only calls glUseProgram() if another ShaderProgram has previously set the static int curr_program to its own ID. It does nothing if the GL shader program has been set to 0 manually by calling GL.UseProgram(0).
I simply removed the line and everything is working now.

C# OpenTK GLSL Crashing on attempting to render

I've been trying to implement GLSL into my program, however given that i have never used GLSL before, i decided I would try following a tutorial. Unfortunately following tutorials aren't my forte, and I am stuck here with my program crashing when 'RenderTerrain()' is called (in the second line of code of the function (GL.DrawElements))
Now this obviously all the code in the program, there is A LOT more, there's no chance any of you would go through 20k lines to find my problem :P But if you need to ask questions about any of it, please comment :)
So my question simply is, is there anything wrong with this code? Why would it be crashing?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenTK.Graphics.OpenGL;
using OpenTK;
namespace HoardOfUpgrades
{
public class Shaders
{
private static string TerrainVertexShaderText = #"
#version 140
// object space to camera space transformation
uniform mat4 modelview_matrix;
// camera space to clip coordinates
uniform mat4 projection_matrix;
// incoming vertex position
in vec3 vertex_position;
// incoming vertex normal
in vec3 vertex_normal;
// incoming vertex_color
in vec3 vertex_color
// transformed vertex normal
out vec3 normal;
void main(void)
{
//not a proper transformation if modelview_matrix involves non-uniform scaling
normal = ( modelview_matrix * vec4( vertex_normal, 0 ) ).xyz;
// transforming the incoming vertex position
gl_Position = projection_matrix * modelview_matrix * vec4( vertex_position, 1 );
}
";
private static string TerrainFragmentShaderText = #"
#version 140
precision highp float;
const vec3 ambient = vec3( 0.1, 0.1, 0.1 );
const vec3 lightVecNormalized = normalize( vec3( 0.5, 0.5, 2 ) );
const vec3 lightColor = vec3( 1.0, 0.8, 0.2 );
in vec3 normal;
out vec4 out_frag_color;
void main(void)
{
float diffuse = clamp( dot( lightVecNormalized, normalize( normal ) ), 0.0, 1.0 );
out_frag_color = vec4( ambient + diffuse * lightColor, 1.0 );
}
";
public static int TerrainFragmentShaderHandle, TerrainVertexShaderHandle, TerrainProgramHandle, ProjectionMatrixLocation, ModelviewMatrixLocation, TerrainNormHandle, TerrainPosHandle, TerrainColorHandle, TerrainIndicesHandle, TerrainIndiceCount;
public static void Load(Vector3[] position, Vector3[] normals, Vector3[] colors, int[] indices)
{
LoadShaders();
LoadProgram();
LoadVertexPositions(position);
LoadVertexNormals(normals);
LoadVertexColors(colors);
LoadIndexer(indices);
}
static void LoadProgram()
{
TerrainProgramHandle = GL.CreateProgram();
GL.AttachShader(TerrainProgramHandle, TerrainVertexShaderHandle);
GL.AttachShader(TerrainProgramHandle, TerrainVertexShaderHandle);
GL.LinkProgram(TerrainProgramHandle);
}
static void LoadShaders()
{
TerrainVertexShaderHandle = GL.CreateShader( ShaderType.VertexShader );
TerrainFragmentShaderHandle = GL.CreateShader( ShaderType.FragmentShader );
GL.ShaderSource(TerrainVertexShaderHandle, TerrainVertexShaderText);
GL.ShaderSource(TerrainFragmentShaderHandle, TerrainFragmentShaderText);
GL.CompileShader(TerrainVertexShaderHandle);
GL.CompileShader(TerrainFragmentShaderHandle);
}
private static void QueryMatrixLocations()
{
ProjectionMatrixLocation = GL.GetUniformLocation(TerrainProgramHandle, "projection_matrix");
ModelviewMatrixLocation = GL.GetUniformLocation(TerrainProgramHandle, "modelview_matrix");
}
public static void SetModelviewMatrix(Matrix4 matrix)
{
GL.UniformMatrix4(ModelviewMatrixLocation, false, ref matrix);
}
public static void SetProjectionMatrix(Matrix4 matrix)
{
GL.UniformMatrix4(ProjectionMatrixLocation, false, ref matrix);
}
private static void LoadVertexPositions(Vector3[] data)
{
GL.GenBuffers(1, out TerrainPosHandle);
GL.BindBuffer(BufferTarget.ArrayBuffer, TerrainPosHandle);
GL.BufferData<Vector3>(BufferTarget.ArrayBuffer,
new IntPtr(data.Length * Vector3.SizeInBytes),
data, BufferUsageHint.StaticDraw);
GL.EnableVertexAttribArray(0);
GL.BindAttribLocation(TerrainProgramHandle, 0, "vertex_position");
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, Vector3.SizeInBytes, 0);
}
private static void LoadVertexNormals(Vector3[] data)
{
GL.GenBuffers(1, out TerrainNormHandle);
GL.BindBuffer(BufferTarget.ArrayBuffer, TerrainNormHandle);
GL.BufferData<Vector3>(BufferTarget.ArrayBuffer,
new IntPtr(data.Length * Vector3.SizeInBytes),
data, BufferUsageHint.StaticDraw);
GL.EnableVertexAttribArray(1);
GL.BindAttribLocation(TerrainProgramHandle, 1, "vertex_normal");
GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, Vector3.SizeInBytes, 0);
}
private static void LoadVertexColors(Vector3[] data)
{
GL.GenBuffers(1, out TerrainColorHandle);
GL.BindBuffer(BufferTarget.ArrayBuffer, TerrainColorHandle);
GL.BufferData<Vector3>(BufferTarget.ArrayBuffer,
new IntPtr(data.Length * Vector3.SizeInBytes),
data, BufferUsageHint.StaticDraw);
GL.EnableVertexAttribArray(1);
GL.BindAttribLocation(TerrainProgramHandle, 1, "vertex_color");
GL.VertexAttribPointer(2, 3, VertexAttribPointerType.Float, false, Vector3.SizeInBytes, 0);
}
private static void LoadIndexer(int[] data)
{
TerrainIndiceCount = data.Length;
GL.GenBuffers(1, out TerrainIndicesHandle);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, TerrainIndicesHandle);
GL.BufferData<int>(BufferTarget.ElementArrayBuffer,
new IntPtr(data.Length * sizeof(int)),
data, BufferUsageHint.StaticDraw);
}
public static void RenderTerrain()
{
GL.UseProgram(TerrainProgramHandle);
GL.DrawElements(BeginMode.Triangles, TerrainIndiceCount,
DrawElementsType.UnsignedInt, IntPtr.Zero);
GL.UseProgram(0);
}
}
}
These lines of code must be included:
GL.DisableClientState(ArrayCap.NormalArray);
GL.DisableClientState(ArrayCap.VertexArray);
GL.DisableClientState(ArrayCap.TextureCoordArray);
Arrays were enabled, they must be disabled to use the GL.DrawElements() function

Categories