PDA

View Full Version : OpenGL lighting problem



Outtey
01-16-2010, 11:33 AM
Hello all! I have just started working with OpenGL and I seem to be having some problems regarding lighting and I was hoping someone would be able to help me out. Here's my situation, I have a diamond with a ball circling it. I need the ball to light the diamond. From what I have done so far, there is light but it doesn't seem to be coming from the ball. Also, I'm not sure if I'm calculating the normals correctly. Any help or recommendations would be highly appreciated!


#ifdef _WINDOWS
#include <windows.h>
#endif

#include <gl/gl.h>
#include <gl/glu.h>
#include <math.h>
#include <stdio.h>

#include "CGfxOpenGL.h"
#include "gmath.h"

// disable float-double conversion warnings
#pragma warning(disable:4305)
#pragma warning(disable:4244)

extern bool Wireframe;

CGfxOpenGL::CGfxOpenGL()
{
}

CGfxOpenGL::~CGfxOpenGL()
{
Shutdown();
}

bool CGfxOpenGL::Init()
{
// erase the background to black
glClearColor(0.0, 0.0, 0.0, 0.0);

// initialize a rotation angle
m_angle = 0.0f;

// create a quadric object for drawing spheres
m_Quadric = gluNewQuadric();

return true;
}

bool CGfxOpenGL::Shutdown()
{
// delete the quadric object
if (m_Quadric != NULL) {
gluDeleteQuadric(m_Quadric);
m_Quadric = NULL;
}
return true;
}

void CGfxOpenGL::SetupProjection(int width, int height)
{
if (height == 0) // don't want a divide by zero
{
height = 1;
}

glViewport(0, 0, width, height); // reset the viewport to new dimensions
glMatrixMode(GL_PROJECTION); // set projection matrix current matrix
glLoadIdentity(); // reset projection matrix

// calculate aspect ratio of window
gluPerspective(52.0f,(GLfloat)width/(GLfloat)height,1.0f,1000.0f);

glMatrixMode(GL_MODELVIEW); // set modelview matrix
glLoadIdentity(); // reset modelview matrix

m_windowWidth = width;
m_windowHeight = height;
}

void CGfxOpenGL::Prepare(float dt)
{
// update the rotation angle
m_angle += 0.1f;
}

// draw a normal form the center of poly defined by p1, p2, p3
// using the normal value
// this function used to test/visualize the normal value
void DrawNormal(Vector3&amp; p1, Vector3&amp; p2, Vector3&amp; p3, Vector3&amp; normal) {
Vector3 center;

// compute the center of the poly
center = p1 + p2 + p3;
center.scale(1.0/3.0);

// temporarily disable lighting to draw the normal line
glDisable(GL_LIGHTING);


// draw a small white line to represent the normal
glBegin(GL_LINES);
glColor3f(1.0, 1.0, 1.0);
glVertex3f(center.x, center.y, center.z);
glColor3f(1.0, 1.0, 1.0);
glVertex3f(center.x + normal.x, center.y + normal.y, center.z + normal.z);

glEnd();

// re-enable lighting
glEnable(GL_LIGHTING);
}


// define a single sided face
struct Face {
int i1, i2, i3; // indexes into vertex data
};

void CGfxOpenGL::Render()
{
// enable color tracking
glEnable(GL_COLOR_MATERIAL);
// set material properties which will be assigned by glColor
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
// enable lighting
glEnable(GL_LIGHTING);
int numFaces = 8;
Vector3 p1, p2, p3; // points or vertices of the triangle

// define 5 vertices of a diamond shape - colors not being used now
Vector3 vertexes[] = {
Vector3( 0, 2, 0 ), // vertex 0
Vector3( 1, 0, 1 ), // vertex 1
Vector3( 1, 0, -1 ), // vertex 2 ...
Vector3( -1, 0, -1 ),
Vector3( -1, 0, 1 ),
Vector3( 0, -2, 0 )
};

// set up the face index data into the vertex array above
// each triple will define a single face (triangle) of our shape
Face faceData[] = {
0, 4, 1, // top front-facing face
0, 3, 4, // top left face
0, 2, 3, // top rear face
0, 1, 2, // top right face
5, 1, 4, // bottom front face ...
5, 4, 3,
5, 3, 2,
5, 2, 1,
};

// clear screen and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

// enable z or depth buffer testing
glEnable(GL_DEPTH_TEST);

//if (Wireframe) {
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//}
//else {
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
//}


// move the whole scene back
glTranslatef(0.0, 0.0, -10.0f);

// set up a temporary transform for the orbiting sphere
glPushMatrix();


// make light rotate about an odd axis
glRotatef(m_angle, 1.0f, 1.0f, 0.0f);

// move the light into upper left corner of the scene
glTranslatef(-2.0f, 2.0f, 3.0f);
// setup and enable light
GLfloat lightPos[] = {0.0f, 0.0f, 1.0f, 1.0f};
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
GLfloat specular[] = {0.0f, 0.0f, 0.0f , 1.0f};
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
GLfloat ambient[] = {1.0f, 1.0f, 1.0f , 1.0f};
glLightfv(GL_LIGHT0, GL_AMBIENT_AND_DIFFUSE, ambient);
glEnable(GL_LIGHT0);

// draw a small sphere for light position
glColor3f(1.0, 1.0, 1.0);
gluSphere(m_Quadric, 0.2, 10, 10);

glPopMatrix();

// rotate object about Y
glRotatef(m_angle*2, 0.0f, 1.0f, 0.0f);

// for each of the 8 faces
for (int i=0; i < numFaces; i++) {
// draw the faces that make up the diamond shape
glBegin(GL_TRIANGLES);
glColor3f(1.0, 0.0, 0.0);
GLfloat colorRed[] = { 1.0f, 0.0f, 0.0f, 1.0f};
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, colorRed);
GLfloat specReflection[] = { 0.8f, 0.8f, 0.8f, 1.0f };
glMaterialfv(GL_FRONT, GL_SPECULAR, specReflection);
glMateriali(GL_FRONT, GL_SHININESS, 96);


// draw 3 vertices with color, light and normal info
// vertex 1
p1 = vertexes[faceData[i].i1];
glVertex3f(p1.x, p1.y, p1.z);

// vertex 2
p2 = vertexes[faceData[i].i2];
glVertex3f(p2.x, p2.y, p2.z);

// vertex 3
p3 = vertexes[faceData[i].i3];
glVertex3f(p3.x, p3.y, p3.z);

// calculate new normal
Vector3 n1 = p2-p1;
Vector3 n2 = p3-p1;
Vector3 newN = CrossProduct(n1,n2);

// vertex 1
glNormal3f(newN.x, newN.y, newN.z);
glVertex3f(p1.x, p1.y, p1.z);

// vertex 2
glNormal3f(newN.x, newN.y, newN.z);
glVertex3f(p2.x, p2.y, p2.z);

// vertex 3
glNormal3f(newN.x, newN.y, newN.z);
glVertex3f(p3.x, p3.y, p3.z);

vertexes[faceData[i].i1] = p1;
vertexes[faceData[i].i2] = p2;
vertexes[faceData[i].i3] = p3;


glEnd();

}
}

Dark Photon
01-16-2010, 06:56 PM
...having some problems regarding lighting...I have a diamond with a ball circling it. I need the ball to light the diamond. From what I have done so far, there is light but it doesn't seem to be coming from the ball.
One potential cause is that your ball (sphere) is centered on 0,0,0 in the local object space, but you position the light source at 0,0,1. Change the latter to 0,0,0.


Also, I'm not sure if I'm calculating the normals correctly.
Are the normals you're passing to glNormal guarenteed to be unit vectors? If not, normalize them before passing them in. Or glEnable( GL_NORMALIZE ) to ask OpenGL to do it.

See the first tip here:
http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/