ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I'm trying to use OpenGL in a programme, but I'm running into problems with lighting. What I would like is for the models to be lit from the direction of the viewpoint (ie. as if there were a torch strapped to the viewer's head, or a light on the camera or something).
The code I have works for some facings, but when I rotate by 180 degrees the light seems to "go out". I'm not entirely sure if it's not actually following my viewpoint, or whether something isn't configured correctly. This is a compilable code example showing the problem:
Code:
#include <GL/freeglut.h>
#include <math.h>
#define WIDTH 11
#define HEIGHT 11
#define BLOCKSIZE 5.0
const static float fdspeed = BLOCKSIZE*(0.002/1.5), rotspeed = 0.05;
const static double deg_to_rad = 3.141592653589793/180;
static float x = WIDTH*BLOCKSIZE/2, z= HEIGHT*BLOCKSIZE/2, facing = 0.0;
static int fd = 0, rt = 0, strafe = 0;
void drawWalls(int width, int height){
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
glColor3f(1.0,1.0,1.0);
glBegin(GL_POLYGON);
glVertex3f(0.0,0.0,0.0);
glVertex3f(0.0,-BLOCKSIZE,0.0);
glVertex3f(width*BLOCKSIZE,-BLOCKSIZE,0.0);
glVertex3f(width*BLOCKSIZE,0.0,0.0);
glEnd();
glBegin(GL_POLYGON);
glVertex3f(0.0,0.0,0.0);
glVertex3f(0.0,-BLOCKSIZE,0.0);
glVertex3f(0.0,-BLOCKSIZE,height*BLOCKSIZE);
glVertex3f(0.0,0.0,height*BLOCKSIZE);
glEnd();
glBegin(GL_POLYGON);
glVertex3f(0.0,0.0,height*BLOCKSIZE);
glVertex3f(0.0,-BLOCKSIZE,height*BLOCKSIZE);
glVertex3f(width*BLOCKSIZE,-BLOCKSIZE,height*BLOCKSIZE);
glVertex3f(width*BLOCKSIZE,0.0,height*BLOCKSIZE);
glEnd();
glBegin(GL_POLYGON);
glVertex3f(height*BLOCKSIZE,0.0,0.0);
glVertex3f(height*BLOCKSIZE,-BLOCKSIZE,0.0);
glVertex3f(height*BLOCKSIZE,-BLOCKSIZE,height*BLOCKSIZE);
glVertex3f(height*BLOCKSIZE,0.0,height*BLOCKSIZE);
glEnd();
}
void display(void){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glRotatef(facing, 0.0, 1.0, 0.0); // Rotate to the correct facing
glTranslatef(-x, 0.5*BLOCKSIZE, -z); // Move the models to the correct x and z co-ordinates
drawWalls(WIDTH,HEIGHT);
glPopMatrix();
glutSwapBuffers();
}
void reshape(int w, int h){
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat) w / (GLfloat) h, 0.45, (WIDTH>HEIGHT)?1.42*WIDTH*BLOCKSIZE:1.42*HEIGHT*BLOCKSIZE);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -1.0, 0.0); // y is 'up', we begin looking up the -ve z axis.
}
void movePlayer(void){
z += cos(facing*deg_to_rad)*fd*fdspeed;
x -= sin(facing*deg_to_rad)*fd*fdspeed;
z -= cos((facing+90)*deg_to_rad)*strafe*fdspeed;
x += sin((facing+90)*deg_to_rad)*strafe*fdspeed;
facing -= rt * rotspeed;
while(facing < 0) facing += 360.0;
while(facing >= 360) facing -= 360.0;
glutPostRedisplay();
}
void skeyboard(int key, int x, int y){
switch(key){
case GLUT_KEY_RIGHT:
rt = 1;
break;
case GLUT_KEY_LEFT:
rt = -1;
break;
default:
break;
}
if(fd == 0 && rt == 0 && strafe == 0) glutIdleFunc(NULL);
else glutIdleFunc(movePlayer);
}
void keyboard(unsigned char key, int x, int y){
switch(key){
case 'a':
strafe = -1;
break;
case 'd':
strafe = 1;
break;
case 'w':
fd = 1;
break;
case 's':
fd = -1;
break;
default:
break;
}
if(fd == 0 && rt == 0 && strafe == 0) glutIdleFunc(NULL);
else glutIdleFunc(movePlayer);
}
void skeyboardUp(int key, int x, int y){
switch(key){
case GLUT_KEY_RIGHT:
case GLUT_KEY_LEFT:
rt = 0;
break;
default:
break;
}
if(fd == 0 && rt == 0 && strafe == 0) glutIdleFunc(NULL);
else glutIdleFunc(movePlayer);
}
void keyboardUp(unsigned char key, int x, int y){
switch(key){
case 'a':
case 'd':
strafe = 0;
break;
case 'w':
case 's':
fd = 0;
break;
default:
break;
}
if(fd == 0 && rt == 0 && strafe == 0) glutIdleFunc(NULL);
else glutIdleFunc(movePlayer);
}
void init(void){
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_shininess[] = { 50.0 };
GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel (GL_SMOOTH);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glEnable(GL_NORMALIZE);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutKeyboardUpFunc(keyboardUp);
glutSpecialFunc(skeyboard);
glutSpecialUpFunc(skeyboardUp);
glutIdleFunc(movePlayer);
}
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();
glutMainLoop();
return 0;
}
Compile with
Code:
gcc file.c -o file -lglut -lGL -lGLU -Wall
The OpenGL-y stuff is in "main", "reshape", "display" and "init". The other functions are for handling input, plus a function to draw the walls.
Controls are WASD to move forward/left/back/right, left/right arrow keys to turn around. Expected behaviour is that you can always see the walls which are around you, actual behaviour is that the screen is almost black until you turn around to face the other direction.
Hi,
I don't know if it is the problem here, but I don't see any calls to glNormalXX in your code. You need to set normals to each surface you render so the OpenGL can determine the angle between the normal to the face and the direction to the source of the light. I don't know how Opengl treats normals if not specified, but it probably uses some default value such as 0.0, 0.0, 1.0 or so. If all normals are the same for all vertices in the scene, then if you look at the wall in one direction it is light because the normals are pointing towards you. If you then turn around 180 degrees the normals on the other wall will point away from you and the walls will be dark.
so for example the code to draw one of the walls could be
Note: Since the walls are rectangles, you could probably render them as GL_QUAD (or, even better, GL_TRIANGLE_STRIP) and draw all four walls within a single glBegin() / glEnd() pair, which should result in better performance.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.