Here is the full code listing
And the highlights:
The Materials.java file has static methods for changing the material settings.
public class Materials {
public static void set_material_properties(GL gl, float[] ambient,
float[] diffuse, float[] specular, float[] shine) {
gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT, ambient, 0);
gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_DIFFUSE, diffuse, 0);
gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_SPECULAR, specular, 0);
gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_SHININESS, shine, 0);
}
public static void emerald(GL gl) {
Materials.set_material_properties(
gl,
new float[]{0.0215f, 0.1745f, 0.0215f},
new float[]{0.07568f, 0.61424f, 0.07568f},
new float[]{0.633f, 0.727811f, 0.633f},
new float[]{0.6f});
}
...
so to set the material to emerald, you simply have to call
Materials.emerald(gl);
This cleans up the code in the main program quite a bit. It is always good to try to refactor your code as you expand upon it.
The other major change is the light position. One mistake I fall prey to is seeing that the scene is dark in some areas and attributing this to light not hitting those areas because it is too far away. This is actually the opposite of what is happening. Namely, light is not hitting the areas because the light is TOO CLOSE. Uncomment the last two lines and see how much worse the scene becomes.
float[] light0_pos = {500.0f, 1000.0f, -1000.0f, 1.0f};
float[] light1_pos = {-1000.0f, 1000.0f, 500.0f, 1.0f};
// float[] light0_pos = {50.0f, 100.0f, -100.0f, 1.0f};
// float[] light1_pos = {-100.0f, 100.0f, 50.0f, 1.0f};
One last important note is that we need to enable depth testing, or we will see through walls, depending on the order that parts of an object are rendered - so if a rear wall which should be obscured is rendered last, we will see it. To avoid this issue we set:
//prevent us from seeing through object walls -obey depth rules instead of
//just order that an object's walls are rendered
gl.glEnable(GL.GL_DEPTH_TEST);