So we set up to now, our program did not actually draw anything. All we did is set up the basics and filled up the colour buffer with the colour blue.
Let’s review that code again.
The function GL.ClearColor. Here is a tip when it comes to figuring out what these kinds of funcitons actually done. There is a lot of refs, Khronos has a lot (the creators of OpenGL), but also funnily enough so does Microsoft, you know the Direct X guys! I actually find Microsoft’s docs actually a little easier to navigate so here is a link to glClearColor:
You can now also use that to look up what GL.Clear does.
Can you see the naming convention? The C# OpenTK does GL.Clear whereas the C++ code uses glClear.
Like I said, nothing was actually drawn.
Now back when I was at Uni, we learned how to use Fixed Function stuff to render things (yeah in 08-12, little bit behind but oh well). However, this is 2018, and shaders are not new. Open GL itself can draw Primitives such as points, lines and triangles. If you know anything about 3D graphics, you know 3D models are made up of lots of triangles, i.e. primitives. Primitives like points, triangles and lines are made up of vertices. In order for stuff to be rendered we need to delve back into the world of vertex and fragment shaders.
You can, in theory, write a shader directly in code in a string array. I am not about that life.
Firstly, we need some boring boilerplate code. I have created 2 files. FileUtils and ShaderUtils.
This is a basic static class that Loads a Text file from the folders route.
Secondly, we have “ShaderUtils”
This is what actually creates our shaders from text input.
But hold up, I hear you say. What is a Vertex and Fragment Shader?
A vertex shader contains the vertex data, i.e. the geometry, which can alter the data of each individual vertex in the model if you so chose. After this has been done, the result is passed to the second step where a function outputs the colour at each vertex. The first step is known as the vertex shader and the second step is known as the fragment shader.
For more info, go check out the Unity shaders
Ok, all of that aside. The above code is loading a parsing the shader data to create something usable.
We are not going to do anything exciting with shaders in this post, we are literally gonna render a red dot.
Start a new class called RedPoint.cs.
This is the class we are gonna use the red dot. We firstly load up the vertex and frag shaders, then create the program.
You will notice an array called _vao. Otherwise known as the Vertex Array Object. A VAO is an OpenGL Object that stores all of the state needed to supply vertex data.
Although the MS docs are good, this time I found they were lacking. So back to Khronos for more info:
We use GL.GenVertexArrays to generate the names of each VAO (in our case there is one).
We then bind the object.
In our draw method, we use the program and use the draw array function to draw points (in this case one).
Basically, we are using this shader program on the points we draw in the primitives.
Cool, so we have how we bind and use the shader, but we actually need to write them.
Create some text files in the following folders:
Make sure the files are Copied to the Output Directory.
Let’s write the shader files.
The vertex shader here literally sets the point to the center of the screen
The out vec4 color part outputs the colour of the pixel. We set this color in the main function.
Add the RedPoint code into Main.cs
If you run the code now:
There is a red point.
Boom, we have loaded a super basic shader and rendered it.