OpenGL :: Textures :: Material 6
contents :
- Load Texture
- Texture mapping
- Repetitive texture
- Colors
Load Texture
With our choice of using OpenGL with SDL, you will see the textures loading phase we will be highly simplified. But before they can load any texture, it is still necessary to have ... For this I suggest you work with this pack of textures high resolutions . It is quite large (124 MB) but fairly comprehensive and includes photorealistic textures classified into various categories: floors, crates, plants, metals, stones, etc..
Examples of textures included in the package
We use two main formats for textures . jpg and. png .
format . jpg is perfect for textures, because it gives smaller file sizes on complex images (such as photorealistic textures).
format . png ( 24 bits) in turn is used because it handles very well transparency. width and height of the textures mustimperatively be powers of 2 ( 64,128,512,1024 ). Indeed, if they are not, textures are resized anyway internally to meet this requirement and you may therefore lose unnecessarily quality . In terms of visual quality , the higher the resolution of the texture, the better the result. The package that I provided mainly contains high-resolution textures (512x512) with which you will not hurt to have made better than Half-Life first name (lighting effects aside for the moment ).
The code required to create OpenGL texture from an array of pixels is not very complicated. However the most painful phase is the loading of an image file (. Jpg,. Bmp,. Tga or other).
Fortunately for us SDL_image is, we simply use it to return us to an SDL_Surface from a file name. Once this surface created, it must be flipped vertically as SDL and OpenGL does not have the same conventions. You may have noticed in the chapter on transformations for the (0,0) OpenGL was at the bottom left while in the SDL (as indicated in the course of teo @ M) is the top left. The last thing to do is to convert the array of pixels contained in the surface texture OpenGL OpenGL calls appropriate.
Know how to code yourself this phase is not necessary for understanding the rest of the chapter. The most important is the use of textures created. We'll go into more detail about calls into question when we see procedural textures but for now I give you it all on a silver platter, that:
In the archive, I give you two files: sdlglutils.h and sdlglutils.cpp . I chose this name because I will add little by little useful functions for this tutorial that are there to make our lives easier but you could do it yourself with a little more knowledge. feature that we interest at the moment is LoadTexture which uses very simple:Code: C + +
- Select
If you're curious you can look at the code behind but it did nothing complicated, just what I explained above (loading the image, flipping, and creating texture OpenGL). The return type is GLuint is the equivalent of an unsigned int . But I never use the typeunsigned int for textures not to be tried in my code to make the calculations above, in fact this number has returned a very specific meaning: it is the identifier of the texture created OpenGL. Whenever we want to use this texture, simply use this identifier.
As we have already created 3D scenes without texture we know that the texturing is not enabled by default. To activate it, just calling:Code: C + +
- Select
Here we are ready, we know load a texture, we know enable the texturing. Now see how, by taking our 3D cube in the previous chapter, apply a texture to an object.
Examples of textures included in the package
Whether you download it or not I still will provide the textures used in the example at the end of the chapter. So you can be content.
Format and size
We use two main formats for textures . jpg and. png .
format . jpg is perfect for textures, because it gives smaller file sizes on complex images (such as photorealistic textures).
format . png ( 24 bits) in turn is used because it handles very well transparency. width and height of the textures mustimperatively be powers of 2 ( 64,128,512,1024 ). Indeed, if they are not, textures are resized anyway internally to meet this requirement and you may therefore lose unnecessarily quality . In terms of visual quality , the higher the resolution of the texture, the better the result. The package that I provided mainly contains high-resolution textures (512x512) with which you will not hurt to have made better than Half-Life first name (lighting effects aside for the moment ).
Use SDL_image to load a texture
The code required to create OpenGL texture from an array of pixels is not very complicated. However the most painful phase is the loading of an image file (. Jpg,. Bmp,. Tga or other).
Fortunately for us SDL_image is, we simply use it to return us to an SDL_Surface from a file name. Once this surface created, it must be flipped vertically as SDL and OpenGL does not have the same conventions. You may have noticed in the chapter on transformations for the (0,0) OpenGL was at the bottom left while in the SDL (as indicated in the course of teo @ M) is the top left. The last thing to do is to convert the array of pixels contained in the surface texture OpenGL OpenGL calls appropriate.
Oops! It looks complicated it all ... I'll be able to do it myself?
Know how to code yourself this phase is not necessary for understanding the rest of the chapter. The most important is the use of textures created. We'll go into more detail about calls into question when we see procedural textures but for now I give you it all on a silver platter, that:
In the archive, I give you two files: sdlglutils.h and sdlglutils.cpp . I chose this name because I will add little by little useful functions for this tutorial that are there to make our lives easier but you could do it yourself with a little more knowledge. feature that we interest at the moment is LoadTexture which uses very simple:Code: C + +
- Select
1 2 | # Include "sdlglutils.h" GLuint identifiant_texture = LoadTexture ( "ma_texture.jpg" ); |
If you're curious you can look at the code behind but it did nothing complicated, just what I explained above (loading the image, flipping, and creating texture OpenGL). The return type is GLuint is the equivalent of an unsigned int . But I never use the typeunsigned int for textures not to be tried in my code to make the calculations above, in fact this number has returned a very specific meaning: it is the identifier of the texture created OpenGL. Whenever we want to use this texture, simply use this identifier.
Enable texturing
As we have already created 3D scenes without texture we know that the texturing is not enabled by default. To activate it, just calling:Code: C + +
- Select
1 | glEnable ( GL_TEXTURE_2D ); |
You may want to do in your scenes live textured objects with non-textured objects (why not after all ...). To do this, simply disable texturing temporarily with:Code: C + +- Select
1 | glDisable ( GL_TEXTURE_2D ); |
Here we are ready, we know load a texture, we know enable the texturing. Now see how, by taking our 3D cube in the previous chapter, apply a texture to an object.
Texture mapping
Let's code that we had to define the first side of the cube:Code: C + +
- Select
We will use texture " stainedglass05.jpg "that you find in the pack in the category window (or in the archive at the end of chapter.) Let's start by loading the launch of our application as explained above:Code: C + +
- Select
In the drawing code before defining the vertices of our textured face first, we need to tell OpenGL that we want to use this texture by calling glBindTexture with our texture identifier:Code: C + +
- Select
And now we realize the plating itself the texture on the face matching each vertex component we face a coordinate on the texture as shown in the diagram below:
Texture mapping coordinates / real coordinates
To define the coordinates of the vertex we know glVertex use, well to define the texture coordinates we use:
The coordinate space of the texture is 2D, bottom left corner has coordinates (0,0) and upper right corner is (1,1), whatever the size in pixels of the image. Here I will begin by defining the vertex (1,1,1) which I want to flatten the upper left corner of the texture is (0.1). therefore I do:Code: C + +
- Select
Continuing with the other vertices of the face so it gives the following complete code:Code: C + +
- Select
Misuse glTexCoord2d (wrong coordinates, forgot to redefine glTexCoord2d for the next vertex) gives rise to strange results:
Error in forgetting to redefine glTexCoord2d the last vertex
Do not laugh these errors are common at the beginning and I'm willing to bet that it will happen at least once . At least you know where the problem ...
In video games, the most primitive basis used is the triangle (we will see why when we will import the 3D models). Texture mapping works the same way in choosing only 3 points on the texture , points are not necessarily the corners of the image.
We have seen in the case of the triangle, it is not necessary to use any texture. This practice is often used to group all the textures to a single object in a single file, such as by the skin of Tommy Vercetti in GTA: Vice City:
Texture of the hero (one of skins possible) GTA: Vice City
Just then, blow glTexCoord2d well designed to delimit the area of the texture that you want to use for the current face:
- Select
1 2 3 4 5 6 | glBegin(GL_QUADS); glVertex3d(1,1,1); glVertex3d(1,1,-1); glVertex3d(-1,1,-1); glVertex3d(-1,1,1); glEnd(); |
We will use texture " stainedglass05.jpg "that you find in the pack in the category window (or in the archive at the end of chapter.) Let's start by loading the launch of our application as explained above:Code: C + +
- Select
1 2 3 4 5 6 7 8 9 10 | GLuint texture1 ; / / global variable int main ( int argc , char * argv []) { / / ... launch during the initialization of OpenGL display before the loop / / ... display loop and event management } |
In the drawing code before defining the vertices of our textured face first, we need to tell OpenGL that we want to use this texture by calling glBindTexture with our texture identifier:Code: C + +
- Select
1 | glBindTexture ( GL_TEXTURE_2D , texture1 ); |
And now we realize the plating itself the texture on the face matching each vertex component we face a coordinate on the texture as shown in the diagram below:
Texture mapping coordinates / real coordinates
To define the coordinates of the vertex we know glVertex use, well to define the texture coordinates we use:
glTexCoord2d (double x_texture, double y_texture);
The coordinate space of the texture is 2D, bottom left corner has coordinates (0,0) and upper right corner is (1,1), whatever the size in pixels of the image. Here I will begin by defining the vertex (1,1,1) which I want to flatten the upper left corner of the texture is (0.1). therefore I do:Code: C + +
- Select
1 2 | glBegin ( GL_QUADS ) glTexCoord2d ( 0 , 1 ); glVertex3d ( 1 , 1 , 1 ); |
glTexCoord2d as glColor3ub applies to all vertices defined later. So do not forget to do it again before each call vertex.
Continuing with the other vertices of the face so it gives the following complete code:Code: C + +
- Select
1 2 3 4 5 6 7 | glBindTexture(GL_TEXTURE_2D, texture1); glBegin(GL_QUADS); glTexCoord2d(0,1); glVertex3d(1,1,1); glTexCoord2d(0,0); glVertex3d(1,1,-1); glTexCoord2d(1,0); glVertex3d(-1,1,-1); glTexCoord2d(1,1); glVertex3d(-1,1,1); glEnd(); |
It is not possible to change the texture being defined to one side. To apply a different texture to the next face must therefore complete the block vertices by a call to glEnd () , change the texture and set the next face:Code: C + +
- Select
It is of course necessary if you want to keep the same texture.
- Select
1 2 3 4 5 6 7 8 | glBindTexture ( GL_TEXTURE_2D , texture1 ) glBegin ( GL_QUADS ) / / first face / / set vertex glEnd () glBindTexture ( GL_TEXTURE_2D , texture2 ) / / change texture glBegin ( GL_QUADS ) / / second side / / definition vertex glEnd (); |
It is of course necessary if you want to keep the same texture.
Common Mistakes
Misuse glTexCoord2d (wrong coordinates, forgot to redefine glTexCoord2d for the next vertex) gives rise to strange results:
Error in forgetting to redefine glTexCoord2d the last vertex
Do not laugh these errors are common at the beginning and I'm willing to bet that it will happen at least once . At least you know where the problem ...
Case of a triangle
In video games, the most primitive basis used is the triangle (we will see why when we will import the 3D models). Texture mapping works the same way in choosing only 3 points on the texture , points are not necessarily the corners of the image.
Code: C + +- Select
|
Use of a part of the texture
We have seen in the case of the triangle, it is not necessary to use any texture. This practice is often used to group all the textures to a single object in a single file, such as by the skin of Tommy Vercetti in GTA: Vice City:
Texture of the hero (one of skins possible) GTA: Vice City
Just then, blow glTexCoord2d well designed to delimit the area of the texture that you want to use for the current face:
Code: C + +- Select
|
As you can see, the texture used here is not a square (384x128) and yet the upper right still has coordinates (1,1). The coordinates of a point on the texture thus provide information on the total size of the image. Here we wanted to cut a part of 128 pixels wide by 384 the total or a ratio of 1/3 (0.33).
Repetitive texture
So far we applied all or part of the texture of our objects. But if you try to create a ground (a simple square of 20x20) in the scene with the same technique we obtain the following result:
As you can see the texture is not meant to be spread over a large area. We must therefore ensure that it repeats itself!
In the examples we have seen that we do not use coordinates between 0 and 1. But in reality the coordinate space of the texture does not limit:
Space texture coordinates
When we consider the original image, we restrict us to a part of this space. But here we want to repeat the texture 10 times, for example, so we will take coordinates between 0 and 10 just! And indeed changing the code accordingly:Code: C + +
- Select
We get much better visual results:
Soil texture repeated 10 times
Code: C + +- Select
|
As you can see the texture is not meant to be spread over a large area. We must therefore ensure that it repeats itself!
In the examples we have seen that we do not use coordinates between 0 and 1. But in reality the coordinate space of the texture does not limit:
Space texture coordinates
When we consider the original image, we restrict us to a part of this space. But here we want to repeat the texture 10 times, for example, so we will take coordinates between 0 and 10 just! And indeed changing the code accordingly:Code: C + +
- Select
1 2 3 4 5 6 7 | glBindTexture(GL_TEXTURE_2D, texture4); glBegin(GL_QUADS); glTexCoord2i(0,0); glVertex3i(-10,-10,-1); glTexCoord2i(10,0); glVertex3i(10,-10,-1); glTexCoord2i(10,10); glVertex3i(10,10,-1); glTexCoord2i(0,10); glVertex3i(-10,10,-1); glEnd(); |
We get much better visual results:
Soil texture repeated 10 times
All textures are not made to be repeated. It must indeed they are specially designed to match the edges when several repetitions of the image are placed end to end. Textures in the pack, you can be pretty sure that all textures of floor, wall, ceiling, grass, rocks are likely to be repeated.
Colors
I have deliberately not mentioned colors since the beginning of this chapter to stay focused on the novelty of the moment: the textures. But our good old colors are not dead either.
We know from the beginning of this tutorial set the color to go with vertices glColor3ub . Nothing prevents us to continue to use more of what we have learned about textures. The complete definition of a vertex can now contain up to 3 lines:
It is of course not necessary to redefine glColor3ub every time if you do not want to change color.
Applied to the ground above, by assigning colors to each vertex is obtained:
As you can see, the color acts as a filter and just give local color to the texture.
Everything seems to go well until you decide to display something else just after having defined our floor, a textured cube eg
As you can see the cube is also affected by the last color used. This is quite logical because glColor3ub by definition is used for allvertices defined after (until the next call to glColor3ub ). should therefore use a neutral color which, when applied as a filter will not change the color texture. And this color is none other than ... the white ! Thus, for somehow " cancel out the effect of color , "just use white as the next color with a call to:Code: C + +
- Select
And indeed by interposing a call glColor3ub (255,255,255); between the soil and the definition of the cube, we obtain a cube virgin any color effect:
That you now know what precautions to take when you want to combine in a single code colors and textures. Do not worry, it will not be uncommon to forget to switch back to white from time to time and often you create beautiful color effects involuntarily.
Combine texture and color
We know from the beginning of this tutorial set the color to go with vertices glColor3ub . Nothing prevents us to continue to use more of what we have learned about textures. The complete definition of a vertex can now contain up to 3 lines:
- color definition with glColor3ub (optional) ;
- definition of coordinates on the texture with glTexCoord2d (mandatory use of a texture) ;
- definition of the spatial coordinates of the vertex with glVertex3d .
It is of course not necessary to redefine glColor3ub every time if you do not want to change color.
Applied to the ground above, by assigning colors to each vertex is obtained:
Code: C + +- Select
|
As you can see, the color acts as a filter and just give local color to the texture.
Everything seems to go well until you decide to display something else just after having defined our floor, a textured cube eg
As you can see the cube is also affected by the last color used. This is quite logical because glColor3ub by definition is used for allvertices defined after (until the next call to glColor3ub ). should therefore use a neutral color which, when applied as a filter will not change the color texture. And this color is none other than ... the white ! Thus, for somehow " cancel out the effect of color , "just use white as the next color with a call to:Code: C + +
- Select
1 | glColor3ub ( 255 , 255 , 255 ); |
And indeed by interposing a call glColor3ub (255,255,255); between the soil and the definition of the cube, we obtain a cube virgin any color effect:
Code: C + +- Select
|
Who would have thought that we would go as fast objects ugly but nicely colored sumptuous textured objects?!
As you can see there is really no magic in the application of textures, just to know affect every vertex coordinates on the right texture and voila.
The best way to make sure you understand is to train yourself to make a small scene in 3D with textures, including a box of 4x2x2with texture box (see caisse.jpg in zip lowest) used in this chapter. I did one quickly you can download the code below:
Unleash your imagination and do not hesitate to post your creations in the comments section or on the forum.
As you can see there is really no magic in the application of textures, just to know affect every vertex coordinates on the right texture and voila.
The best way to make sure you understand is to train yourself to make a small scene in 3D with textures, including a box of 4x2x2with texture box (see caisse.jpg in zip lowest) used in this chapter. I did one quickly you can download the code below:
Unleash your imagination and do not hesitate to post your creations in the comments section or on the forum.
download the files at the links
No comments:
Post a Comment