PDA

View Full Version : texturing question



Savalia
09-04-2010, 11:57 PM
I'm using a .RAW height map and want to apply two textures to the terrain, but without using mulitexturing. My scaled terrain height ranges between 0 to 40, I have taken a simple texture for grass, copied it and modified it for my snow texture. I have a variable called SNOW_CAP (approx scaled height 32) which is the starting point for the "snow-line", above this value I want to use my snow texture, below this value I will use a grass texture. Currently in trying to use a multi-pass approach:

1. draw the terrain above the "snowline" with the snow texture (1st pass)
2. draw the grass section below the "snowline".(2nd pass)
3. draw the water level (scaled height of 8 - 3rd pass)

here is the initializing code


image.Load("grass.tga");
glGenTextures(1, &m_grassTexture);
glBindTexture(GL_TEXTURE_2D, m_grassTexture);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, image.GetWidth(),
image.GetHeight(), GL_RGB, GL_UNSIGNED_BYTE, image.GetImage());
image.Release();

image.Load("snow.tga");
glGenTextures(1, &m_snowTexture);
glBindTexture(GL_TEXTURE_2D, m_snowTexture);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, image.GetWidth(),
image.GetHeight(), GL_RGB, GL_UNSIGNED_BYTE, image.GetImage());
image.Release();

image.Load("water.tga");
glGenTextures(1, &m_waterTexture);
glBindTexture(GL_TEXTURE_2D, m_waterTexture);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, image.GetWidth(),
image.GetHeight(), GL_RGB, GL_UNSIGNED_BYTE, image.GetImage());
image.Release();

And this is my drawing function:


void CGfxOpenGL::DrawTerrain()
{

//draw the terrain using the snow texture ABOVE SNOW_CAP
//first pass
glBindTexture(GL_TEXTURE_2D, m_snowTexture);
//glTexEnvfv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_COLOR,WHI TE);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MO DULATE);
for (int z = 0; z < TERRAIN_SIZE - 1; ++z)
{
glBegin(GL_TRIANGLE_STRIP);
for (int x = 0; x < TERRAIN_SIZE ; ++x)
//for (int x = TERRAIN_SIZE; x < 0; --x)
{
if ((heightmap[z * TERRAIN_SIZE + x] / SCALE_FACTOR) >= SNOW_CAP)
{
// render two vertices of the strip at once
float scaledHeight = heightmap[z * TERRAIN_SIZE + x] / SCALE_FACTOR;
float nextScaledHeight = heightmap[(z + 1)* TERRAIN_SIZE + x] / SCALE_FACTOR;
float color = 0.35 + 1.0f * scaledHeight / MAX_HEIGHT;
float nextColor = 0.35 + 1.0f * nextScaledHeight / MAX_HEIGHT;
glColor3f(color, color, color);
glTexCoord2f((GLfloat)x/TERRAIN_SIZE*8, (GLfloat)z/TERRAIN_SIZE*8);
glVertex3f(static_cast<GLfloat>(x - TERRAIN_SIZE/2), scaledHeight,
static_cast<GLfloat>(z - TERRAIN_SIZE/2));
glColor3f( nextColor, nextColor, nextColor);
glTexCoord2f((GLfloat)x/TERRAIN_SIZE*8, (GLfloat)(z+1)/TERRAIN_SIZE*8);
glVertex3f(static_cast<GLfloat>(x - TERRAIN_SIZE/2), nextScaledHeight,
static_cast<GLfloat>(z + 1 - TERRAIN_SIZE/2));
}
}
glEnd();
}

//second pass
//only draw the area BELOW the
//SNOW_CAP
glBindTexture(GL_TEXTURE_2D, m_grassTexture);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_RE PLACE);
for (int z = 0; z < TERRAIN_SIZE - 1; ++z)
{
glBegin(GL_TRIANGLE_STRIP);
for (int x = 0; x < TERRAIN_SIZE; ++x)
//for (int x = TERRAIN_SIZE; x < 0; --x)
{
if((heightmap[z * TERRAIN_SIZE + x] / SCALE_FACTOR) <= SNOW_CAP)
{
// render two vertices of the strip at once
float scaledHeight = heightmap[z * TERRAIN_SIZE + x] / SCALE_FACTOR;
float nextScaledHeight = heightmap[(z + 1)* TERRAIN_SIZE + x] / SCALE_FACTOR;
float color = 0.5 + 1.0f * scaledHeight / MAX_HEIGHT;
float nextColor = 0.5 + 1.0f * nextScaledHeight / MAX_HEIGHT;
glColor3f(color,color,color);
glTexCoord2f((GLfloat)x/TERRAIN_SIZE*8, (GLfloat)z/TERRAIN_SIZE*8);
glVertex3f(static_cast<GLfloat>(x - TERRAIN_SIZE/2), scaledHeight,
static_cast<GLfloat>(z - TERRAIN_SIZE/2));
glColor3f(nextColor, nextColor, nextColor);
glTexCoord2f((GLfloat)x/TERRAIN_SIZE*8, (GLfloat)(z+1)/TERRAIN_SIZE*8);
glVertex3f(static_cast<GLfloat>(x - TERRAIN_SIZE/2), nextScaledHeight,
static_cast<GLfloat>(z + 1 - TERRAIN_SIZE/2));
}
}
glEnd();
}

//draw the water (functional)
glBindTexture(GL_TEXTURE_2D, m_waterTexture);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0);
glVertex3f(-TERRAIN_SIZE/2.1f, WATER_HEIGHT, TERRAIN_SIZE/2.1f);
glTexCoord2f(TERRAIN_SIZE/4.0f, 0.0);
glVertex3f(TERRAIN_SIZE/2.1f, WATER_HEIGHT, TERRAIN_SIZE/2.1f);
glTexCoord2f(TERRAIN_SIZE/4.0f, TERRAIN_SIZE/4.0f);
glVertex3f(TERRAIN_SIZE/2.1f, WATER_HEIGHT, -TERRAIN_SIZE/2.1f);
glTexCoord2f(0.0, TERRAIN_SIZE/4.0f);
glVertex3f(-TERRAIN_SIZE/2.1f, WATER_HEIGHT, -TERRAIN_SIZE/2.1f);
glEnd();
}

At this point I get a "snow bridge from one snow cap peak to another, and I have "wholes" in a few locations are ound the snow line, How can I correct this?

BionicBytes
09-06-2010, 02:45 PM
Try drawing each pass separately to determine if they work as expected. Can you supply a screen shot of the issue?

Savalia
09-06-2010, 10:31 PM
@BionicBytes
I have tried segregating the first terrain pass with the second. The first pass, that draws above the "snow line" always shows artifacts connecting the two highest points of the terrain. The second pass, also shows artifacts, connecting spaces that are not being mapped by the grass texture(I assumed this would not be a problem, because once the snow is correctly mapped, the only way to see the grass texture artifacts would be to look at them from the underside of the terrain map - which culling should eliminate, and compensate for the performance hit by actually drawing the land in two passes).

What I also tried to do, during the first pass, was to map the entire terrain in the snow texture. Then run the second pass with the grass texture and only texture the vertices below the snow line. I initially thought that this would be a better method, with less possible artifact problems, but when trying it, I can never get the second pass with the grass texture to be visible in the scene.

ZbuffeR
09-06-2010, 11:25 PM
glBegin(GL_TRIANGLE_STRIP);
for (int x = 0; x < TERRAIN_SIZE ; ++x) {
if ((heightmap[z * TERRAIN_SIZE + x] / SCALE_FACTOR) >= SNOW_CAP)

Here it is.
You need to skip the whole triangle, not just the vertex which is below the snow cap.
Otherwise your tristrip will of course continue to the next vertex which is above snow cap.
Try adapting your rendering with GL_TRIANGLES, then test each of the 3 vertices, if any is above snowcap, draw snow triangle, otherwise draw grass triangle.

BionicBytes
09-07-2010, 04:41 AM
ZbuffeR is dead right - the triangle is started but not finished as you expected.

On another note entirely - becareful with: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_RE PLACE);

...as your next step is most likely to add lighting - and this REPLACE environment mode will not react to fixed function OpenGL lighting as you might expect. Use GL_MODULATE instead.

Savalia
09-07-2010, 07:31 PM
@BionocBytes



float color = 0.5 + 1.0f * scaledHeight / MAX_HEIGHT;

-GL_REPLACE seems to negate any adjustment(like the code above) and it shows up noticeably when I use the snow texture for the entire terrain.

Savalia
09-08-2010, 03:57 PM
@BionicBytes & ZbuffeR
I created a struct in my fx.cpp file (where the terrain draw function is



struct vertex {
int x;
int y;
int z;
};


then created three holding variables vertex0, vertex1, vertex2 and added them within the drawing nested loops



vertex vertex0, vertex1, vertex2;

//draw the terrain using the snow texture
//first pass
glBindTexture(GL_TEXTURE_2D, m_snowTexture);
//glTexEnvfv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_COLOR,WHI TE);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MO DULATE);
for (int z = 0; z < TERRAIN_SIZE - 1; ++z)
//for(int z = (TERRAIN_SIZE-1); z >=0; --z)
{
glBegin(GL_TRIANGLE_STRIP);
for (int x = 0; x < TERRAIN_SIZE ; ++x)
//for (int x = TERRAIN_SIZE; x < 0; --x)
{
vertex0.x = (x - TERRAIN_SIZE/2);
vertex0.y = heightmap[z * TERRAIN_SIZE + x] / SCALE_FACTOR; ;
vertex0.z = (z - TERRAIN_SIZE/2);
vertex1.x = ((x+1) - TERRAIN_SIZE/2);
vertex1.y = heightmap[(z + 1)* TERRAIN_SIZE + x] / SCALE_FACTOR;
vertex1.z = ((z+1) - TERRAIN_SIZE/2);
vertex2.x = ((x+2) - TERRAIN_SIZE/2);
vertex2.y = heightmap[(z + 2)* TERRAIN_SIZE + x] / SCALE_FACTOR ;
vertex2.z = ((z+2) - TERRAIN_SIZE/2);

if((vertex0.y >= SNOW_CAP) || (vertex1.y >= SNOW_CAP) || (vertex2.y >= SNOW_CAP))
{
// render two vertices of the strip at once
float scaledHeight = heightmap[z * TERRAIN_SIZE + x] / SCALE_FACTOR;
float nextScaledHeight = heightmap[(z + 1)* TERRAIN_SIZE + x] / SCALE_FACTOR;
float color = 0.35 + 1.0f * scaledHeight / MAX_HEIGHT;
float nextColor = 0.35 + 1.0f * nextScaledHeight / MAX_HEIGHT;
glColor3f(color, color, color);
glTexCoord2f((GLfloat)x/TERRAIN_SIZE*8, (GLfloat)z/TERRAIN_SIZE*8);
glVertex3f(static_cast<GLfloat>(x - TERRAIN_SIZE/2), scaledHeight,
static_cast<GLfloat>(z - TERRAIN_SIZE/2));
glColor3f( nextColor, nextColor, nextColor);
glTexCoord2f((GLfloat)x/TERRAIN_SIZE*8, (GLfloat)(z+1)/TERRAIN_SIZE*8);
glVertex3f(static_cast<GLfloat>(x - TERRAIN_SIZE/2), nextScaledHeight,
static_cast<GLfloat>(z + 1 - TERRAIN_SIZE/2));
}
}
glEnd();
}


My if statement checks each of the 3 vertices, but only the y component(the part mapped by the heightmap), I still get the "landbridge" connecting the peaks and a small number of artifact tris, should my if statement make 3 OR checks as above or should it make 9 OR checks, one for each x,y,z component?

Savalia
09-08-2010, 09:27 PM
Here is what I did to get to this screen shot
1. map the entire terrain using the snow texture
2. map the terrain below the "snow line" with the grass texture, but adjusted the height for every vertex drawn by +0.1
3. map the water texture



void CGfxOpenGL::DrawTerrain()
{
vertex vertex0, vertex1, vertex2;

//draw the terrain using the snow texture
//first pass
glBindTexture(GL_TEXTURE_2D, m_snowTexture);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MO DULATE);
for (int z = 0; z < TERRAIN_SIZE - 1; ++z)
{
glBegin(GL_TRIANGLE_STRIP);
for (int x = 0; x < TERRAIN_SIZE; ++x)
{
// render two vertices of the strip at once
float scaledHeight = heightmap[z * TERRAIN_SIZE + x] / SCALE_FACTOR;
float nextScaledHeight = heightmap[(z + 1)* TERRAIN_SIZE + x] / SCALE_FACTOR;
float color = 0.35 + 1.0f * scaledHeight / MAX_HEIGHT;
float nextColor = 0.35 + 1.0f * nextScaledHeight / MAX_HEIGHT;
glColor3f(color, color, color);
glTexCoord2f((GLfloat)x/TERRAIN_SIZE*8, (GLfloat)z/TERRAIN_SIZE*8);
glVertex3f(static_cast<GLfloat>(x - TERRAIN_SIZE/2), scaledHeight,
static_cast<GLfloat>(z - TERRAIN_SIZE/2));
glColor3f( nextColor, nextColor, nextColor);
glTexCoord2f((GLfloat)x/TERRAIN_SIZE*8, (GLfloat)(z+1)/TERRAIN_SIZE*8);
glVertex3f(static_cast<GLfloat>(x - TERRAIN_SIZE/2), nextScaledHeight,
static_cast<GLfloat>(z + 1 - TERRAIN_SIZE/2));
}
glEnd();
}

//second pass - only draw the area BELOW the SNOW_CAP
glBindTexture(GL_TEXTURE_2D, m_grassTexture);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_CO MBINE);
glTexEnvf(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_MODULAT E);
for (int z = 0; z < TERRAIN_SIZE - 1; ++z)
{
glBegin(GL_TRIANGLE_STRIP);
for (int x = 0; x < TERRAIN_SIZE; ++x)
{
//vertex0.x = (x - TERRAIN_SIZE/2);
vertex0.x = x;
vertex0.y = heightmap[z * TERRAIN_SIZE + x] / SCALE_FACTOR; ;
vertex0.z = z;
vertex1.x = (x+1);
vertex1.y = heightmap[(z + 1)* TERRAIN_SIZE + x] / SCALE_FACTOR;
vertex1.z = (z+1);
vertex2.x = (x+2);
vertex2.y = heightmap[(z + 2)* TERRAIN_SIZE + x] / SCALE_FACTOR ;
vertex2.z = (z+2);

if((vertex0.x <= SNOW_CAP) || (vertex0.y <= SNOW_CAP) || (vertex0.z <= SNOW_CAP) ||
(vertex1.x <= SNOW_CAP) || (vertex1.y <= SNOW_CAP) || (vertex1.z <= SNOW_CAP) ||
(vertex2.x <= SNOW_CAP) || (vertex2.y <= SNOW_CAP) || (vertex2.z <= SNOW_CAP))
{
// render two vertices of the strip at once
float scaledHeight = (heightmap[z * TERRAIN_SIZE + x] / SCALE_FACTOR) + .1;
float nextScaledHeight = (heightmap[(z + 1)* TERRAIN_SIZE + x] / SCALE_FACTOR) + .1;
float color = 0.3 + 1.0f * scaledHeight / MAX_HEIGHT;
float nextColor = 0.3 + 1.0f * nextScaledHeight / MAX_HEIGHT;
glColor3f(color,color,color);
glTexCoord2f((GLfloat)x/TERRAIN_SIZE*8, (GLfloat)z/TERRAIN_SIZE*8);
glVertex3f(static_cast<GLfloat>(x - TERRAIN_SIZE/2), scaledHeight,
static_cast<GLfloat>(z - TERRAIN_SIZE/2));
glColor3f(nextColor, nextColor, nextColor);
glTexCoord2f((GLfloat)x/TERRAIN_SIZE*8, (GLfloat)(z+1)/TERRAIN_SIZE*8);
glVertex3f(static_cast<GLfloat>(x - TERRAIN_SIZE/2), nextScaledHeight,
static_cast<GLfloat>(z + 1 - TERRAIN_SIZE/2));
}
}
glEnd();
}

//draw the water (functional)
glBindTexture(GL_TEXTURE_2D, m_waterTexture);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0);
glVertex3f(-TERRAIN_SIZE/2.1f, WATER_HEIGHT, TERRAIN_SIZE/2.1f);
glTexCoord2f(TERRAIN_SIZE/4.0f, 0.0);
glVertex3f(TERRAIN_SIZE/2.1f, WATER_HEIGHT, TERRAIN_SIZE/2.1f);
glTexCoord2f(TERRAIN_SIZE/4.0f, TERRAIN_SIZE/4.0f);
glVertex3f(TERRAIN_SIZE/2.1f, WATER_HEIGHT, -TERRAIN_SIZE/2.1f);
glTexCoord2f(0.0, TERRAIN_SIZE/4.0f);
glVertex3f(-TERRAIN_SIZE/2.1f, WATER_HEIGHT, -TERRAIN_SIZE/2.1f);
glEnd();
}

I guess my question now is, would this be considered a viable solution?

ZbuffeR
09-09-2010, 01:38 AM
What part of "Try adapting your rendering with GL_TRIANGLES" you did not understand ?

Savalia
09-09-2010, 05:38 PM
@ZbuffeR
I haven't abandoned your solution to use GL_TRIANGLES, I just haven't got it running yet, sometimes to figure a coding problem out, I go "old school" (aka pen & paper) ;)

KylBlz
09-10-2010, 01:17 AM
i would say in your if statement (to check which zone its in) if its in a different zone than your drawing on that pass, then call glEnd() and resume drawing when you hit the next peak by calling glBegin(GL_TRIANGLE_STRIP). your getting land bridges because you're using GL_TRIANGLE_STRIP. I ran into this problem a lot rendering terrain..

Savalia
09-10-2010, 02:38 PM
k so I got the grass texture to process through GL_TRIANGLES but there is an obvious problem, not only did I not properly line up the tris but there are untextured gaps, if you look at the screen shot(04)(thanks to ZbuffeR's keen observation) versus the previous one a few posts up (prior to the "Zs" keen observation) I think the terrain is starting to look more realistic and less tiled.

Here's the code(I used GL_BLEND to make the grass tex easier to spot


vertex[6];
float Height[6];
float color[6];

//draw the terrain using the snow texture - first pass
glBindTexture(GL_TEXTURE_2D, m_snowTexture);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MO DULATE);
for (int z = 0; z < TERRAIN_SIZE - 1; ++z)
{
glBegin(GL_TRIANGLE_STRIP);//I will change this once I get the grass working
for (int x = 0; x < TERRAIN_SIZE; ++x)
{
// render two vertices of the strip at once
float scaledHeight = heightmap[z * TERRAIN_SIZE + x] / SCALE_FACTOR;
float nextScaledHeight = heightmap[(z + 1)* TERRAIN_SIZE + x] / SCALE_FACTOR;
float color = 0.35 + 1.0f * scaledHeight / MAX_HEIGHT;
float nextColor = 0.35 + 1.0f * nextScaledHeight / MAX_HEIGHT;
glColor3f(color, color, color);
glTexCoord2f((GLfloat)x/TERRAIN_SIZE*8, (GLfloat)z/TERRAIN_SIZE*8);
glVertex3f(static_cast<GLfloat>(x - TERRAIN_SIZE/2), scaledHeight,
static_cast<GLfloat>(z - TERRAIN_SIZE/2));
glColor3f( nextColor, nextColor, nextColor);
glTexCoord2f((GLfloat)x/TERRAIN_SIZE*8, (GLfloat)(z+1)/TERRAIN_SIZE*8);
glVertex3f(static_cast<GLfloat>(x - TERRAIN_SIZE/2), nextScaledHeight,
static_cast<GLfloat>(z + 1 - TERRAIN_SIZE/2));
}
glEnd();
}

//second pass - only draw the area BELOW the SNOW_CAP
glBindTexture(GL_TEXTURE_2D, m_grassTexture);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DE CAL);
//glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_CO MBINE);
//glTexEnvf(GL_TEXTURE_ENV,GL_COMBINE,GL_MODULATE);
for (int x = 0; x < TERRAIN_SIZE ; ++x)
{
glBegin(GL_TRIANGLES);
for (int z = 0; z < TERRAIN_SIZE-1; ++z)
{
//verts for 1st tri
vertex[0].x = x;
vertex[0].z = z;
vertex[0].y = heightmap[vertex[0].z * TERRAIN_SIZE + vertex[0].x] / SCALE_FACTOR;
Height[0] = (heightmap[vertex[0].z * TERRAIN_SIZE + vertex[0].x] / SCALE_FACTOR);
color[0] = x + 1.0f * Height[0] / MAX_HEIGHT;

vertex[1].x = vertex[0].x + 1;
vertex[1].z = z;
vertex[1].y = heightmap[vertex[1].z * TERRAIN_SIZE + vertex[1].x] / SCALE_FACTOR;
Height[1] = (heightmap[vertex[0].z * TERRAIN_SIZE + vertex[1].x] / SCALE_FACTOR);
color[1] = x + 1.0f * Height[1] / MAX_HEIGHT;

vertex[2].x = vertex[0].x + 1;
vertex[2].z = vertex[0].z + 1;
vertex[2].y = heightmap[vertex[2].z * TERRAIN_SIZE + vertex[2].x] / SCALE_FACTOR;
Height[2] = (heightmap[vertex[2].z * TERRAIN_SIZE + vertex[1].x] / SCALE_FACTOR);
color[2] = x + 1.0f * Height[2] / MAX_HEIGHT;

//verts for 2nd tri
vertex[3].x = vertex[0].x;
vertex[3].z = vertex[0].z;
vertex[3].y = heightmap[vertex[3].z * TERRAIN_SIZE + vertex[3].x] / SCALE_FACTOR;
Height[3] = Height[0];
color[3] = x + 1.0f * Height[3] / MAX_HEIGHT;

vertex[4].x = vertex[1].x;
vertex[4].z = vertex[2].z;
vertex[4].y = heightmap[vertex[4].z * TERRAIN_SIZE + vertex[4].x] / SCALE_FACTOR;
Height[4] = Height[2];
color[4] = x + 1.0f * Height[4] / MAX_HEIGHT;

vertex[5].x = vertex[0].x;
vertex[5].z = vertex[2].z +1;
vertex[5].y = heightmap[vertex[5].z * TERRAIN_SIZE + vertex[5].x] / SCALE_FACTOR;
Height[5] = (heightmap[vertex[2].z * TERRAIN_SIZE + vertex[0].x] / SCALE_FACTOR);
color[5] = x + 1.0f * Height[5] / MAX_HEIGHT;


if((vertex[0].x <= SNOW_CAP) || (vertex[0].y <= SNOW_CAP) || (vertex[0].z <= SNOW_CAP) ||
(vertex[1].x <= SNOW_CAP) || (vertex[1].y <= SNOW_CAP) || (vertex[1].z <= SNOW_CAP) ||
(vertex[2].x <= SNOW_CAP) || (vertex[2].y <= SNOW_CAP) || (vertex[2].z <= SNOW_CAP) ||
(vertex[3].x <= SNOW_CAP) || (vertex[3].y <= SNOW_CAP) || (vertex[3].z <= SNOW_CAP) ||
(vertex[4].x <= SNOW_CAP) || (vertex[4].y <= SNOW_CAP) || (vertex[4].z <= SNOW_CAP) ||
(vertex[5].x <= SNOW_CAP) || (vertex[5].y <= SNOW_CAP) || (vertex[5].z <= SNOW_CAP))
{
// render two triangles(6vertices) of the terrain at once
for(int q = 0; q < 6; ++q)
{
glColor3f(color[q],color[q],color[q]);
glTexCoord2f((GLfloat)vertex[q].x/TERRAIN_SIZE*8, (GLfloat)vertex[q].z/TERRAIN_SIZE*8);
glVertex3f(static_cast<GLfloat>(vertex[q].x - TERRAIN_SIZE/2), Height[q],
static_cast<GLfloat>(vertex[q].z - TERRAIN_SIZE/2));
}
}
}
glEnd();
}

...am I on the right track with the algorithms for calculating the vertecies for the 2 tris?

Savalia
09-21-2010, 03:07 PM
@ZbuffeR,
I have a working render of the terrain using on GL_TRIANGLES, but the terrain now looks like it was made from LEGOs (stepped changes in elevation - like in TR 1). I reduced my vertices for the triangles from 6 to 4(260x260 map - 2 vertices removes more than 135,000 calculations). Can I expect to achieve a smooth terrain surface with the following code(once it runs correctly, or do I need to revert back to a 6 vertex terrain model to get a smooth terrain surface?


//first pass - only draw the area above the SNOW_CAP
//2nd pass identical - only draw below SNOW_CAP
glBindTexture(GL_TEXTURE_2D, m_snowTexture);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DE CAL);
for (int z = 0; z < TERRAIN_SIZE - 1; ++z)
{
glBegin(GL_TRIANGLES);
for (int x = 0; x < TERRAIN_SIZE; ++x)
{
//verts for 1st tri
vertex[0].x = x; vertex[0].z = z;
vertex[0].y = heightmap[z * TERRAIN_SIZE + x] / SCALE_FACTOR;
color[0] = MAX_FOG_HEIGHT + 1.0f * vertex[0].y / MAX_HEIGHT;

vertex[1].x = x + 1; vertex[1].z = z + 1;
vertex[1].y = heightmap[(z+1) * TERRAIN_SIZE + (x+1)] / SCALE_FACTOR;
color[1] = MAX_FOG_HEIGHT + 1.0f * vertex[1].y / MAX_HEIGHT;

vertex[2].x = x; vertex[2].z = z +1;
vertex[2].y = heightmap[(z+1) * TERRAIN_SIZE + x] / SCALE_FACTOR;
color[2] = MAX_FOG_HEIGHT + 1.0f * vertex[2].y / MAX_HEIGHT;

//vert for 2nd tri
vertex[3].x = x + 1; vertex[3].z = z;
vertex[3].y = heightmap[(z) * TERRAIN_SIZE + (x+1)] / SCALE_FACTOR;
color[3] = MAX_FOG_HEIGHT + 1.0f * vertex[3].y / MAX_HEIGHT;


if((vertex[0].y > SNOW_CAP) || (vertex[1].y > SNOW_CAP) || (vertex[2].y > SNOW_CAP) ||
(vertex[3].y > SNOW_CAP))
{
// render two triangles(4 vertices) of the terrain at once
glColor3f(1,1,1);
//glColor3f(color[0],color[1],color[2]);
// Vertex 00
glTexCoord2f((GLfloat)vertex[0].x/TERRAIN_SIZE*8, (GLfloat)vertex[0].z/TERRAIN_SIZE*8);
glVertex3f(static_cast<GLfloat>(vertex[0].x - TERRAIN_SIZE/2), vertex[0].y,
static_cast<GLfloat>(vertex[0].z - TERRAIN_SIZE/2));
// Vertex 01
glTexCoord2f((GLfloat)vertex[3].x/TERRAIN_SIZE*8, (GLfloat)vertex[3].z/TERRAIN_SIZE*8);
glVertex3f(static_cast<GLfloat>(vertex[3].x - TERRAIN_SIZE/2), vertex[3].y,
static_cast<GLfloat>(vertex[3].z - TERRAIN_SIZE/2));
// Vertex 02
glTexCoord2f((GLfloat)vertex[1].x/TERRAIN_SIZE*8, (GLfloat)vertex[1].z/TERRAIN_SIZE*8);
glVertex3f(static_cast<GLfloat>(vertex[1].x - TERRAIN_SIZE/2), vertex[1].y,
static_cast<GLfloat>(vertex[1].z - TERRAIN_SIZE/2));

glColor3f(1,1,1);
//glColor3f(color[3],color[3],color[3]);
// Vertex 00
glTexCoord2f((GLfloat)vertex[0].x/TERRAIN_SIZE*8, (GLfloat)vertex[0].z/TERRAIN_SIZE*8);
glVertex3f(static_cast<GLfloat>(vertex[0].x - TERRAIN_SIZE/2), vertex[0].y,
static_cast<GLfloat>(vertex[0].z - TERRAIN_SIZE/2));
// Vertex 03
glTexCoord2f((GLfloat)vertex[1].x/TERRAIN_SIZE*8, (GLfloat)vertex[1].z/TERRAIN_SIZE*8);
glVertex3f(static_cast<GLfloat>(vertex[1].x - TERRAIN_SIZE/2), vertex[1].y,
static_cast<GLfloat>(vertex[1].z - TERRAIN_SIZE/2));
// Vertex 01
glTexCoord2f((GLfloat)vertex[2].x/TERRAIN_SIZE*8, (GLfloat)vertex[2].z/TERRAIN_SIZE*8);
glVertex3f(static_cast<GLfloat>(vertex[2].x - TERRAIN_SIZE/2), vertex[2].y,
static_cast<GLfloat>(vertex[2].z - TERRAIN_SIZE/2));
}
}
glEnd();
}

ZbuffeR
09-22-2010, 09:27 AM
Such stepping generally means integer conversion somewhere where it should not be.
Nothing to do with number of vertices.
Example :


vertex[2].y = heightmap[(z+1) * TERRAIN_SIZE + x] / SCALE_FACTOR;


Does heightmap[] contain int ?
Is SCALE_FACTOR an int ?
If "yes" is the answer to both questions, then "/" does an integer division.
Try that instead to force floating point :


vertex[2].y = heightmap[(z+1) * TERRAIN_SIZE + x] * 1.0 / SCALE_FACTOR;

Then I hope vertex.xyz are floats too ...

Savalia
09-22-2010, 03:23 PM
@ZbuffeR
changing the types for xyz from int to float did the trick. I was thinking because I had a smooth surface with 6 vertices, then switched to 4, that the problem could only be with how I had set up the triangle patterns to receive the textures.

Thanks.