Friday, November 25, 2016

opengl - lighting for landscape


I've got a landscape(created in Photoshop .raw file) and a .tga texture for it. I read .raw file and read .tga file like this


LoadRawFile("landscape.Raw", MapSize * MapSize, &HeightMap[0][0]);


Texture landscape;
if (LoadTGA(&landscape, "landscape.tga")) {

glGenTextures(1, &landscape.texID);
glBindTexture(GL_TEXTURE_2D, landscape.texID);
glTexImage2D(GL_TEXTURE_2D,
0,
landscape.bpp / 8,
landscape.width,

landscape.height,
0,
landscape.type,
GL_UNSIGNED_BYTE,
landscape.imageData);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

if (landscape.imageData) free(landscape.imageData);

} else {
cout<<"Cannot load texture"<}

glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer (3, GL_FLOAT, 0, VertexMap);

glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, TextureMap);


for (int Row=0; Row < MapSize*2; Row++)
{
Indices[Row] = Row;
}

I render landscape like this(method renderLandscape)


int x, y, i, j;
int Index = 0;

for (i = 0; i < MapSize-1; i++)

{
Index = 0;
for (j = 0;j < MapSize-1; j++)
{
x = j * Zoom;
y = i * Zoom;

TextureMap[Index+0][0]= j * TextureBit;
TextureMap[Index+0][1]= i * TextureBit;
TextureMap[Index+1][0]= j * TextureBit;

TextureMap[Index+1][2]= (i+1) * TextureBit;

VertexMap[Index+0][2] = HeightMap[j][i];
VertexMap[Index+1][2] = HeightMap[j][i+1];

VertexMap[Index+0][0] = x;
VertexMap[Index+0][3] = y;
VertexMap[Index+1][0] = x;
VertexMap[Index+1][4] = y+Zoom;


Index += 2;
}

glDrawElements(GL_TRIANGLE_STRIP, Index, GL_UNSIGNED_INT, Indices);
}

draw method


glPushMatrix();
glTranslatef(-20, 0, 0);
glScalef(0.01, 0.01, 0.01);

glRotatef(90, 1, 0, 0);
landscape.RenderLandscape();
glPopMatrix();

So by default(without lighting) it looks like this enter image description here


But when I enable lighting(add this lines to my opengl init function)


GLfloat light_ambient[] = { 0.5, 0.5, 0.5, 1.0 };
GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };


glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

The result landscape looks like this enter image description here



I don't need any special or difficult lighting. So it seems I need to calculate normales(I am new in opengl and usually create .obj models where vn precalculated). What is the best way to calculate normales in my case?



Answer



This is how you calculate normals for a mesh. This methods averages vertex normals that is shared by multiple faces.


void CalculateNormals()
{
size_t vertexCount = m_triangles.size();

m_normals.reserve( m_vertices.size() );

for( int i = 0; i < vertexCount; i += 3 )

{
// get the three vertices that make the faces
glm::vec3 p0 = m_vertices[m_triangles[i+0]];
glm::vec3 p1 = m_vertices[m_triangles[i+1]];
glm::vec3 p2 = m_vertices[m_triangles[i+2]];

glm::vec3 e1 = p1 - p0;
glm::vec3 e2 = p2 - p0;
glm::vec3 normal = glm::cross( e1, e2 );
normal = glm::normalize(normal);


// Store the face's normal for each of the vertices that make up the face.
m_normals[m_triangles[i+0]] += normal ;
m_normals[m_triangles[i+1]] += normal ;
m_normals[m_triangles[i+2]] += normal ;
}


// Now loop through each vertex vector, and avarage out all the normals stored.
for( int i = 0; i < m_normals.size(); ++i )

{
m_normals[i] = glm::normalize(m_normals[i]);
}
}

No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...