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) {
glMatrixMode(GL11.GL_PROJECTION);
glLoadIdentity();
gluPerspective(80f, (float) width / height, .1f, 100f);
//glOrtho(0, width, height, 0, .1, 1000);
glMatrixMode(GL11.GL_MODELVIEW);
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
glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
// 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
glBegin(GL_TRIANGLE_FAN);
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]);
}
glEnd();
}
}
}
private void setUpLighting(int width, int height) {
glShadeModel(GL_FLAT);
glEnable(GL_LIGHTING);
float lightPosition[] = { height, 0f, 4f, 0.0f };
FloatBuffer lPos = ByteBuffer.allocateDirect(16).order(ByteOrder.nativeOrder()).asFloatBuffer();
lPos.put(lightPosition).flip();
/*
FloatBuffer lightColor = ByteBuffer.allocateDirect(16).asFloatBuffer();
lightColor.mark();
lightColor.put(new float[] { .5f, .5f, .5f, 1f });
lightColor.reset();
*/
float lightDiffuse[] = { .2f, .2f, .2f, 1.0f };
FloatBuffer lDif = ByteBuffer.allocateDirect(16).order(ByteOrder.nativeOrder()).asFloatBuffer();
lPos.put(lightDiffuse).flip();
glLight(GL_LIGHT0, GL_DIFFUSE, lDif);
FloatBuffer position = ByteBuffer.allocateDirect(16).asFloatBuffer();
position.mark();
position.put(new float[] { height, 0f, 4f, 0.0f });
position.reset();
glLight(GL_LIGHT0, GL_POSITION, lPos);
glEnable(GL_LIGHT0);
//GL11.glLight(GL11.GL_LIGHT0, GL11.GL_AMBIENT, ambient);
//glLight(GL_LIGHT1, GL_DIFFUSE, ambient);
//glLight(GL_LIGHT1, GL_SPECULAR, ambient);
//glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 1.5f);
//glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.5f);
//glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.2f);
//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 };
}
}
[/QUOTE]</div>
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!
-geekygenius