Jump to content
  • Advertisement
Sign in to follow this  
John Matrix

Height based terrain texturing - Multi-texturing

This topic is 3668 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi. I haven't really played about with multi-texturing before so I'm looking for some pointers on how I would go about texturing a randomly generated terrain based on height. I would like to have a set up where the whole terrain is given a basic rocky texture then at low heights I would blend in a sandy texture, medium heights a grassy one and high heights snowy. What I have set up so far is Terrain.h:
PFNGLMULTITEXCOORD2FARBPROC	glMultiTexCoord2fARB		= NULL;
PFNGLACTIVETEXTUREARBPROC	glActiveTextureARB		= NULL;

Terrain.cpp:
void initMultiTexture(void)
{
	glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC) wglGetProcAddress("glMultiTexCoord2fARB");
	glActiveTextureARB   = (PFNGLACTIVETEXTUREARBPROC)	 wglGetProcAddress("glActiveTextureARB");
}

Then to render the terrain:
for ( intX = 0; intX < ((TERRAINSIZE+1)-BLOCKSIZE); intX += BLOCKSIZE )
{
	for ( intY = 0; intY < ((TERRAINSIZE+1)-BLOCKSIZE); intY += BLOCKSIZE )
	{
		/////////////////////////////////////////////////
		/////Calculate the lowest vertex of the qaud/////
		/////////////////////////////////////////////////
		float heightcounter=0.0f;
		//Set the lowest point to the first vertex making up the quad
		heightcounter=0.0f + HeightValues[intX+(intY*TERRAINARRAYSIZE)];
		//if any of the other vertexes are lower, set that vertex to the lowest point
		if(0.0f+HeightValues[intX+((intY+BLOCKSIZE)*TERRAINARRAYSIZE)]<heightcounter)
			heightcounter=0.0f+HeightValues[intX+((intY+BLOCKSIZE)*TERRAINARRAYSIZE)];
		if(0.0f+HeightValues[(intX+BLOCKSIZE)+((intY+BLOCKSIZE)*TERRAINARRAYSIZE)]<heightcounter)			
                        heightcounter=0.0f+HeightValues[(intX+BLOCKSIZE)+((intY+BLOCKSIZE)*TERRAINARRAYSIZE)];
		if(0.0f+HeightValues[(intX+BLOCKSIZE)+(intY*TERRAINARRAYSIZE)]<heightcounter)
			heightcounter=0.0f+HeightValues[(intX+BLOCKSIZE)+(intY*TERRAINARRAYSIZE)];

                //Activate first texture
		glActiveTextureARB(GL_TEXTURE0_ARB);
		glBindTexture(GL_TEXTURE_2D, texture[0]);
		glEnable(GL_TEXTURE_2D);
		glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
		glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE);

                //Draw Terrain
		glBegin( GL_QUADS );
		floatX=((float) intX) - (TERRAINSIZE/2);
		floatY=(float) intY;
				
		x = floatX;
		y = 0.0f + HeightValues[intX+(intY*TERRAINARRAYSIZE)];						
		z = floatY;
				
		glNormal3f(0.0f, 1.0f, 0.0f);
		glMultiTexCoord2fARB(GL_TEXTURE0_ARB, x*(1.0f/512.0f), z*(1.0f/512.0f));
                glVertex3f(x, y, z);

		x = floatX;
		y = 0.0f + HeightValues[intX+((intY+BLOCKSIZE)*TERRAINARRAYSIZE)];
		z = floatY+BLOCKSIZE;

		glNormal3f(0.0f, 1.0f, 0.0f);
		glMultiTexCoord2fARB(GL_TEXTURE0_ARB, x*(1.0f/512.0f), z*(1.0f/512.0f));
		glVertex3f(x, y, z);

		x = floatX+BLOCKSIZE; 
		y = 0.0f + HeightValues[(intX+BLOCKSIZE)+((intY+BLOCKSIZE)*TERRAINARRAYSIZE)];
		z = floatY+BLOCKSIZE;
				
		glNormal3f(0.0f, 1.0f, 0.0f);
		glMultiTexCoord2fARB(GL_TEXTURE0_ARB, x*(1.0f/512.0f), z*(1.0f/512.0f));
		glVertex3f(x, y, z);

		x = floatX+BLOCKSIZE; 
		y = 0.0f + HeightValues[(intX+BLOCKSIZE)+(intY*TERRAINARRAYSIZE)];
		z = floatY;
				
		glNormal3f(0.0f, 1.0f, 0.0f);
		glMultiTexCoord2fARB(GL_TEXTURE0_ARB, x*(1.0f/512.0f), z*(1.0f/512.0f));
		glVertex3f(x, y, z);
		glEnd();
	}
}

Now that I believe I have multitexturing set up correctly, any pointers to how would I go about adding another texture or two to achieve the effect I want would be helpful. So what paramaters would be given to glTexEnvf, how would I set up the textures I wan't to use (eg. alpha channels) etc.

Share this post


Link to post
Share on other sites
Advertisement
Hi!! for use other texture use repete the line

glMultiTexCoord2fARB(GL_TEXTURE0_ARB, ......., .......);

but against use GL_TEXTURE0_ARB use GL_TEXTURE1_ARB , obviuslly you need to load the other texture ;) you can found nice examples about multitex in nehe site
by the way you can boost-up your render speed using VBO to write all the vertex in one OpenGL call

Share this post


Link to post
Share on other sites
Consider using texture arrays and shaders (if your graphics card is compliant).

Shaders allow you to program the OpenGL pipeline. This will allow you to come up with custom rendering effects, as well as place the burden of some calculations on the GPU instead of the CPU.

You would be able to create a simple vertex / fragment shader that takes the height of the current vertex, and decide which texture to use from an array passed to the opengl pipeline.

If you aren't familiar with shaders it will take a little bit of time to learn, but the entire direction of modern game development is/will be based around shaders, so you've got to learn it sometime ;)

Share this post


Link to post
Share on other sites
Quote:
Original post by juglar
Hi!! for use other texture use repete the line

glMultiTexCoord2fARB(GL_TEXTURE0_ARB, ......., .......);

but against use GL_TEXTURE0_ARB use GL_TEXTURE1_ARB , obviuslly you need to load the other texture ;) you can found nice examples about multitex in nehe site
by the way you can boost-up your render speed using VBO to write all the vertex in one OpenGL call


I had tried that but it didn't seem to work properly. The Snowy texture is fine but elsewhere it doesn't texture properly.

New code.


// loop through the entire array and draw a textured quad with the height position in the array values
for ( intX = 0; intX < ((TERRAINSIZE+1)-BLOCKSIZE); intX += BLOCKSIZE )
{
for ( intY = 0; intY < ((TERRAINSIZE+1)-BLOCKSIZE); intY += BLOCKSIZE )
{
/////////////////////////////////
/////height related textures/////
/////////////////////////////////
float heightcounter=0.0f;
//Set the lowest point to the first vertex making up the quad
heightcounter = 0.0f + HeightValues[intX+(intY*TERRAINARRAYSIZE)];
//if any of the other vertexes are lower, set that vertex to the lowest point
if(0.0f+HeightValues[intX+((intY+BLOCKSIZE)*TERRAINARRAYSIZE)]<heightcounter)
heightcounter=0.0f+HeightValues[intX+((intY+BLOCKSIZE)*TERRAINARRAYSIZE)];
if(0.0f+HeightValues[(intX+BLOCKSIZE)+((intY+BLOCKSIZE)*TERRAINARRAYSIZE)]<heightcounter)
heightcounter=0.0f+HeightValues[(intX+BLOCKSIZE)+((intY+BLOCKSIZE)*TERRAINARRAYSIZE)];
if(0.0f+HeightValues[(intX+BLOCKSIZE)+(intY*TERRAINARRAYSIZE)]<heightcounter)
heightcounter=0.0f+HeightValues[(intX+BLOCKSIZE)+(intY*TERRAINARRAYSIZE)];

//Set up the normal Texture
glActiveTextureARB(GL_TEXTURE0_ARB);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glEnable(GL_TEXTURE_2D);
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE);


if(heightcounter>50.0f) // If the highest value just calculated is greater than 50
{
//Set up the snowy Texture
glActiveTextureARB(GL_TEXTURE1_ARB);
glBindTexture(GL_TEXTURE_2D, texture[7]);
glEnable(GL_TEXTURE_2D);
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE);
}

glBegin( GL_QUADS ); //Start drawing quads
floatX=((float) intX) - (TERRAINSIZE/2); // Set the x and y positions as integer to access the height array
floatY=(float) intY; // Set the x and y positions as integer to access the height array

//////////////////////////////////////////////////////////
///////////Draw each of the vertexes in the quad//////////
//////////////////////////////////////////////////////////

// Get The (X, Y, Z) Value For The Bottom Left Vertex
x = floatX;
y = 0.0f + HeightValues[intX+(intY*TERRAINARRAYSIZE)];
z = floatY;

glNormal3f(0.0f, 1.0f, 0.0f);
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, x*(1.0f/512.0f), z*(1.0f/512.0f));
if(heightcounter>50.0f)
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, x*(1.0f/512.0f), z*(1.0f/512.0f));
glVertex3f(x, y, z); // Send This Vertex To OpenGL To Be Rendered

// Get The (X, Y, Z) Value For The Top Left Vertex
x = floatX;
y = 0.0f + HeightValues[intX+((intY+BLOCKSIZE)*TERRAINARRAYSIZE)];
z = floatY+BLOCKSIZE;

glNormal3f(0.0f, 1.0f, 0.0f);
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, x*(1.0f/512.0f), z*(1.0f/512.0f));
if(heightcounter>50.0f)
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, x*(1.0f/512.0f), z*(1.0f/512.0f));
glVertex3f(x, y, z); // Send This Vertex To OpenGL To Be Rendered

// Get The (X, Y, Z) Value For The Top Right Vertex
x = floatX+BLOCKSIZE;
y = 0.0f + HeightValues[(intX+BLOCKSIZE)+((intY+BLOCKSIZE)*TERRAINARRAYSIZE)];
z = floatY+BLOCKSIZE;

glNormal3f(0.0f, 1.0f, 0.0f);
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, x*(1.0f/512.0f), z*(1.0f/512.0f));
if(heightcounter>50.0f)
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, x*(1.0f/512.0f), z*(1.0f/512.0f));
glVertex3f(x, y, z); // Send This Vertex To OpenGL To Be Rendered

// Get The (X, Y, Z) Value For The Bottom Right Vertex
x = floatX+BLOCKSIZE;
y = 0.0f + HeightValues[(intX+BLOCKSIZE)+(intY*TERRAINARRAYSIZE)];
z = floatY;

glNormal3f(0.0f, 1.0f, 0.0f);
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, x*(1.0f/512.0f), z*(1.0f/512.0f));
if(heightcounter>50.0f)
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, x*(1.0f/512.0f), z*(1.0f/512.0f));
glVertex3f(x, y, z); // Send This Vertex To OpenGL To Be Rendered
glEnd();
}
}



Screenshot:

http://img234.imageshack.us/img234/3034/terrainok4.png

I'll need to have a look at shaders soon but it would be good to get this setup quickly with multitexturing first.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!