dagon
dagon

Reputation: 67

OpenGL first steps with light and normals

I'm playing around with some basic OpenGL stuff and I'm trying to set up a simple square with lighting enabled, but the lighting is not correct so there is something wrong with my normals i guess.

Or is my understanding of normals totally wrong?

enter image description here

Here's my rendering code (btw I'm using lwjgl): public class Renderer {

DisplayMode displayMode;
int i;
int width;
int height;
private boolean drawAxes = false;
private float rotation = 40.0f;
private float zoom = -20f;

// ----------- Variables added for Lighting Test -----------//
private FloatBuffer matSpecular;
private FloatBuffer lightPosition;
private FloatBuffer whiteLight;
private FloatBuffer lModelAmbient;

public Renderer(int width, int height) {
    this.width = width;
    this.height = height;
}

public static Renderer start() throws LWJGLException {
    Renderer r = new Renderer(800, 600);
    r.initContext();
    r.run();
    return r;
}

private void initContext() throws LWJGLException {
    Display.setFullscreen(false);
    DisplayMode d[] = Display.getAvailableDisplayModes();
    for (int i = 0; i < d.length; i++) {
        if (d[i].getWidth() == width && d[i].getHeight() == height && d[i].getBitsPerPixel() == 32) {
            displayMode = d[i];
            break;
        }
    }
    Display.setDisplayMode(displayMode);
    Display.create();
}

private void run() {
    initGL();
    while (!Display.isCloseRequested()) {
        preRender();
        render();
        Display.update();
        Display.sync(60);
    }
    Display.destroy();
}

private void initGL() {

    GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Black Background
    GL11.glClearDepth(1.0); // Depth Buffer Setup
    GL11.glEnable(GL11.GL_DEPTH_TEST); // Enables Depth Testing
    GL11.glDepthFunc(GL11.GL_LEQUAL); // The Type Of Depth Testing To Do

    GL11.glMatrixMode(GL11.GL_PROJECTION); // Select The Projection Matrix
    GL11.glLoadIdentity(); // Reset The Projection Matrix

    // Calculate The Aspect Ratio Of The Window
    GLU.gluPerspective(45.0f, (float) displayMode.getWidth() / (float) displayMode.getHeight(), 0.1f, 100.0f);
    GL11.glMatrixMode(GL11.GL_MODELVIEW); // Select The Modelview Matrix

    // Really Nice Perspective Calculations
    GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);

    GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);

    initLightArrays();
    glShadeModel(GL_SMOOTH);
    glMaterial(GL_FRONT, GL_SPECULAR, matSpecular); // sets specular material color
    glMaterialf(GL_FRONT, GL_SHININESS, 100.0f); // sets shininess

    glLight(GL_LIGHT0, GL_POSITION, lightPosition); // sets light position
    glLight(GL_LIGHT0, GL_SPECULAR, whiteLight); // sets specular light to white
    glLight(GL_LIGHT0, GL_DIFFUSE, whiteLight); // sets diffuse light to white
    glLightModel(GL_LIGHT_MODEL_AMBIENT, lModelAmbient); // global ambient light

    glEnable(GL_LIGHTING); // enables lighting
    glEnable(GL_LIGHT0); // enables light0

    glEnable(GL_COLOR_MATERIAL); // enables opengl to use glColor3f to define material color
    glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); // tell opengl glColor3f effects the ambient and diffuse properties of material

}

private void preRender() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    GL11.glTranslatef(0f, 0f, zoom);
    GL11.glRotatef(-60f, 1f, 0f, 0f);
    GL11.glRotatef(rotation, 0f, 0f, 1f);
}

private void render() {

    FloatBuffer cBuffer = BufferUtils.createFloatBuffer(6*3);
    float[] cArray = {  1f,1f,1f,
                        1f,1f,1f,
                        1f,1f,1f,
                        1f,1f,1f,
                        1f,1f,1f,
                        1f,1f,1f};
    cBuffer.put(cArray);
    cBuffer.flip();

    FloatBuffer vBuffer = BufferUtils.createFloatBuffer(6*3);
    float[] vArray = {  1f,1f,0f,
                        -1f,-1f,0,
                        1f,-1f,0,
                        1f,1f,0f,
                        -1f,1f,0,
                        -1f,-1f,0};
    vBuffer.put(vArray);
    vBuffer.flip();

    FloatBuffer nBuffer = BufferUtils.createFloatBuffer(6*3);
    float[] nArray = {  0f,0f,1f,
                        0f,0f,1f,
                        0f,0f,1f,
                        0f,0f,1f,
                        0f,0f,1f,
                        0f,0f,1f};
    nBuffer.put(nArray);
    nBuffer.flip();

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);

    glColorPointer(3, 0, cBuffer);
    glVertexPointer(3, 0, vBuffer);
    glNormalPointer(3, nBuffer);
    glDrawArrays(GL_TRIANGLES, 0, 6);

    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);

    if (drawAxes) {
        drawAxes(6);
    }

    glTranslatef(0.0f, 0.0f, 3);
    glColor3f(0.1f, 0.4f, 0.9f);
}

public static void main(String[] args) throws LWJGLException {
    System.setProperty("org.lwjgl.opengl.Display.allowSoftwareOpenGL", "true");
    Renderer.start();
}

Upvotes: 0

Views: 476

Answers (2)

derhass
derhass

Reputation: 45332

You are setting your normal pointer wrong:

glColorPointer(3, 0, cBuffer);
glVertexPointer(3, 0, vBuffer);
glNormalPointer(3, nBuffer);

The fixed-function GL might always expects normals to be 3-dimensional vectors, henze the size parameter (which tells the GL how many values are there in every vector) is not present in glNormalPointer. The 3 you are setting here is the stride parameter, which specifies the byte offset between consecutive array elements. Now 3 does not make any sence, it will interpret the second normal as to beginning 3 bytes into the arry, which means it combines the last byte of your first normal's x component together with 3 bytes from your first normal's y component when it reads the second normal'x s component, and so on...

Since your array is tightly packed, you can use the shortcut 0 here, like you do with the other pointers.

However, you must be aware that all of that is deprecated since almost a decade in OpenGL, modern core versions of OpenGL do not support the fixed function pipeline at all. If you are learning OpenGL nowadays, I strongly recommend you to learn modern, shader-based GL instead.

Upvotes: 1

Xirema
Xirema

Reputation: 20396

Without seeing more of your code, it's very difficult to see exactly what's going wrong.

However, I do see one thing that could be a problem:

FloatBuffer vBuffer = BufferUtils.createFloatBuffer(6*3);
float[] vArray = {  1f,1f,0f,
                    1f,-1f,0,
                    -1f,-1f,0,
                    1f,1f,0f,
                    -1f,1f,0,
                    -1f,-1f,0};
vBuffer.put(vArray);
vBuffer.flip();

The winding order on your triangles are not the same. The first triangle winds clockwise, whereas the second triangle winds counter-clockwise. You'll need to reorder the vertices to make sure that they wind in the same direction. OpenGL usually prefers things to wind counter-clockwise, so if I were you, I'd flip the first triangle.

If you're still getting the problem after you've done this, then post the rest of your draw code, as what you're showing here doesn't give a lot of information.

Upvotes: 0

Related Questions