// 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 map file that I am using for this tutorial: // int cMap[10][10] = { // {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 load // it 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 be // either grass or dirt in the case of the textures I have created. // 1 will 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. // 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); // -------------------------------------------------------------------- // And now for the drawTiles() function. This function 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 #include #include #include #include GLuint texture; //the array for our texture GLuint texture2; //the array for our second texture 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}, }; //function to load the RAW file GLuint LoadTexture( const char * filename, int width, int height ) { GLuint texture; unsigned char * data; FILE * file; //The following code will read in our RAW file file = fopen( filename, "rb" ); if ( file == NULL ) return 0; data = (unsigned char *)malloc( width * height * 3 ); fread( data, width * height * 3, 1, file ); fclose( file ); glGenTextures( 1, &texture ); //generate the texture with the loaded data glBindTexture( GL_TEXTURE_2D, texture ); //bind the texture to it's array glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); //set texture environment parameters //here we are setting what textures to use and when. The MIN filter is which quality to show //when the texture is near the view, and the MAG filter is which quality to show when the texture //is far from the view. //The qualities are (in order from worst to best) //GL_NEAREST //GL_LINEAR //GL_LINEAR_MIPMAP_NEAREST //GL_LINEAR_MIPMAP_LINEAR //And if you go and use extensions, you can use Anisotropic filtering textures which are of an //even better quality, but this will do for now. glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); //Here we are setting the parameter to repeat the texture instead of clamping the texture //to the edge of our shape. glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); //Generate the texture glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); free( data ); //free the texture return texture; //return whether it was successfull } void FreeTexture( GLuint texture ) { glDeleteTextures( 1, &texture ); } void drawTiles (void) { //our function to draw the tiles for (int i = 0; i < 10; i++) //loop through the height of the map { for (int j = 0; j < 10; j++) //loop through the width of the map { 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 //otherwise { glBindTexture( GL_TEXTURE_2D, texture2 ); //bind our dirt texture to our shape } 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 } void display (void) { glClearColor (0.0,0.0,0.0,1.0); glClear (GL_COLOR_BUFFER_BIT); glLoadIdentity(); glEnable( GL_TEXTURE_2D ); glTranslatef(-5, 4, -20); //translate back a bit to view the map correctly drawTiles(); //draw our tiles glutSwapBuffers(); } void reshape (int w, int h) { glViewport (0, 0, (GLsizei)w, (GLsizei)h); glMatrixMode (GL_PROJECTION); glLoadIdentity (); gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 100.0); glMatrixMode (GL_MODELVIEW); } int main (int argc, char **argv) { glutInit (&argc, argv); glutInitDisplayMode (GLUT_DOUBLE); glutInitWindowSize (500, 500); glutInitWindowPosition (100, 100); glutCreateWindow ("A basic OpenGL Window"); glutDisplayFunc (display); glutIdleFunc (display); glutReshapeFunc (reshape); //Load our texture texture = LoadTexture("texture.raw", 256, 256); texture2 = LoadTexture("texture2.raw", 256, 256); glutMainLoop (); //Free our texture FreeTexture(texture); FreeTexture(texture2); return 0; }