Tuesday, March 27, 2012

Part 3: Vertex Data and Shader Source

In this post, I will give you the arrays I will be using for drawing my cube (not a rabbit), both vertices and indices array. I will add a little piece of code that enables some features in OpenGL and the view, and I will set up the ViewPort. Finally, I will add the 2 shader files to my project and write the code for each of them.

Alright, if we want to draw a cube, let's start by adding our cube data at the top of our file, as a global variable.

OpenGL ES can only draw triangles, so each face is made of 4 vertices that make 2 triangles. I am reusing vertices on each face, but not between face. This is simply because I'm thinking ahead, and taking into account that I'm drawing a cube. When I do lighting calculations, I will need each face to be independent to get sharp edges. More details in this thread:

Since I'm reusing vertices for the 2 triangles that make 1 face, I will need to use an array of indices that describe these triangles, also as a global variable.

The order of the indices is important for face culling, as described here:

The next step is to navigate to the ViewDidLoad method and add the following code after the initialization of the view. Ultimately, this piece of code could be added to the template, since you will often use these settings, and it also helps you remember to set them/change them when you need to.

When that's done, you can move on to the shader part. First, you need the to create 2 files and add them to your project. I call them "fragment.glsl" and "vertex.glsl". At the top of the Controller's .m file, add

#define VERTEX_SHADER @"vertex"
#define FRAGMENT_SHADER @"fragment"

I will keep the code of the shaders very simple at the beginning, so here it is:

The vertex shader takes the product of the ModelView and Projection matrices (uniform variable since it doesn't change during the complete drawing of our cube). gl_Position, which is a built-in variable, is the result of that matrix multiplied by the position of each vertex (attribute variable since it represents vertex data).

Internally, the resulting positions will be used to create a primitive assembly, and the rasterisation stage will create the fragments (pixels).

In the fragment shader, we just tell it to draw each of those fragments (pixels) red. This can't be more simple.


bestimmmaa said...

Where's the shader source? Great tutorials btw!

Gabriel Gohier-Roy said...

This really sucks but apparently gist.github.com changed their website and they lost a bunch of my gists. So, the code snippets are just gone...sad face. I'm going to try and see what I can do.

Gabriel Gohier-Roy said...

Seems like the gists that disappeared are only the ones that had their names changed. It wasn't a problem before, but it seems like it can't find the files anymore if the name doesn't match. I fixed a couple of them, let me know if you find more. Thanks!