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.