|
|
|
|||||||||||
|
|
|
![]() |
|
|
|
|||||||
|
|
|
|
|
|
||||||||
|
|
|
|||||||||||
|
|
|
|
|
|||||||||
How to use the glMultiTexCoord2fARB function in OpenGLWelcome to third in my terrain tutorials. This has come a little later than expected I suppose you could call this a bit of a step backwards, as I have removed all of the In this tutorial I have also fixed the terrain, so that it no longer appears as a -------------------------------------------------------------------------------------- I have added a few variables to this tutorial. Most of them control the camera which I So in detail, here are the new variables. This variable controls how detailed our terrain is. The lower the number, the more I have added another scaling variable, this will control the height and is seperate This simply controls the speed of the camera movement. The lower the number, the slower These next few variables, control our camera system. This when added to the camera ypos, will allow for a neat little bobbing effect. This will control the scaling of our detail texture. The higher the number, the smaller These will just let us know which texture is assigned to which number. Now because this uses an OpenGL extension. This next portion of the code is #define GL_COMBINE_ARB 0x8570 this gives us the ability to combine our textures (through r,g,b) Here we tell our program that the following functions exist, these are needed for the whole multi texturing experience Now we link the above functions to our calls. -------------------------------------------------------------------------------- I have made the following adjustment to our LoadHeightmap function: I found that this is slightly more effective decreasing the risk of errors around ------------------------------------------------------------------------------- This is where most of our changes will take place as we now need to add the glPushMatrix(); glActiveTextureARB(GL_TEXTURE0_ARB); //set our current texture to texture0 glBindTexture(GL_TEXTURE_2D, texture[tground]); //bind our ground texture glMatrixMode(GL_TEXTURE); go to our texture matrix //this rotation will correct our texture so that it matches up with our heightmap glMatrixMode(GL_MODELVIEW); //switch back to our model matrix glActiveTextureARB(GL_TEXTURE1_ARB); //activate our next texture, texture1 glBindTexture(GL_TEXTURE_2D, texture[tdetail]); //bind our detail texture glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); //set the texture mode to combine the two glMatrixMode(GL_TEXTURE); //switch to our texture matrix again glScalef((float)terrainDetailLevel, (float)terrainDetailLevel, 1); //scale the size of the texture glMatrixMode(GL_MODELVIEW); //switch back to our model matrix for (mapX = 1; mapX < MapWidth; mapX +=LOD){ glBegin(GL_TRIANGLE_STRIP); Height = HeightMap[mapX][mapZ+LOD]; Height = HeightMap[mapX+LOD][mapZ]; Height = HeightMap[mapX+LOD][mapZ+LOD]; Turn the second multitexture pass off Turn the first multitexture pass off glPopMatrix(); ---------------------------------------------------------------------------- void init (void) { And finally we load our heightmap ------------------------------------------------------------------------------- And there we have it. We can now texture our terrain using the glMultiTexCoord2fARB If you have any questions, please email me at swiftless@gmail.com #include <GL/gl.h> int mapX; const MapWidth = 128; int LOD = 10; float scale = 5; float camerascale = 0.25; double xpos = 0; double bounce; float terrainDetailLevel = 1.5; int tground = 0, tdetail = 1; BYTE HeightMap[MapWidth][MapHeight]; //----------------------- #define GL_COMBINE_ARB 0x8570 // this gives us the ability to combine our textures (through r,g,b) // Here we tell our program that the following functions exist, these are needed for the whole multi texturing experience // Now we link the above functions to our calls. { 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_MIPMAP_LINEAR ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_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 with mipmaps gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height, 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 LoadHeightMap (char* Filename, int Width, int Height) { int smoothen; FILE * File; File = fopen( Filename, "rb" ); fread( HeightMap, 1, Width * Height * 3, File ); fclose( File ); for (smoothen = 1; smoothen < 1; smoothen++){ for (mapX = 1; mapX < (Width)-1; mapX ++){ for (mapZ = 1; mapZ < (Height)-1; mapZ++){ mapY = HeightMap[mapX][mapZ]; mapY += HeightMap[mapX-1][mapZ]; mapY += HeightMap[mapX+1][mapZ]; mapY += HeightMap[mapX][mapZ-1]; mapY += HeightMap[mapX][mapZ+1]; mapY += HeightMap[mapX-1][mapZ-1]; mapY += HeightMap[mapX-1][mapZ+1]; mapY += HeightMap[mapX+1][mapZ-1]; mapY += HeightMap[mapX+1][mapZ+1]; mapY = mapY/9; HeightMap[mapX][mapZ] = mapY ; } } } } void DisplayHeightMap (void) { float Height; glPushMatrix(); glActiveTextureARB(GL_TEXTURE0_ARB); //set our current texture to texture0 glEnable(GL_TEXTURE_2D); //enable texturing glBindTexture(GL_TEXTURE_2D, texture[tground]); //bind our ground texture glMatrixMode(GL_TEXTURE); // go to our texture matrix glLoadIdentity(); //clear our texture matrix //this rotation will correct our texture so that it matches up with our heightmap glRotatef(180,1,0,0); //rotate our texture on the x axis 180 degrees glRotatef(180,0,0,1); //rotate our texture on the z axis 180 degrees glRotatef(90,0,0,1); //rotate our texture on the y axis 90 degrees glMatrixMode(GL_MODELVIEW); //switch back to our model matrix glActiveTextureARB(GL_TEXTURE1_ARB); //activate our next texture, texture1 glEnable(GL_TEXTURE_2D); //enable texturing again glBindTexture(GL_TEXTURE_2D, texture[tdetail]); //bind our detail texture glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); //set the texture mode to combine the two glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 2); //scale the color of this texture by 2 glMatrixMode(GL_TEXTURE); //switch to our texture matrix again glLoadIdentity(); //clear the matrix glScalef((float)terrainDetailLevel, (float)terrainDetailLevel, 1); //scale the size of the texture glMatrixMode(GL_MODELVIEW); //switch back to our model matrix for (mapX = 1; mapX < MapWidth; mapX +=LOD){ for (mapZ = 1; mapZ < MapHeight; mapZ +=LOD){ glBegin(GL_TRIANGLE_STRIP); Height = HeightMap[mapX][mapZ]; glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (float)mapX/(float)MapWidth, ((float)mapZ)/(float)MapHeight); //attach our ground texture, stretching it across the heightmap glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0, 0); //attach our detail texture, setting it to the current triangle strip glVertex3f(mapX*scale*3,Height*scaleheight,mapZ*scale); Height = HeightMap[mapX][mapZ+LOD]; glMultiTexCoord2fARB(GL_TEXTURE0_ARB, ((float)mapX)/(float)MapWidth, ((float)mapZ+LOD)/(float)MapHeight); glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0, 1); glVertex3f(mapX*scale*3,Height*scaleheight,(mapZ+LOD)*scale); Height = HeightMap[mapX+LOD][mapZ]; glMultiTexCoord2fARB(GL_TEXTURE0_ARB, ((float)mapX+LOD)/(float)MapWidth, (float)mapZ/(float)MapHeight); glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1, 0); glVertex3f((mapX+LOD)*scale*3,Height*scaleheight,mapZ*scale); Height = HeightMap[mapX+LOD][mapZ+LOD]; glMultiTexCoord2fARB(GL_TEXTURE0_ARB, ((float)mapX+LOD)/(float)MapWidth, ((float)mapZ+LOD)/(float)MapHeight); glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1, 1); glVertex3f((mapX+LOD)*scale*3,Height*scaleheight,(mapZ+LOD)*scale); glEnd(); } } // Turn the second multitexture pass off glActiveTextureARB(GL_TEXTURE1_ARB); glDisable(GL_TEXTURE_2D); // Turn the first multitexture pass off glActiveTextureARB(GL_TEXTURE0_ARB); glDisable(GL_TEXTURE_2D); glPopMatrix(); } void enable (void) { glEnable(GL_DEPTH_TEST); //enable the depth testing glDepthFunc(GL_LEQUAL); //set the depth function glFrontFace(GL_CCW); //set which face is facing forward glCullFace(GL_BACK); //set the face to be culled glEnable(GL_CULL_FACE); //enable culling to speed up the processing time glEnable(GL_TEXTURE_2D); //enable texturing } void camera (void) { int posX = xpos; int posZ = zpos; ypos = HeightMap[posX][posZ]; ypos += sin((3.141592654*bounce) * 2) / 2; ypos += 10; glRotatef(xrot,1.0,0.0,0.0); //rotate our camera on teh x-axis (left and right) glRotatef(yrot,0.0,1.0,0.0); //rotate our camera on the y-axis (up and down) glTranslated(-xpos *scale *3,-ypos*scaleheight,-zpos *scale); //translate the screen to the position of our camera } void display (void) { glClearColor (0.0,0.0,0.0,1.0); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); enable(); camera(); DisplayHeightMap(); //display our heightmap glutSwapBuffers(); } void init (void) { // Here we initialize our multitexturing functions glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC) wglGetProcAddress("glActiveTextureARB"); glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC) wglGetProcAddress("glMultiTexCoord2fARB"); texture[tground] = LoadTexture("ground.raw", 512, 512); texture[tdetail] = LoadTexture("detail.raw", 256, 256); LoadHeightMap ("height.raw", 128, 128); } void reshape (int w, int h) { glViewport (0, 0, (GLsizei)w, (GLsizei)h); glMatrixMode (GL_PROJECTION); glLoadIdentity (); gluPerspective (60, (GLfloat)w / (GLfloat)h, 0.1, 10000.0); glMatrixMode (GL_MODELVIEW); } void keyboard (unsigned char key, int x, int y) { if (key=='r') { xrot += 1; if (xrot >360) xrot -= 360; } if (key=='f') { xrot -= 1; if (xrot < -360) xrot += 360; } if (key=='w') { float xrotrad, yrotrad; yrotrad = (yrot / 180 * 3.141592654f); xrotrad = (xrot / 180 * 3.141592654f); xpos += float(sin(yrotrad)) * camerascale; zpos -= float(cos(yrotrad)) * camerascale * 3; ypos -= float(sin(xrotrad)) ; bounce += 0.04; } if (key=='s') { float xrotrad, yrotrad; yrotrad = (yrot / 180 * 3.141592654f); xrotrad = (xrot / 180 * 3.141592654f); xpos -= float(sin(yrotrad)) * camerascale; zpos += float(cos(yrotrad)) * camerascale * 3; ypos += float(sin(xrotrad)); bounce += 0.04; } if (key=='d') { float yrotrad; yrotrad = (yrot / 180 * 3.141592654f); xpos += float(cos(yrotrad)) * camerascale; zpos += float(sin(yrotrad)) * camerascale * 3; } if (key=='a') { float yrotrad; yrotrad = (yrot / 180 * 3.141592654f); xpos -= float(cos(yrotrad)) * camerascale; zpos -= float(sin(yrotrad)) * camerascale * 3; } if (key==27) { exit(0); } } void mouseMovement(int x, int y) { int diffx=x-lastx; //check the difference between the current x and the last x position int diffy=y-lasty; //check the difference between the current y and the last y position lastx=x; //set lastx to the current x position lasty=y; //set lasty to the current y position xrot += (float) diffy; //set the xrot to xrot with the addition of the difference in the y position if (xrot > 90) { xrot = 90; } if (xrot < -90) { xrot = -90; } yrot += (float) diffx; //set the xrot to yrot with the addition of the difference in the x position } int main (int argc, char **argv) { glutInit (&argc, argv); glutInitDisplayMode (GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA); glutInitWindowSize (500, 500); glutInitWindowPosition (100, 100); glutCreateWindow ("A basic OpenGL Window"); init(); glutDisplayFunc (display); glutIdleFunc (display); glutReshapeFunc (reshape); glutPassiveMotionFunc(mouseMovement); //check for mouse movement glutKeyboardFunc (keyboard); glutMainLoop (); return 0; } Download Ground Texture (.RAW) Download Detail Texture (.RAW) Download Heightmap (.RAW) - same as previously used Download C++ Source Code for this Tutorial Download Visual Basic Source Code for this Tutorial (soon maybe) |
|
|||||||||||
|
|
||||||||||||
|
|
||||||||||||
|
|
||||||||||||
|
|
||||||||||||
|
|
||||||||||||
|
|
||||||||||||
|
|
||||||||||||
|
|
||||||||||||
|
|
||||||||||||
|
|
||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Copyright 2008, Donald Urquhart |
||||||||||||