Terrain Lighting

Hi,

I am sure this topic is a very well worn one, but I seem to be having a specific problem. I can’t for the life of me seem to be able to get my textured terrain to light properly. Or at all for that matter. I do some vector math to calculate the normals for each point.

    private void computeNormals() {
        if (!computedNormals) {
            //only do it if the normals aren't computed already
            //Vec3f[][] normals2 = new Vec3f[width][height];
            normals = new Vec3f[width][height];
            
            for (int z=0; z<height; z++) {
                for (int x=0; x<width; x++) {
                    Vec3f sum = new Vec3f(0.0f, 0.0f, 0.0f);
                    
                    Vec3f out = new Vec3f(0.0f,0.0f,0.0f);
                    if (z > 0) {
                        out = new Vec3f(0.0f, getHeight(x,z-1) - getHeight(x,z),
                                -1.0f);
                    }
                    
                    Vec3f in = new Vec3f(0.0f,0.0f,0.0f);
                    if (z < height - 1) {
                        in = new Vec3f(0.0f, getHeight(x,z+1) - getHeight(x,z),
                                1.0f);
                    }
                    
                    Vec3f left = new Vec3f(0.0f,0.0f,0.0f);
                    if (x > 0) {
                        left = new Vec3f(-1.0f, getHeight(x-1,z) - getHeight(x,z), 
                                0.0f);
                    }
                    
                    Vec3f right = new Vec3f(0.0f,0.0f,0.0f);
                    if (x < width - 1) {
                        right = new Vec3f(1.0f, getHeight(x+1,z) - getHeight(x,z),
                                0.0f);
                    }
                    
                    if (x > 0 && z > 0) {
                        sum = sum.add(out.cross(left).normalize());
                    }
                    if (x > 0 && z < height - 1) {
                        sum = sum.add(left.cross(in).normalize());
                    }
                    if (x < width - 1 &&z < height -1) {
                        sum = sum.add(in.cross(right).normalize());
                    }
                    if (x < width - 1 && z > 0) {
                        sum = sum.add(right.cross(out).normalize());
                    }
                    
                    sum = sum.normalize();
                    
                    normals[x][z] = sum;
                }
            }
            
            computedNormals = true;
            
        }
    }

And then I pass it to my function to draw the actual terrain

    public void drawTerrain(Terrain terr, float bumpup) {
        /*if (!changeColor) {
            glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
        } else {
            glColor4f(0.0f, 0.0f, 0.0f, 0.2f);
        }*/
        if (terr != null) {
            for (int z = 0; z < terr.height; z++) {
                //we are drawing rows of x's
                glBegin(GL_QUAD_STRIP);
                for (int x = 0; x < terr.width; x++) {
                    if (bumpup != 0 && (terr.getHeight(x,z) <= 4.9)) {
                        glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
                    } else if(bumpup == 0) {
                        glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
                    } else if (bumpup != 0) {
                        glColor4f(0.0f,0.0f,0.0f,0.2f);
                    }
                    Vec3f normal = terr.getNormal(x, z);
                    //System.out.println(normal);
                    glNormal3f(normal.x, normal.y, normal.z);
                    glVertex3f(x+terr.xOffset, terr.getHeight(x,z)+bumpup-20.0f, 
                            z+terr.zOffset);
                    if (z != terr.height - 1) {
                        normal = terr.getNormal(x, z+1);
                        glNormal3f(normal.x, normal.y, normal.z);
                        glVertex3f(x+terr.xOffset, terr.getHeight(x,z+1)+bumpup-20.0f, 
                                z+1+terr.zOffset);
                    }
                }
                glEnd();
            }
        }
    }

But I end up with a plain green sheet without definition. If it means anything, each Terrain has a x and z offset value, as the larger terrain is split into chunks. The ground is also textured, but I do not know if that means anything.

I would appreciate any help,
Jacob

You can see some height change in the above image.

But it cannot be seen without the wireframe overlayed.

Have you enabled lighting with glEnable(GL_LIGHTING) and enabled a particular light, such as glEnable(GL_LIGHT0)?

Yeah. The lighting related code is below;

        glEnable(GL_LIGHTING);
        glEnable(GL_LIGHT0);
        //glEnable(GL_LIGHT1);
        glEnable(GL_NORMALIZE);
        glEnable(GL_CULL_FACE);
        glShadeModel(GL_SMOOTH);
        
        ...
     
        //setup lighting
        //add some ambient light. [special lwjgl fixes]
        ByteBuffer temp = ByteBuffer.allocateDirect(20);
        temp.order(ByteOrder.nativeOrder());

        glLightModel(GL_LIGHT_MODEL_AMBIENT, (FloatBuffer)temp.asFloatBuffer().put(new float[]{0.2f,0.2f,0.2f,1.0f}).flip());
        
        //add positioned light
        glLight(GL_LIGHT0, GL_DIFFUSE, (FloatBuffer)temp.asFloatBuffer().put(new float[]{0.5f,0.5f,0.5f,1.0f}).flip());
        glLight(GL_LIGHT0, GL_POSITION, (FloatBuffer)temp.asFloatBuffer().put(new float[]{4.0f,0.0f,8.0f,1.0f}).flip());