Tutorial 6 is all about textures. In the original tutorial they use a rotating cube so we’ll do the same.
Fortunately the esUtils set of code comes with a handy function esGenCube which will generate vertices, tex coords and indices for drawing a cube. We now have some setup code in our awakeFromNib function:
// create a cube
esGenCube(1.0f, &cubeVertices, NULL, &cubeTexCoords, &cubeIndices);
// load up a texture
textureId=loadTexture(@"texture.png", -1, -1);
To actually draw a texture to the screen we need to modify our shaders. Our vertex shader now needs to take a set of texture coords in addition to the vertice positions. It now looks like:
attribute vec4 position;
attribute vec2 texcoord;
uniform mat4 mvp;
varying mediump vec2 v_texcoord;
void main()
{
gl_Position = mvp * position;
v_texcoord=texcoord;
}
Notice that we now have an attribute called texcoord that we assign to a varying called v_texcoord.
Our fragment shader looks like this:
varying mediump vec2 v_texcoord;
uniform sampler2D texture;
void main()
{
gl_FragColor = texture2D(texture, v_texcoord);
}
This now has a uniform that is of type sampler2D (this will receive our texture) and the varying v_texcoord that will get the tex coord from the vertex shader. It uses the texture2D function to get the correct value from the texture and we assign that to the fragment colour.
Our drawing code now looks like this:
// reset our modelview to identity
esMatrixLoadIdentity(&modelView);
// translate back into the screen by 6 units and down by 1 unit
esTranslate(&modelView, 0.0f , 0.0f, -3.0f);
// rotate the triangle
esRotate(&modelView, rCube, 1.0, 1.0, 0.0);
// tell the GPU we want to use our program
glUseProgram(simpleProgram);
// create our new mvp matrix
esMatrixMultiply(&mvp, &modelView, &projection );
// set the mvp uniform
glUniformMatrix4fv(uniformMvp, 1, GL_FALSE, (GLfloat*) &mvp.m[0][0] );
// set the texture uniform
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureId);
glUniform1i(uniformTexture, 0);
// set the position vertex attribute with our triangle's vertices
glVertexAttribPointer(ATTRIB_POSITION, 3, GL_FLOAT, false, 0, cubeVertices);
glEnableVertexAttribArray(ATTRIB_POSITION);
// set the texture coords
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, 0, 0, cubeTexCoords);
glEnableVertexAttribArray(ATTRIB_TEXCOORD);
// and finally tell the GPU to draw our triangle!
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, cubeIndices);
That’s it! You can find the source code for this project here.