so I learned about how to establish a local viewer, which I understand, considers not only the angle between a surface normal and the light source(s), but also the angle between the viewer and the surface. So I decided to try to test it out, but can’t seem to obtain any noticeable results.
My intent with the following program, is to draw a sierpinski gasket, at (0,0,-20), give it high specular reflectance, set it rotating about (1,0,0), and place a light source directly above it at (0,10,-20). I hope then, when the object has been rotated 45 degrees, i will see a spotlike reflection of the light on the surface of the object, or at least, see the object reach maximum illumination at that point. I am seeing neither, and getting some odd results.
Here is the full program, it uses glut:
#include "stdafx.h" // for visual C++
#include "glut.h"
#include <gl/gl.h>
#include <gl/glu.h>
float spinAngle = 0; // used for spinning rendered object
// properties for light0
float ambientLight0[] = { 1, 1, 1, 1.0f };
float diffuseLight0[] = { 1, 1, 1, 1.0f };
float specularLight0[] = {1, 1, 1, 1.0f};
float lightLocation0[] = {0, 10.0f, -20.0f, 1.0f }; /* intended to be directly above the object */
// Material light properties for the object
float matAmbient[] = { 0.1f, 0.1f, 0.4f, 1.0f }; // blueish
float matDiff[] = { 0.1f, 0.1f, 0.1f, 1.0f};
float matSpec[] = {0.5f, 0.5f, 0.5f, 1.0f}; // high specular
static void _Timer(int value)
{
// increment angle
spinAngle += 0.5;
while (spinAngle > 360)
spinAngle -= 360;
// send redisplay event
glutPostRedisplay();
// call this function again in 10 milliseconds
glutTimerFunc(10, _Timer, 0);
}
void initLighting()
{
// enable lighting
glEnable(GL_LIGHTING);
glPushMatrix(); /* push and clear modelview matrix to ensure light0's location is not transformed */
glLoadIdentity();
// use a local view
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
// Setup the material properties for the object
glMaterialfv(GL_FRONT, GL_AMBIENT, matAmbient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, matDiff);
glMaterialfv(GL_FRONT, GL_SPECULAR, matSpec);
glMaterialfv(GL_BACK, GL_AMBIENT, matAmbient);
glMaterialfv(GL_BACK, GL_DIFFUSE, matDiff);
glMaterialfv(GL_BACK, GL_SPECULAR, matSpec);
// Now setup LIGHT0
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight0);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight0);
glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight0);
glLightfv(GL_LIGHT0, GL_POSITION, lightLocation0);
// enable light0
glEnable(GL_LIGHT0);
}
void init()
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel (GL_SMOOTH);
// initialize lighting
initLighting();
}
void drawSquare(float x, float y, float length)
{
// a simple square drawing routine
length /= 2; // halve the length so the square is centered at (x,y)
glNormal3f(0,0,1);
glBegin(GL_QUADS);
glVertex3f(x-length, y-length, 0);
glVertex3f(x+length, y-length, 0);
glVertex3f(x+length, y + length, 0);
glVertex3f(x -length, y + length,0);
glEnd();
}
void drawGasket(float x, float y, float length, int depth)
{
// draw a sierpinski gasket
if (depth <= 1)
{
drawSquare(x,y, length);
return;
}
//else
depth--;
drawGasket(x, y, length/3, depth);
drawGasket(x + length/3, y,length/3, depth);
drawGasket(x + 2*length/3, y,length/3, depth);
drawGasket(x, y - length/3, length/3, depth);
drawGasket(x + 2*length/3, y - length/3, length/3, depth);
drawGasket(x, y- 2*length/3, length/3, depth);
drawGasket(x + length/3, y- 2*length/3, length/3, depth);
drawGasket(x + 2*length/3, y-2*length/3,length/3, depth);
}
void display(void)
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(-4,0,-20); // place the object at z = -20 so it is under light0, nudge left to center
glRotatef(spinAngle, 1,0,0);
drawGasket(0,0,8,5); // an 8x8 sierpinski gasket with a recursize depth of 5 at (0,0)
glutSwapBuffers();
}
void reshape (int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective(30.0f, w/(float)h, 1, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutTimerFunc(10, _Timer, 0);
glutMainLoop();
return 0;
}
the results don’t make sense. The object abruptly becomes fully lit when its at 45 degrees off the zy plane, and goes dark again when it reaches -270, as shown below:
doesn’t seem to be behaving at all how i’d expect. Can anyone explain why?
(edit) my diagram is dumb, pivot point and light0 should be horizontally aligned, but you get the idea.