35. OpenGL Tiling Engine
Well due to a request, here is a tiling example for you all.
To tile in OpenGL, it is not that easy to merge or combine textures to create a simple 2D tiling game.
It is easier for us to draw a bunch of quads that take up the space of the world in which we want
to tile and assign different textures to those quads according to what is in our map file.
Here is the example of a map file that I am using for this tutorial, which is integrated into the code:
int cMap[10][10] = { //our map
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
};
Now if you don’t like storing this in your program, you can just as easily store all of this in a file and loadit in when you need it.
So now that we have our ‘map’, we want to load in our two textures for our two states, 1 or 0, which will beeither grass or dirt in the case of the textures I have created.
I am setting 1 to be dirt, and 0 will be grass.
So as this is building on from the texturing tutorial, we need to create another variable to hold our other texture, as we already setup the first texture in the first tutorial.
GLuint texture2; //the array for our second texture
Now that we have our textures, we need to load them in, do this just like you did in the texturing tutorial:
//Load our texture
texture = LoadTexture(“texture.raw”, 256, 256);
texture2 = LoadTexture(“texture2.raw”, 256, 256);
glutMainLoop ();
//Free our texture
FreeTexture(texture);
FreeTexture(texture2);
So now that we have our map, and our textures, we need to now draw it all. I am creating a method called drawTiles(). This method will be called in the display function and takes no parameters.
void drawTiles (void) { //our function to draw the tiles
First thing we want to do is start looping through the height of the map, the value of 10 here is specific
to this application. If you have a bigger or smaller map, change this value as you need.
for (int i = 0; i < 10; i++) //loop through the height of the map
{
Then we will want to loop through the width of the map, just as I said above, the value 10 is specific
to this tutorial.
for (int j = 0; j < 10; j++) //loop through the width of the map
{
Now here is where the main part of our tiling takes place, we need to check if the map value at the
current [i][j] position is either a 0 or a 1. If it is a 0, then we bind the grass texture to the quad
that we are about to draw.
if (cMap[i][j] == 0) //if the map at this position contains a 0
{
glBindTexture( GL_TEXTURE_2D, texture ); //bind our grass texture to our shape
}
Else we automatically assign it to dirt. If you have more than two states, you will need to make several if statements,
and if you do not want a default, then you will remove the else and replace it with an if.
else //otherwise
{
glBindTexture( GL_TEXTURE_2D, texture2 ); //bind our dirt texture to our shape
}
The rest of the code draws a quad at the current i, j position we are at.
Drawing a quad should be simple for you at this stage. So I will not explain it.
glPushMatrix(); //push the matrix so that our translations only affect this tile
glTranslatef(j, -i, 0); //translate the tile to where it should belong
glBegin (GL_QUADS); //begin drawing our quads
glTexCoord2d(0.0, 0.0);
glVertex3f(0.0, 0.0, 0.0); //with our vertices we have to assign a texcoord
glTexCoord2d(1.0, 0.0);
glVertex3f(1.0, 0.0, 0.0); //so that our texture has some points to draw to
glTexCoord2d(1.0, 1.0);
glVertex3f(1.0, 1.0, 0.0);
glTexCoord2d(0.0, 1.0);
glVertex3f(0.0, 1.0, 0.0);
glEnd();
glPopMatrix(); //pop the matrix
} //end first loop
} //end second loop
}
And there we have it, you can now create a 2D tiled map for use with a game. Simple wasn’t it? 🙂
If you have any questions, email me at swiftless@gmail.com
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157.
|
#include <GL/gl.h> GLuint texture; //the array for our texture int cMap[10][10] = { //our map //function to load the RAW file GLuint LoadTexture( const char * filename, int width, int height ) //The following code will read in our RAW file glGenTextures( 1, &texture ) glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, //Here we are setting the parameter to repeat the texture //Generate the texture void FreeTexture( GLuint texture ) void drawTiles (void) { //our function to draw the tiles glBegin (GL_QUADS); //begin drawing our quads glTexCoord2d(1.0, 0.0); glTexCoord2d(1.0, 1.0); glTexCoord2d(0.0, 1.0); void display (void) { int main (int argc, char **argv) { //Load our texture glutMainLoop (); //Free our texture return 0; |
For anyone having the following problems, here’s how I solved them:
1) Not compiling
Add #include //add and move to top of include list for Visual Studio 2010.
#include “glut.h” //add glut header & search for it locally if you need too.
2) Getting white block/square
Check directory of files. Make sure they’re in the project folder.
(the same location as the TileProject.vcxproj file itself).
I hope this helps.
And great job on the tutorials Swiftless. I really enjoy them.
hi, i tried loading a standard jpg file but it’s rendered incorrectly, doesnt even resemble the image itself just random colours.
what’s the default supported image format?
Hi John,
There is no default image format as such. If you use a library to handle image loading, you can use anything. I am using a RAW file format which is just RGB values with no other information.
Cheers,
Swiftless
After looking for a solution for this poor performance I found out that if you check the currently bound textures and if it is already bound then just skipping the binding it actually gives a huge speed boost.
Yes, I mean don’t draw them.
In the loop, before you draw, you can do the check as to whether or not you need to draw.
Cheers,
Swiftless
when you mean cull them do you mean not draw them because doesn’t the whole thing just go through a loop
Hey Jjack,
GL_CULL culls back-facing polygons, so it won’t take care of removing objects out side of the field of view.
If you have a set field of view, then you could do a hack and work out the distance between tiles and the centre of the screen, and cull them if they are too far away. However the correct way is to do a bounding box collision check against the view frustrum.
Vertex Buffer Objects can be set once and then drawn whenever you want them, the advantage being that they are stored on the graphics card and not system memory, so they are so much faster than regular rendering. You can alternatively set the VBO to be update-able if you need to make changes to it at any stage.
Cheers,
Swiftless
Will the simple glEnable(GL_CULL); work or will you have to do some fancy algorithms and with vertex buffer objects do you have to update them each frame or can you just set them once and then they will not get overwritten?
Thanks
Thanks for the tutorial I have been looking all over the internet for one and this seems the most recent. Well I would like to ask why the FPS is so low I am getting about <10 frames per second when scrolling.
Hi jjack,
The number of frames per second if you use this straight out, is going to be fairly poor for a large number of tiles. I am not doing any culling to test if a tile is visible or not, which means every tile is going to be drawn, even if it isn’t in the window.
Another reason it would be so slow, is this is using OpenGL’s Immediate Mode, to speed it up even more so, you could store the tiles in Vertex Buffer Objects.
Cheers,
Swiftless
i played the original SimCity in the 90’s and until now i still play the latest version of SimCity*`:
I have just fixed it up, it appears that
tags are causing the tutorials to disappear in some instances.
Let me know if you find any more.
Cheers,
Swiftless
Hey,
can you re-upload this tutorial, please?
Thank’s a lot!
Hi Meee,
If all the tiles are white, then this sounds like it simply isn’t loading your textures.
Make sure your textures are in the correct directory and that they are loading correctly.
Cheers,
Swiftless
Why am I just getting a white block?