Skip to main content
gamedev.net
🔒 Locked

Lighting

Started by Isolier 2 replies 650+ views
Original Post
Isolier
Isolier
Hello, I seem to be having trouble with lighting in my current project which creates terrain from a heightmap. The problem seems to be with directional lights. When I set up a directional light, the entire world is lit as if I was only using ambient light, so I am getting a 2d looking landscape basically, because there is no shading done along the hills or anything. However, when I use a positional light, things seem to work correctly as the 3d terrain appears to be correctly lit along the hills and valleys and such. I am simply using:
float[] diffuseLight = {0.5f, 0.5f, 0.5f, 1.0f};
float[] lightPos    = {0.0f, 1.0f, 0.0f, 0.0f};
nomalizeVector(lightPos);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);


I am fairly sure my normals are calculated correctly else the positional light wouldn't work I am assuming. Does anyone know what is wrong? Am I setting up the directional light incorrectly? Thanks in advance.
KyRo1989
KyRo1989
1. u use glLightfv to assign the values, so you have to assign a pointer. I don't know whether it is just one, in delphi you have to place an @ before the variable or constant, I don't know which language u use, maybe there's a similar way.
2. your light position describes a direction exactly to -y. this may look a little bit strange because all "walls" will get darken. Ambient light is just a value which is added to every calculation, it doesn't depend on normals. However - you won't get happy with wierd looking standard opengl lighting, so you should learn how to use GLSL, too

greets KyRo1989
James Trotter
James Trotter
That piece of code seems alright, (except the normalizeVector(lightPos); the vector is obviously unit-length from before...)
Post some more relevant code, i.e. the rest of the lighting setup, (I don't see glEnable(GL_LIGHTING) in there, for example), and also the code that you use to calculate the normals.
Isolier
Isolier
Hey,

The lighting appears to work somewhat correctly now, the problem was I wasn't storing the calculated vertex normals correctly(somewhat of a "Javaism" if you will). However, there may be some inacuracy in the normal calculations as the terrain appears to be somewhat bumpy. Here is a screenshot so you can see what I mean.

Also, I noticed that I am getting negative numbers in my normals x and z values, is this correct or shouldn't the normal's x, y and z values always be positive?

Well, the surface normal calculation is as such:
int surfaceNormalsIndex = 0;for(int y = -1; y <= mapLength - 1; y++){		float height1, height2, height3;	for(int x = -1; x <= mapWidth - 1; x++)	{		if(x == -1 || x == mapWidth - 1 || y == -1 || y == mapLength -1)		{			surfaceNormals[surfaceNormalsIndex++] = new float[]{0.0f, 1.0f, 0.0f};			surfaceNormals[surfaceNormalsIndex++] = new float[]{0.0f, 1.0f, 0.0f};		}		else		{			height1 = heightBuffer[(y*mapWidth)+x];			height2 = heightBuffer[((y+1)*mapWidth)+x];			height3 = heightBuffer[(y*mapWidth)+x+1];						float[] vec1 = {0.0f, height2 - height1, 1.0f};			float[] vec2 = {1.0f, height3 - height1, 0.0f};			surfaceNormals[surfaceNormalsIndex++] = GameUtil.crossProduct(vec1, vec2);						height1 = height3;			height3 = heightBuffer[((y+1)*mapWidth)+x+1];						vec1[1] = height2 - height1;			vec2[1] = height3 - height1;						surfaceNormals[surfaceNormalsIndex++] = GameUtil.crossProduct(vec1, vec2);		}	}}


I then normalize them with:

for(int i = 0; i < surfaceNormals.length; i++){	GameUtil.nomalizeVector(surfaceNormals);}


And finally I calculate the vertex normals with:


int triRowOffset = ((mapWidth+1)*2)-1;int triIndex     = 1;int vertexIndex  = 0;float[] currentNormal = new float[3];float[][] tempVec = new float[6][3];for(int z = 0; z < mapLength; z++){	for(int x = 0; x < mapWidth; x++)	{		tempVec[0] = surfaceNormals[triIndex];		tempVec[1] = surfaceNormals[triIndex + 1];		tempVec[2] = surfaceNormals[triIndex + 2];		tempVec[3] = surfaceNormals[triRowOffset + triIndex];		tempVec[4] = surfaceNormals[triRowOffset + triIndex + 1];		tempVec[5] = surfaceNormals[triRowOffset + triIndex + 2];				currentNormal[0] = (tempVec[0][0] + tempVec[1][0] + tempVec[2][0] + tempVec[3][0] + tempVec[4][0] + tempVec[5][0]) / 6.0f;		currentNormal[1] = (tempVec[0][1] + tempVec[1][1] + tempVec[2][1] + tempVec[3][1] + tempVec[4][1] + tempVec[5][1]) / 6.0f;		currentNormal[2] = (tempVec[0][2] + tempVec[1][2] + tempVec[2][2] + tempVec[3][2] + tempVec[4][2] + tempVec[5][2]) / 6.0f;		 		vertexNormals[vertexIndex][0] = currentNormal[0];                vertexNormals[vertexIndex][1] = currentNormal[1];                vertexNormals[vertexIndex][2] = currentNormal[2];				triIndex +=2;		vertexIndex++;	}	triIndex += 2;}


So there you have it, sorry to bombard you with so much code. I have verified my little helper methods, crossProduct() and normalizeVector(), so I know those aren't miscalculating antyhing. You may(or may not) notice that it is Java... Thanks again.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.