# Texture Mapping

Hello everyone,

I would like to apply a texture mapping on my cube (to learn OpenGL) in order to have different textures on each face of my cube with only one bitmap file. How can I do that ?

Thanks !

## Comment viewing options

### Re: Texture Mapping

You have to define per vertex texture coordinates for your cube and create a texture atlas as bitmap file that contains all desired textures. For a cube, this is quite simple, as you can define the texture coordinates by hand. For more complex objects, you usually use a tool to unwrap your 3D object to a plane. Look up the bold keywords for further explanations. If you want to use a different texture for each face, you will notice that regular per vertex texture coordinates produce false results, as each vertex is shared among 3 faces. Thus, you have to replicate the vertices for each face, i.e. instead of drawing 8 vertices which define a cube, you have to draw 6 * 4 vertices which define the individual faces. Having done that, you can assign texture coordinates.

Have you already managed to map the same texture to each face of the vertex? The texture coordinates for the four vertices of one face would be (0, 0), (1, 0), (1, 1), (0, 1) - the float values between 0 and 1 represent the position inside a texture, i.e. (0, 0) is the lower left corner, (1, 1) is the upper right corner of the texture, (0.5, 0.5) is the center.

To map different textures, you divide your texture atlas into different sectors. For the 6 faces of your cube you could use a texture with a width divisible by 6, e.g. 6 * 256 = 1536 x 256 pixels. Now you can assign the texture coordinates to your face vertices as follows:

First face:
Lower left vertex: (0, 0)
Lower right vertex: (1/6, 0)
Upper right vertex: (1/6, 1)
Upper left vertex: (0, 1)

Second face:
Lower left vertex: (1/6, 0)
Lower right vertex: (2/6, 0)
Upper right vertex: (2/6, 1)
Upper left vertex: (1/6, 1)

...

Sixth face:
Lower left vertex: (5/6, 0)
Lower right vertex: (1, 0)
Upper right vertex: (1, 1)
Upper left vertex: (5/6, 1)

Is this clear?

### Re: Texture Mapping

Thanks ! So I have to define a Texture Matrix and what's next ? Could you give me a little example of the texturing part of a cube ?

### Re: Texture Mapping

No, the texture matrix is not what you want. You use a texture matrix if you want to transform a texture on the object, not for regular texture mapping. Instead, you have to use UV mapping (that's the thingy with the texture coordinates). You pass the per-vertex texture coordinates to the video card as attributes to your vertices. Doing this in a forward compatible way:

```uint[] indices = new uint[] {
// front face
0, 1, 2, 2, 3, 0,

// back face
4, 5, 6, 6, 7, 4,

// left face
8, 9, 10, 10, 11, 8,

// right face
12, 13, 14, 14, 15, 12,

// top face
16, 17, 18, 18, 19, 16,

// bottom face
20, 21, 22, 22, 23, 20
};

Vector3[] normals = new Vector3[] {
// front face
new Vector3(0.0f, 0.0f, 1.0f),
new Vector3(0.0f, 0.0f, 1.0f),
new Vector3(0.0f, 0.0f, 1.0f),
new Vector3(0.0f, 0.0f, 1.0f),

// back face
new Vector3(0.0f, 0.0f, -1.0f),
new Vector3(0.0f, 0.0f, -1.0f),
new Vector3(0.0f, 0.0f, -1.0f),
new Vector3(0.0f, 0.0f, -1.0f),

// left face
new Vector3(1.0f, 0.0f, 0.0f),
new Vector3(1.0f, 0.0f, 0.0f),
new Vector3(1.0f, 0.0f, 0.0f),
new Vector3(1.0f, 0.0f, 0.0f),

// right face
new Vector3(-1.0f, 0.0f, 0.0f),
new Vector3(-1.0f, 0.0f, 0.0f),
new Vector3(-1.0f, 0.0f, 0.0f),
new Vector3(-1.0f, 0.0f, 0.0f),

// top face
new Vector3(0.0f, 1.0f, 0.0f),
new Vector3(0.0f, 1.0f, 0.0f),
new Vector3(0.0f, 1.0f, 0.0f),
new Vector3(0.0f, 1.0f, 0.0f),

// bottom face
new Vector3(0.0f, -1.0f, 0.0f),
new Vector3(0.0f, -1.0f, 0.0f),
new Vector3(0.0f, -1.0f, 0.0f),
new Vector3(0.0f, -1.0f, 0.0f)
};

Vector4[] vertices = new Vector4[] {
// front face
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f),
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f),
new Vector4(1.0f, -1.0f, 1.0f, 1.0f),
new Vector4(1.0f, 1.0f, 1.0f, 1.0f),

// back face
new Vector4(1.0f, 1.0f, -1.0f, 1.0f),
new Vector4(1.0f, -1.0f, -1.0f, 1.0f),
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f),
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f),

// left face
new Vector4(1.0f, 1.0f, 1.0f, 1.0f),
new Vector4(1.0f, -1.0f, 1.0f, 1.0f),
new Vector4(1.0f, -1.0f, -1.0f, 1.0f),
new Vector4(1.0f, 1.0f, -1.0f, 1.0f),

// right face
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f),
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f),
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f),
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f),

// top face
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f),
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f),
new Vector4(1.0f, 1.0f, 1.0f, 1.0f),
new Vector4(1.0f, 1.0f, -1.0f, 1.0f),

// bottom face
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f),
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f),
new Vector4(1.0f, -1.0f, -1.0f, 1.0f),
new Vector4(1.0f, -1.0f, 1.0f, 1.0f)
};

Vector2[] texCoords = new Vector2[] {
// front face
new Vector2(0.0f, 0.0f),
new Vector2(0.0f, 1.0f),
new Vector2(1.0f, 1.0f),
new Vector2(1.0f, 0.0f),

// back face
new Vector2(0.0f, 0.0f),
new Vector2(0.0f, 1.0f),
new Vector2(1.0f, 1.0f),
new Vector2(1.0f, 0.0f),

// left face
new Vector2(0.0f, 0.0f),
new Vector2(0.0f, 1.0f),
new Vector2(1.0f, 1.0f),
new Vector2(1.0f, 0.0f),

// right face
new Vector2(0.0f, 0.0f),
new Vector2(0.0f, 1.0f),
new Vector2(1.0f, 1.0f),
new Vector2(1.0f, 0.0f),

// top face
new Vector2(0.0f, 0.0f),
new Vector2(0.0f, 1.0f),
new Vector2(1.0f, 1.0f),
new Vector2(1.0f, 0.0f),

// bottom face
new Vector2(0.0f, 0.0f),
new Vector2(0.0f, 1.0f),
new Vector2(1.0f, 1.0f),
new Vector2(1.0f, 0.0f)
};

// vertex array object
GL.GenVertexArrays(1, out this.vertexArray);
GL.BindVertexArray(this.vertexArray);

// get the locations of the shader fields which you want to bind your buffers to
// (this assumes that you have the in fields vec4 inPosition, vec3 inNormal and vec2 inTexCoord in your shader!)

// vertex buffer
GL.GenBuffers(1, out this.vertexBuffer);
GL.BindBuffer(BufferTarget.ArrayBuffer, this.vertexBuffer);
GL.BufferData<Vector4>(
BufferTarget.ArrayBuffer,
new IntPtr(this.vertices.Length * Vector4.SizeInBytes),
this.vertices,
BufferUsageHint.StaticDraw);
GL.EnableVertexAttribArray(positionLoc);
GL.VertexAttribPointer(positionLoc, 4, VertexAttribPointerType.Float, false, Vector4.SizeInBytes, 0);

// normal buffer
GL.GenBuffers(1, out this.normalBuffer);
GL.BindBuffer(BufferTarget.ArrayBuffer, this.normalBuffer);
GL.BufferData<Vector3>(
BufferTarget.ArrayBuffer,
new IntPtr(this.vertices.Length * Vector3.SizeInBytes),
this.normals,
BufferUsageHint.StaticDraw);
GL.EnableVertexAttribArray(normalLoc);
GL.VertexAttribPointer(normalLoc, 3, VertexAttribPointerType.Float, false, Vector3.SizeInBytes, 0);

// texcoord buffer
GL.GenBuffers(1, out this.texCoordBuffer);
GL.BindBuffer(BufferTarget.ArrayBuffer, this.texCoordBuffer);
GL.BufferData<Vector2>(
BufferTarget.ArrayBuffer,
new IntPtr(this.vertices.Length * Vector2.SizeInBytes),
this.texCoords,
BufferUsageHint.StaticDraw);
GL.EnableVertexAttribArray(texCoordLoc);
GL.VertexAttribPointer(texCoordLoc, 2, VertexAttribPointerType.Float, false, Vector2.SizeInBytes, 0);

// index buffer
GL.GenBuffers(1, out this.elementBuffer);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, this.elementBuffer);
GL.BufferData(BufferTarget.ElementArrayBuffer, new IntPtr(sizeof(uint) * this.indices.Length), this.indices, BufferUsageHint.StaticDraw);

GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
GL.BindVertexArray(0);```

The last part is the initialization of a Vertex Array Object and Vertex Buffer Objects bound to it. You will find a lot of OpenGL sample code using GL.Begin() ... GL.End() calls, but you should not do this anymore as it is deprecated. Therefore, the forward compatible and much more faster method of rendering is using those Vertex Array and Vertex Buffer Objects. If you have trouble drawing from the buffers, have a look at some sample code posted here in the forum, there are little tutorial pages that cover the usage of VAOs and VBOs. The procedure is something like

```// bind your Vertex Array Object
GL.BindVertexArray(this.vertexArray);

GL.BindBuffer(BufferTarget.ElementArrayBuffer, this.elementBuffer);

// bind your texture atlas to bind index 0
GL.Enable(EnableCap.Texture2D);
GL.ActiveTexture(0);
GL.BindTexture(TextureTarget.Texture2D, this.textureIndex);

// draw from the buffers bound to the Vertex Array Object
GL.DrawElements(BeginMode.Triangles, this.indices.Length, DrawElementsType.UnsignedInt, IntPtr.Zero);

// unbind your Vertex Array Object
GL.BindVertexArray(0);

GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);

// unbind the index 0 texture
GL.ActiveTexture(0);
GL.BindTexture(TextureTarget.Texture2D, 0);
GL.Disable(EnableCap.Texture2D);

GL.UseProgram(0);```

I hope this all works, I copy&pasted a bit together from my rendering framework which is much more complicated and also based on CG as shader language (and I assume you want to use GLSL), so I don't know for sure if I got the shader binding calls right. As I said, there is a lot of sample code on the forum and, of course, all over the internet. This is not an OpenTK matter, but standard OpenGL procedure, so you will find tons of useful information.