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 ?
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)
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:
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);
// bind your index bufferGL.BindBuffer(BufferTarget.ElementArrayBuffer, this.elementBuffer);
// bind your texture atlas to bind index 0GL.Enable(EnableCap.Texture2D);
GL.ActiveTexture(0);
GL.BindTexture(TextureTarget.Texture2D, this.textureIndex);
// bind your shaderGL.UseProgram(this.shader);
// draw from the buffers bound to the Vertex Array ObjectGL.DrawElements(BeginMode.Triangles, this.indices.Length, DrawElementsType.UnsignedInt, IntPtr.Zero);
// unbind your Vertex Array ObjectGL.BindVertexArray(0);
// unbind your index bufferGL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
// unbind the index 0 textureGL.ActiveTexture(0);
GL.BindTexture(TextureTarget.Texture2D, 0);
GL.Disable(EnableCap.Texture2D);
// unbind your shaderGL.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.
Oh, and one more thing: You might notice that the code is quite sophisticated and there are a lot of new GL calls if you are a beginner. Let me tell you that texturing a cube in OpenGL is not a trivial task or a Hello World example which you can do without knowledge. If you don't get it running or don't understand the code I wrote, I recommend you to start somewhere lower: First draw a simple 2D triangle according to some online tutorial with vertex and fragment shader to the screen. Nothing fancy, but you get a feeling for the shader stuff and know that this is working. Then, try to draw this triangle with Vertex Buffer Objects and a Vertex Array Object. Then, extend this to the third dimension, which is already challenging as you have to use matrix multiplications. Note that you should do this in the vertex shader as well and not with the deprecated OpenGL matrix stack. Once you have managed to work with a model view projection matrix in the shader, you can try texturing the triangle. You will find out what states you need to enable and how to bind a texture (correctly) to the shader and how to do texture lookups in your shader. Having accomplished that, you can try to draw a simple cube, still using shaders and VAO/VBOs. The next step would be to texture all faces of the cube with the same texture. This is what the cube code I posted above does. And once you have accomplished this, it would be time to extend this to the possibility of mapping different textures to the faces with changing the texture coordinates according to my first post. If you are a beginner, this will be quite a way to go, but there are some very good tutorials out there that guide you. You can do yourself a favor by never getting used to the deprecated immediate mode. The first thing you should regard for this is not to follow tutorials which are several years old. Search for "OpenGL 3" tutorials, if possible. When going through foreign code, always have a look at http://www.khronos.org/files/opengl-quick-reference-card.pdf - each call which is marked blue in this file is deprecated and should not be used. I'm afraid this will eliminate the majority of all OpenGL tutorials, but believe me, if you have the chance to avoid getting used to the deprecated, inefficient (although much more easy to use) stuff, you should seize it.
Hope that helps. Don't hesitate to ask in the forum if you need help with a specific topic, but keep in mind that you are not limited to the OpenTK forum when searching, as these are native OpenGL topics which a lot of people have written stuff and articles about.
Comments
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:
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
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.
Oh, and one more thing: You might notice that the code is quite sophisticated and there are a lot of new GL calls if you are a beginner. Let me tell you that texturing a cube in OpenGL is not a trivial task or a Hello World example which you can do without knowledge. If you don't get it running or don't understand the code I wrote, I recommend you to start somewhere lower: First draw a simple 2D triangle according to some online tutorial with vertex and fragment shader to the screen. Nothing fancy, but you get a feeling for the shader stuff and know that this is working. Then, try to draw this triangle with Vertex Buffer Objects and a Vertex Array Object. Then, extend this to the third dimension, which is already challenging as you have to use matrix multiplications. Note that you should do this in the vertex shader as well and not with the deprecated OpenGL matrix stack. Once you have managed to work with a model view projection matrix in the shader, you can try texturing the triangle. You will find out what states you need to enable and how to bind a texture (correctly) to the shader and how to do texture lookups in your shader. Having accomplished that, you can try to draw a simple cube, still using shaders and VAO/VBOs. The next step would be to texture all faces of the cube with the same texture. This is what the cube code I posted above does. And once you have accomplished this, it would be time to extend this to the possibility of mapping different textures to the faces with changing the texture coordinates according to my first post. If you are a beginner, this will be quite a way to go, but there are some very good tutorials out there that guide you. You can do yourself a favor by never getting used to the deprecated immediate mode. The first thing you should regard for this is not to follow tutorials which are several years old. Search for "OpenGL 3" tutorials, if possible. When going through foreign code, always have a look at http://www.khronos.org/files/opengl-quick-reference-card.pdf - each call which is marked blue in this file is deprecated and should not be used. I'm afraid this will eliminate the majority of all OpenGL tutorials, but believe me, if you have the chance to avoid getting used to the deprecated, inefficient (although much more easy to use) stuff, you should seize it.
Hope that helps. Don't hesitate to ask in the forum if you need help with a specific topic, but keep in mind that you are not limited to the OpenTK forum when searching, as these are native OpenGL topics which a lot of people have written stuff and articles about.