Lighting a Triangle Fan

So, I have been building a dynamic terrain renderer, and it was going well until I needed to add lighting. I am new to OpenGL, and I have no idea what is causing the problem, but I have a few ideas.

Here is my code so far, it is written in Java using LWJGL.
<div class=“ubbcode-block”><div class=“ubbcode-header”>Click to reveal… <input type=“button” class=“form-button” value=“Show me!” onclick=“toggle_spoiler(this, ‘Yikes, my eyes!’, ‘Show me!’)” />]<div style=“display: none;”>

package geekygenius.nutrality;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.util.glu.GLU.*;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import org.lwjgl.opengl.GL11;

public class DeafultMapRenderer implements MapRenderer {
	private final float HEIGHT_MOD = .5f;

	public void initilizeRenderer(Map map, int width, int height) {
		gluPerspective(80f, (float) width / height, .1f, 100f);
		//glOrtho(0, width, height, 0, .1, 1000);
		glRotatef(-30, 1.0f, 0.0f, 0.0f);
		glTranslatef(-(width / 64), 0, -10);
		setUpLighting(width, height);

		// Debug crap
		map.setHeightRange(10, 5, 2, 2, 2);
		map.setType(10, 5, BlockType.SEA);

		// Wire frame mode
		//glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );

	public void render(Map map) {
		// Clear the screen and depth buffer

		// set the color of the quad (R,G,B,A)
		glColor3f(0.1f, 0.8f, 0.1f); // Green

		// Allocate some memory for the verticies
		float[][] verticies = new float[6][3];
		float[] normal = new float[3];

		for (int x = 0; x < map.getWidth(); x++) {
			for (int y = 0; y < map.getHeight(); y++) {
				// TODO replace with ctual textures/shaders
				if (map.getType(x, y) == BlockType.LAND) {
					glColor3f(0.1f, 0.8f, 0.1f); // Green
				} else if (map.getType(x, y) == BlockType.SEA) {
					glColor3f(0.1f, 0.1f, 0.8f); // Blue

				// Calculate verticies now, so we don't have to re calculate
				// when finding normals
				verticies[0] = new float[] {x + .5f,y + .5f,average(map.getHeight(x, y), map.getHeight(x + 1, y),
                                         map.getHeight(x, y + 1),map.getHeight(x + 1, y + 1))* HEIGHT_MOD };
				verticies[1] = new float[] { x, y,map.getHeight(x, y) * HEIGHT_MOD };
				verticies[2] = new float[] { x + 1, y,map.getHeight(x + 1, y) * HEIGHT_MOD };
				verticies[3] = new float[] { x + 1, y + 1,map.getHeight(x + 1, y + 1) * HEIGHT_MOD };
				verticies[4] = new float[] { x, y + 1,map.getHeight(x, y + 1) * HEIGHT_MOD };
				verticies[5] = verticies[1];// Wrap it around

				glVertex3f(verticies[0][0], verticies[0][1], verticies[0][2]);
				glVertex3f(verticies[1][0], verticies[1][1], verticies[1][2]);
				for (int v = 2; v < 6; v++) {// v for vertex
					glVertex3f(verticies[v][0], verticies[v][1],verticies[v][2]);
					normal = getNormal(verticies[0][0], verticies[v - 1][0],verticies[v][0],
							verticies[0][1],verticies[v - 1][1], verticies[v][1],
							verticies[0][2], verticies[v - 1][2],verticies[v][2]);// Normal for top section
					//normal = new float [] {0.0f, 0.0f, 1.0f};
					glNormal3f(normal[0], normal[1], normal[2]);

	private void setUpLighting(int width, int height) {

		float lightPosition[] = { height, 0f, 4f, 0.0f };
		FloatBuffer lPos = ByteBuffer.allocateDirect(16).order(ByteOrder.nativeOrder()).asFloatBuffer();
		FloatBuffer lightColor = ByteBuffer.allocateDirect(16).asFloatBuffer();
		lightColor.put(new float[] { .5f, .5f, .5f, 1f });
    	float lightDiffuse[] = { .2f, .2f, .2f, 1.0f };
		FloatBuffer lDif = ByteBuffer.allocateDirect(16).order(ByteOrder.nativeOrder()).asFloatBuffer();
		glLight(GL_LIGHT0, GL_DIFFUSE, lDif);

		FloatBuffer position = ByteBuffer.allocateDirect(16).asFloatBuffer();
		position.put(new float[] { height, 0f, 4f, 0.0f });
		glLight(GL_LIGHT0, GL_POSITION, lPos);
		//GL11.glLight(GL11.GL_LIGHT0, GL11.GL_AMBIENT, ambient);
		//glLight(GL_LIGHT1, GL_DIFFUSE, ambient);
		//glLight(GL_LIGHT1, GL_SPECULAR, ambient);

		//glLightModel(GL_LIGHT_MODEL_AMBIENT, lDif);
		//glLightModeli(GL11.GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);		

	private float average(int a, int b, int c, int d) {
		return (a + b + c + d) / 4;

	private float[] getNormal(float x1, float x2, float x3, float y1, float y2,
			float y3, float z1, float z2, float z3) {
		float nx1 = (y3 - y1) * (z2 - z1) - (y2 - y1) * (z3 - z1);
		float ny1 = (z3 - z1) * (x2 - x1) - (z2 - z1) * (x3 - x1);
		float nz1 = (x3 - x1) * (y2 - y1) - (x2 - x1) * (y3 - y1);
		float fac1 = (float) Math.sqrt((nx1 * nx1) + (ny1 * ny1) + (nz1 * nz1));
		nx1 /= fac1;
		ny1 /= fac1;
		nz1 /= fac1;
		return new float[] { nx1, ny1, nz1 };


Essentially what is does is renders triangle fan squares to try and get an end result similar to Transport tycoon. If I enable wire-frame mode, and disable lighting, I get this next image, which is the target result as far as meshes go. [IMAGE1]

However, if I turn on lighting, I get a dimly lit mesh, or plane (depending if wire-frame is on or not). It looks something like this: [IMAGE2] The bottom half has been brightened so the rendered portion without lighting can be seen easier.

I don’t know what is causing this, I’ve probably forgot something obvious that I didn’t know existed yet. I have tried tinkering with a few different things, and left them commented, but I can’t guarentee every combination was tried. Anyways, thanks for taking the time to read my post and post an answer if you did!


In your TRIANGLE_FAN rendering code,

compute the normals first and do glNormal() followed by glVertex() and check.

I still get the same results as before. Maybe something is wrong with my lighting?

Are you calling to set up lighting before rendering your triangle fan?

Your code only describes the class methods. Just check the sequence used to call your methods.

Also, call glNormal() before glVertex to assign normals to the vertices.

I got textures to work properly, and I think they are applied the same way as normals, before the vertex. Yes, I checked, and the methods are being called at the appropriate times.

There are several reasons why fixed function lighting can go wrong.
Firstly the polygon winding may be wrong for some of the vertices and this may be flipping the normals.
Secondly the mesh may not be tessellated enough for lighting.
Thirdly your lighting setup may be wrong and the most common cause of issues is not calling glLightv immediately after setting the modelview matrix (ie after glulookat)

So, I re-ordered the gl calls, according to the way you described earlier, and it works lust how it should! Thanks!