Related
I am trying to make a background using SOIL_load_OGL_texture but when I added my 3D models the texture disappeared. The code for 3D models were separated from the texture code but when I combine it, the background becomes black and my 3D models is facing back. Is the problem here because of the coordination?
I expect the output would be the 3D models facing front and it is in front of the texture.
#include <stdlib.h>
#include <stdio.h>
#include <GL/glut.h>
#include "SOIL2.h"
GLuint myTexture;
const GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
const GLfloat mat_diffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f };
static int head = 0, rear = -90, lear = -90, body = 0, lleg = -90, rleg = -90, ball = 0, stage = 0;
GLfloat ballRadius = 0.1f;
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3d(0.5, 0.85, 0.9); // head
glPushMatrix();
glTranslated(0, 0.25, 0.15);
glRotated((GLfloat)head, 0, 1, 0);
glutSolidSphere(0.2, 40, 50);
glPopMatrix();
glPushMatrix(); //ear
glTranslated(0.11, 0.3, 0.18);
glRotated((GLfloat)rear, 1, 0, 0);
glutSolidCone(0.08, 0.2, 16, 16);
glPopMatrix();
glPushMatrix(); //ear
glTranslated(-0.11, 0.3, 0.18);
glRotated((GLfloat)lear, 1, 0, 0);
glutSolidCone(0.08, 0.2, 16, 16);
glPopMatrix();
glColor3d(0.0, 0.0, 0.0); //eyes
glPushMatrix();
glTranslated(0.07, 0.3, 0.33);
glRotated(-5, 0, 0, 1);
glScalef(0.5, 0.1, 0.1);
glutSolidCube(0.1);
glPopMatrix();
glPushMatrix(); //eyes
glTranslated(-0.07, 0.3, 0.33);
glRotated(-5, 0, 0, -1);
glScalef(0.5, 0.1, 0.1);
glutSolidCube(0.1);
glPopMatrix();
glPushMatrix(); //mouth
glTranslated(0.0, 0.25, 0.35);
glRotated(0, 0, 0, 0);
glScalef(1, 0.1, 0.1);
glutSolidCube(0.1);
glPopMatrix();
glColor3d(1.0, 1.0, 1.0);
glPushMatrix(); // teeth
glTranslated(-0.045, 0.255, 0.34);
glRotated(-90, 1, 0, 0);
glutSolidCone(0.01, 0.02, 16, 16);
glPopMatrix();
glPushMatrix(); // teeth
glTranslated(0.045, 0.255, 0.34);
glRotated(-90, 1, 0, 0);
glutSolidCone(0.01, 0.02, 16, 16);
glPopMatrix();
glColor3d(0.5, 0.85, 0.88); // body
glTranslatef(0, 0, 0.1);
glPushMatrix();
glRotated((GLfloat)body, 1, 0, 0);
glutSolidSphere(0.3, 40, 50);
glPopMatrix();
glPushMatrix();
glTranslatef(0, 0.7, 0.0);
glRotatef((GLfloat)stage, 0.0, 1.0, 0.0);
glTranslatef(1.0, 0.0, 0.0);
glPushMatrix();
glScalef(2.0, 0.4, 1.0);
glutWireCube(1.0);
glPopMatrix();
//glFlush();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBindTexture(GL_TEXTURE_2D, myTexture);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
/*glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); */
glNormal3f(0.0, 1.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-2.5f, -2.5f, 2.5f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(2.5f, -2.5f, 2.5f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(2.5f, -2.5f, -2.5f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-2.5f, -2.5f, -2.5f);
glEnd();
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glutSwapBuffers();
}
void reshape(int width, int height)
{
if (height == 0) height = 1; // To prevent divide by 0
GLfloat aspect = (GLfloat)width / (GLfloat)height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//glFrustum(-ar + 1, ar - 1, -1.0, 1.0, 2.0, 90.0);
//gluOrtho2D(0, width, 0, height);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(640, 480);
glutCreateWindow("SOIL test");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
myTexture = SOIL_load_OGL_texture("background.png", 0, 1, SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_INVERT_Y);
if (!myTexture)
{
printf("soil failed to load texture\n");
}
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glutMainLoop();
return EXIT_SUCCESS;
}
If you want that the background image is draw in the back, then you've to draw the background first, but disable the Depth Test (The depth buffer has to be cleared before).
This causes that the other geometry covers the background.
When the background is drawn no projection matrix is set, the projection matrix is the identity matrix. So the z-coordinate of the background has to be in [-1, 1], else it wold be clipped by the near or far plane.
If texturing is enabled, then by default the color of the texel is multiplied by the current color, because by default the texture environment mode (GL_TEXTURE_ENV_MODE) is GL_MODULATE. See glTexEnv.
This causes that the color of the texels of the texture is "mixed" by the last color which you have set by glColor3d.
Set a "white" color before you render the texture:
glColor3d(1.0, 1.0, 1.0);
Note, OpenGL is a state engine. If a color was set, the color is kept until it is changed again, even beyond frames. So this might not be an issue in the first frame, but it would be in the further frames.
The fixed function light model is applied on the background, too. This will cause a bad look with fixed function gouraud light model. I recommend to disable lighting before you draw the background.
glDisable(GL_LIGHTING);
and to enable lighting before you draw the geometry
glEnable(GL_LIGHTING);
The function display may look like this:
void display(void)
{
// clear color buffer and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// prepare for drawing the back ground
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glColor3d(1.0, 1.0, 1.0);
// projection and model view for the background
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// draw the background
glBindTexture(GL_TEXTURE_2D, myTexture);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glEnd();
// prepare for drawing the geometry
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
// projection and model view for the geoemtry
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//glFrustum(-ar + 1, ar - 1, -1.0, 1.0, 2.0, 90.0);
//gluOrtho2D(0, width, 0, height);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// draw geometry
glColor3d(0.5, 0.85, 0.9); // head
// ...
glFlush();
glutSwapBuffers();
glutPostRedisplay();
}
I have a pixmap for some app in Xephyr and I need draw this pixmap on rectangle openGL. I seen example from khronos for pixmap when created in code but it's not working for me:
mPixmap = XCreatePixmap(dpy, client->getWindow(), static_cast<unsigned int>(attr.width),
static_cast<unsigned int>(attr.height), static_cast<unsigned int>(attr.depth));
And code where I drawed:
void startPluginPixmap() {
XEvent xev;
GLuint texture_id;
GLint pix_att[5] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
vi = glXChooseVisual(dpy, 0, pix_att);
swa.event_mask = ExposureMask | KeyPressMask;
swa.colormap = XCreateColormap(dpy, root, vi->visual, AllocNone);
uint64_t window_width = 300;
uint64_t window_height = 400;
uint32_t window_depth = vi->depth;
win = XCreateWindow(dpy, root, 0, 0, window_width, window_height, 0, window_depth, InputOutput, vi->visual, CWEventMask | CWColormap, &swa);
XMapWindow(dpy, win);
XStoreName(dpy, win, "PIXMAP TEST");
glc = glXCreateContext(dpy, vi, NULL, GL_TRUE);
if (!glc) {
exit(0);
}
glXMakeCurrent(dpy, win, glc);
glEnable(GL_DEPTH_TEST);
uint64_t pixmap_width = 150;
uint64_t pixmap_height = 100;
GC gc = DefaultGC(dpy, 0);
XFlush(dpy);
XImage * xim = XGetImage(dpy, mPixmap, 0, 0, pixmap_width, pixmap_height, AllPlanes, ZPixmap);
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &texture_id);
glBindTexture(GL_TEXTURE_2D, texture_id);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, pixmap_width, pixmap_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (void *)(&(xim->data[0])));
XDestroyImage(xim);
while(true) {
XNextEvent(dpy, &xev);
if (xev.type == Expose) {
redrawPixmapImage();
}
else if (xev.type == KeyPress && xev.xkeymap.type == 0x19) {
glXMakeCurrent(dpy, None, NULL);
glXDestroyContext(dpy, glc);
XDestroyWindow(dpy, win);
XCloseDisplay(dpy);
exit(0);
}
}
}
void Cube::redrawPixmapImage() {
XWindowAttributes gwa;
XGetWindowAttributes(dpy, win, &gwa);
glViewport(0, 0, gwa.width, gwa.height);
glClearColor(.0, 1.0, .0, .5);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.25, 1.25, -1.25, 1.25, 1., 20.);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0., 0., 10., 0., 0., 0., 0., 1., 0.);
glColor3f(1.f, 1.f, 1.f);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0);
//glColor3f(1.f, 0.f, 0.f);
glVertex3f(-1.0, 1.0, 0.0);
glTexCoord2f(1.0, 0.0);
glVertex3f( 1.0, 1.0, 0.0);
glTexCoord2f(1.0, 1.0);
glVertex3f( 1.0, -1.0, 0.0);
glTexCoord2f(0.0, 1.0);
glVertex3f(-1.0, -1.0, 0.0);
glTexCoord2f(1.0, 1.0);
glVertex3f(-1.0, 1.0, 0.0);
glEnd();
glXSwapBuffers(dpy, win);
}
In this code I enter width and height manual because get it in debug info.
And for me this calculation of textcoord doesn't work (When I run in Xephyr xeyes, and then this code, I seeing artifacts and green area).
So, how I can calculate texcoords for pixmap some app?
I'm trying to render a simple (10x3x10 in size) room using OpenGL and GLUT, written in C.
I'd like to create a simple statinary spotlight, while i can move around in the room.
(The ultimate goal is to make a spotlight coming from a lamp at the ceiling)
The problem is the light changes when i move the camera around.
I'm calling the following function from main():
void init() {
glEnable(GL_TEXTURE_2D);
loadTexture(); // loading some textures using SOIL
loadModels(); // loading some OBJ models
glShadeModel(GL_SMOOTH);
glEnable(GL_NORMALIZE);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glClearDepth(1);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glDepthFunc(GL_LEQUAL);
glClearColor(0, 0, 0, 1);
}
The function i pass to glutDisplayFunc():
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
initLight();
gluLookAt(x, 1.5f, z, x + vX, 1.5f, z + vZ, 0.0f, 1.5f, 0.0f);
// ...
// drawing the ground, ceiling and the walls
// no matrix transformations here, just simple glVertex () calls
// ...
glPushMatrix();
// drawing a table
glTranslatef(5, 0.842843, 5);
glBindTexture(GL_TEXTURE_2D, texture[1]);
draw_model(&modelTable);
// drawing some chairs
glTranslatef(0, -0.312053, chair1Position);
glBindTexture(GL_TEXTURE_2D, texture[2]);
draw_model(&modelChair1);
glTranslatef(0, 0, chair2Position);
draw_model(&modelChair2);
glPopMatrix();
glutSwapBuffers();
}
And the initLight() function:
void initLight() {
// i would like the light to originate from an upper corner
// directed to the opposing lower corner (across the room basically)
GLfloat lightPosition[] = { 10, 3, 0, 1 };
GLfloat lightDirection[] = { 0, 0, 10, 0 };
GLfloat ambientLight[] = { 0.3, 0.3, 0.3, 1 };
GLfloat diffuseLight[] = { 1, 1, 1, 1 };
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 180);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 64);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, lightDirection);
}
I was told this problem could be solved by the proper positioning of the glPushMatrix() and glPopMatrix() calls.
Wherever i put them, the light either keeps changing when i'm moving the camera or i got no light at all. I just cannot figure it out.
What would be a proper solution here?
Thanks in advance.
EDIT:
I've moved the initLight() call to after the gluLookAt() call as #derhass suggested below.
The light is still changing when i'm moving around.
There are two screenshots below.
On the first one the light is not even visible. When i turn slightly to the right, it appears.
EDIT2:
The full (stripped down) source code:
#include <GL/glut.h>
#include <SOIL/SOIL.h>
#include <math.h>
GLfloat lightPosition[] = { 10, 3, 0, 1 };
GLfloat lightDirection[] = { 0, 0, 10, 0 };
GLfloat diffuseLight[] = { 0, 1, 0, 1 };
GLfloat ambientLight[] = { 0.2, 0.2, 0.2, 1 };
float x = 1.0f, z = 5.0f;
float vX = 1.0f, vZ = 0.0f;
float angle = 1.5f;
int windowWidth = 1024;
int windowHeight = 768;
char* textureFiles[13] = { "floortexture.png", "tabletexture.png",
"chairtexture.png", "orange.png", "helptexture.png",
"fridgetexture.png", "oven.png", "yellow.png", "dishwasher.png",
"metallic.png", "cabinet.png", "wood.png", "cabinet2.png" };
GLuint texture[13];
void loadTexture() {
for (int i = 0; i < 13; i++) {
texture[i] = SOIL_load_OGL_texture(textureFiles[i], SOIL_LOAD_RGBA,
SOIL_CREATE_NEW_ID, 0);
glBindTexture(GL_TEXTURE_2D, texture[i]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
}
void init() {
glEnable(GL_TEXTURE_2D);
loadTexture();
glShadeModel(GL_SMOOTH);
glEnable(GL_NORMALIZE);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glClearDepth(1);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glClearColor(0, 0, 0, 1);
}
void processSpecialKeys(int key, int xx, int yy) {
float moveFraction = 0.2f;
float angleFraction = 0.1f;
switch (key) {
case GLUT_KEY_LEFT:
angle -= angleFraction;
vX = sin(angle);
vZ = -cos(angle);
break;
case GLUT_KEY_RIGHT:
angle += angleFraction;
vX = sin(angle);
vZ = -cos(angle);
break;
case GLUT_KEY_UP:
x += vX * moveFraction;
z += vZ * moveFraction;
if (x < 1) {
x = 1;
}
if (z < 1) {
z = 1;
}
if (x > 9) {
x = 9;
}
if (z > 9) {
z = 9;
}
break;
case GLUT_KEY_DOWN:
x -= vX * moveFraction;
z -= vZ * moveFraction;
if (x < 1) {
x = 1;
}
if (z < 1) {
z = 1;
}
if (x > 9) {
x = 9;
}
if (z > 9) {
z = 9;
}
break;
}
}
void initLight() {
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 180);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 128);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, lightDirection);
}
void renderWalls() {
// floor
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(0.0f, 0.0f, 0.0f);
glTexCoord2f(0, 8);
glVertex3f(0.0f, 0.0f, 10.0f);
glTexCoord2f(8, 8);
glVertex3f(10.0f, 0.0f, 10.0f);
glTexCoord2f(8, 0);
glVertex3f(10.0f, 0.0f, 0.0f);
glEnd();
// walls
glBindTexture(GL_TEXTURE_2D, texture[3]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// first wall
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(0.0f, 0.0f, 0.0f);
glTexCoord2f(0, 1);
glVertex3f(0.0f, 3.0f, 0.0f);
glTexCoord2f(1, 1);
glVertex3f(10.0f, 3.0f, 0.0f);
glTexCoord2f(1, 0);
glVertex3f(10.0f, 0.0f, 0.0f);
glEnd();
// second wall
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(10.0f, 0.0f, 0.0f);
glTexCoord2f(0, 1);
glVertex3f(10.0f, 3.0f, 0.0f);
glTexCoord2f(1, 1);
glVertex3f(10.0f, 3.0f, 10.0f);
glTexCoord2f(1, 0);
glVertex3f(10.0f, 0.0f, 10.0f);
glEnd();
// third wall
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(10.0f, 0.0f, 10.0f);
glTexCoord2f(0, 1);
glVertex3f(10.0f, 3.0f, 10.0f);
glTexCoord2f(1, 1);
glVertex3f(0.0f, 3.0f, 10.0f);
glTexCoord2f(1, 0);
glVertex3f(0.0f, 0.0f, 10.0f);
glEnd();
// fourth wall
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(0.0f, 0.0f, 0.0f);
glTexCoord2f(0, 1);
glVertex3f(0.0f, 3.0f, 0.0f);
glTexCoord2f(1, 1);
glVertex3f(0.0f, 3.0f, 10.0f);
glTexCoord2f(1, 0);
glVertex3f(0.0f, 0.0f, 10.0f);
glEnd();
// ceiling
glBindTexture(GL_TEXTURE_2D, texture[7]);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(0.0f, 3.0f, 0.0f);
glTexCoord2f(0, 1);
glVertex3f(10.0f, 3.0f, 0.0f);
glTexCoord2f(1, 1);
glVertex3f(10.0f, 3.0f, 10.0f);
glTexCoord2f(1, 0);
glVertex3f(0.0f, 3.0f, 10.0f);
glEnd();
}
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(x, 1.5f, z, x + vX, 1.5f, z + vZ, 0.0f, 1.5f, 0.0f);
initLight();
renderWalls();
glutSwapBuffers();
}
void changeWindowSize(int width, int height) {
if (height == 0) {
height = 1;
}
float ratio = 1.0 * width / height;
windowWidth = width;
windowHeight = height;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, width, height);
gluPerspective(45.0f, ratio, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowPosition(0, 0);
glutInitWindowSize(windowWidth, windowHeight);
glutCreateWindow("Kitchen");
init();
glutDisplayFunc(display);
glutReshapeFunc(changeWindowSize);
glutIdleFunc(display);
glutSpecialFunc(processSpecialKeys);
glutMainLoop();
return 0;
}
Your light is stationary - but to the camera.
Fixed-function OpenGL does all the lighting calculations in eye space. At the moment you specify the GL_POSITION of a light, it is transformed according to the current modelView matrix at the time of the call, to get the eye space position. Since modelView is set to identity, it will always set the light to the given eye-space location - no matter where you later place the camera.
To fix this, just move initLight() after the gluLookAt.
However. You should not be doing this at all. You are using deprecated OpenGL features which you shouldn't use since a decade now. In modern GL, that functionality is completely removed. So if you are learning OpenGL in 2016, do yourself a favour and forget about that old cruft, and just learn shaders directly.
I am asked to make a simple carousel that rotates by right and left click of mouse. For the sticks I used GL_LINES and the problem I am having is that there is no way to define normal vector or something similar as I did with GL_POLYGON to make the lighting be correct. I searched the web and I didn't find any source explaining the lighting for the GL_LINES (some people told me the lighting is automatic and I don't need to specify anything for GL_LINES), that is why I asked the questions.
Here is the screenshot of the front which show everything is fine from front:
Here is the screenshot of the back that shows the problems in lighting. In particular, the light source is in the back but still those sticks are bright.
Here is the another screenshot of the back that show the problems in lighting as well.
These are the two functions that specify horizontal and vertical sticks:
void DrawHorizontalStick(){
glLineWidth(15);
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_LINES);
glVertex3f(0.0, 7.0, 0.0);
glVertex3f(4.0 * cos(radian__IN_RANGE), 7.0 + 4.0 * sin(radian__IN_RANGE), 0.0);
glEnd();
}
void DrawVerticalStick(){
glLineWidth(5);
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_LINES);
glVertex3f(4.0 * cos(radian__IN_RANGE), 7.0 + 4.0 * sin(radian__IN_RANGE), 0.0);
glVertex3f(4.0 * cos(radian__IN_RANGE), 7.0 + 4.0 * sin(radian__IN_RANGE) - 1, 0.0);
glEnd();
}
Here is the complete source code:
#include <GL/glut.h>
#include <stdlib.h>
#include <Windows.h>
#include <math.h>
#include <stdio.h>
#define PI 3.14159265
#define numberOfRotationTypes 3
static GLfloat lpos[] = { 0.0, 6.0, 8.0, 1.0 };
static GLfloat black[] = { 0.0, 0.0, 0.0, 1.0 };
static GLfloat white[] = { 1.0, 1.0, 1.0, 1.0 };
static GLfloat red[] = { 1.0, 0.0, 0.0, 1.0 };
static GLfloat green[] = { 0.0, 1.0, 0.0, 1.0 };
static GLfloat blue[] = { 0.0, 0.0, 1.0, 1.0 };
static GLfloat yellow[] = { 1.0, 1.0, 0.0, 1.0 };
static GLfloat magenta[] = { 1.0, 0.0, 1.0, 1.0 };
static GLfloat cyan[] = { 0.0, 1.0, 1.0, 1.0 };
static GLfloat lightgreen[] = { 0.5, 1.0, 0.5, 1.0 };
static float alpha = 0.0;
static float beta = PI / 6.0;
static float zoom = 25.0;
static bool lightSource = true;
float numberOfTriangles = 1;
static GLdouble cpos[3];
static double fenceHeight = -0.5;
static int angle = 0;
static int angle__IN_RANGE = 0.0;
static double radian__IN_RANGE = 0.0;
static int arrayOfAnglesInRange[181];
static int id = 0;
static int speed = 0;
static int signal = 1;
static GLint window[2];
static int rotationType = 0;
void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
/* since back "face" appears in wireframe mode */
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
}
void writemessage()
{
}
void processAngle(){
angle__IN_RANGE = arrayOfAnglesInRange[abs(angle) % 181];
}
void setRadian_IN_RANGE(){
radian__IN_RANGE = ((float)angle__IN_RANGE / 180) * PI;
}
void fillArray(){
int j = -45;
for (int i = 0; i < 181; i++)
{
if (i < 90)
arrayOfAnglesInRange[i] = j++;
else
arrayOfAnglesInRange[i] = j--;
}
//for (int i = 0; i < 182; i++)
//{
// printf("%d\n", arrayOfAnglesInRange[i]);
//}
}
void keepTrackOfID(){
int tempAngle = angle;
if (id % 4 == 0)
angle += 0;
else if (id % 4 == 1)
angle += 30;
else if (id % 4 == 2)
angle += 60;
else if (id % 4 == 3)
angle += 90;
processAngle();
setRadian_IN_RANGE();
angle = tempAngle;
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (GLfloat)w / (GLfloat)h, 0.01, 50.0);
glMatrixMode(GL_MODELVIEW);
}
void DrawSticksArroundYard(){
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, black);
GLUquadricObj *quadObj;
// Right-Line
glPushMatrix();
glTranslatef(6.8, 1.0 + fenceHeight, -7.0);
quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.1, 0.1, 14.0, 10, 10);
glPopMatrix();
// Left-Line
glPushMatrix();
glTranslatef(-6.8, 1.0 + fenceHeight, -7.0);
quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.1, 0.1, 14.0, 10, 10);
glPopMatrix();
// Back-Line
glPushMatrix();
glTranslatef(-6.8, 1.0 + fenceHeight, -7.0);
glRotatef(90, 0, 1, 0);
quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.1, 0.1, 13.7, 10, 10);
glRotatef(-90, 0, 1, 0);
glPopMatrix();
// Front-Line
glPushMatrix();
glTranslatef(6.8, 1.0 + fenceHeight, 7.0);
glRotatef(-90, 0, 1, 0);
quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.1, 0.1, 13.7, 10, 10);
glRotatef(90, 0, 1, 0);
glPopMatrix();
// Pin-Front-Right
glPushMatrix();
glTranslatef(6.8, 0, 7.0);
glRotatef(-90, 1, 0, 0);
quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.2, 0.1, 1.3 + fenceHeight, 10, 10);
glRotatef(90, 1, 0, 0);
glPopMatrix();
// Pin-Front-Left
glPushMatrix();
glTranslatef(-6.8, 0, 7.0);
glRotatef(-90, 1, 0, 0);
quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.2, 0.1, 1.3 + fenceHeight, 10, 10);
glRotatef(90, 1, 0, 0);
glPopMatrix();
// Pin-Back-Left
glPushMatrix();
glTranslatef(-6.8, 0, -7.0);
glRotatef(-90, 1, 0, 0);
quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.2, 0.1, 1.3 + fenceHeight, 10, 10);
glRotatef(90, 1, 0, 0);
glPopMatrix();
// Pin-Back-Right
glPushMatrix();
glTranslatef(6.8, 0, -7.0);
glRotatef(-90, 1, 0, 0);
quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.2, 0.1, 1.3 + fenceHeight, 10, 10);
glRotatef(90, 1, 0, 0);
glPopMatrix();
// Pin-Back-Center
glPushMatrix();
glTranslatef(0, 0, -7.0);
glRotatef(-90, 1, 0, 0);
quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.2, 0.1, 1.3 + fenceHeight, 10, 10);
glRotatef(90, 1, 0, 0);
glPopMatrix();
// Pin-Front-Center
glPushMatrix();
glTranslatef(0, 0, 7.0);
glRotatef(-90, 1, 0, 0);
quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.2, 0.1, 1.3 + fenceHeight, 10, 10);
glRotatef(90, 1, 0, 0);
glPopMatrix();
// Pin-Right-Center
glPushMatrix();
glTranslatef(6.8, 0, 0);
glRotatef(-90, 1, 0, 0);
quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.2, 0.1, 1.3 + fenceHeight, 10, 10);
glRotatef(90, 1, 0, 0);
glPopMatrix();
// Pin-Left-Center
glPushMatrix();
glTranslatef(-6.8, 0, 0);
glRotatef(-90, 1, 0, 0);
quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.2, 0.1, 1.3 + fenceHeight, 10, 10);
glRotatef(90, 1, 0, 0);
glPopMatrix();
}
void DrawYardFloor(){
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, lightgreen);
glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, lightgreen);
glBegin(GL_POLYGON);
glNormal3f(0, 1, 0);
glVertex3f(-7.3, -0.005, -7.3);
glVertex3f(-7.3, -0.005, 7.3);
glVertex3f(7.3, -0.005, 7.3);
glVertex3f(7.3, -0.005, -7.3);
glEnd();
}
void DrawCenterPin(){
glRotatef(-90, 1, 0, 0);
GLUquadricObj *quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.2, 0.2, 7, 10, 10);
glRotatef(90, 1, 0, 0);
}
void DrawBase(){
glRotatef(-90, 1, 0, 0);
GLUquadricObj *quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.5, 0.1, 2, 10, 10);
glRotatef(90, 1, 0, 0);
}
void DrawTop(){
glPushMatrix();
glTranslatef(0, 7, 0);
glRotatef(-90, 1, 0, 0);
GLUquadricObj *quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.2, 0.0, 0.5, 10, 10);
glRotatef(90, 1, 0, 0);
glPopMatrix();
}
void DrawHorizontalStick(){
glLineWidth(15);
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_LINES);
glVertex3f(0.0, 7.0, 0.0);
glVertex3f(4.0 * cos(radian__IN_RANGE), 7.0 + 4.0 * sin(radian__IN_RANGE), 0.0);
glEnd();
}
void DrawVerticalStick(){
glLineWidth(5);
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_LINES);
glVertex3f(4.0 * cos(radian__IN_RANGE), 7.0 + 4.0 * sin(radian__IN_RANGE), 0.0);
glVertex3f(4.0 * cos(radian__IN_RANGE), 7.0 + 4.0 * sin(radian__IN_RANGE) - 1, 0.0);
glEnd();
}
void DrawCabin(){
// Back
glNormal3f(0.0, 0.0, -1.0);
glBegin(GL_POLYGON);
glVertex3f(0, 0, -1);
glVertex3f(0, 1, -1);
glVertex3f(2, 1, -1);
glVertex3f(2, 0, -1);
glEnd();
glNormal3f(0.0, 0.0, -1.0);
glBegin(GL_POLYGON);
glVertex3f(0, 1.7, -1);
glVertex3f(0, 2, -1);
glVertex3f(2, 2, -1);
glVertex3f(2, 1.7, -1);
glEnd();
glNormal3f(0.0, 0.0, -1.0);
glBegin(GL_POLYGON);
glVertex3f(0, 1, -1);
glVertex3f(0, 1.7, -1);
glVertex3f(0.2, 1.7, -1);
glVertex3f(0.2, 1, -1);
glEnd();
glNormal3f(0.0, 0.0, -1.0);
glBegin(GL_POLYGON);
glVertex3f(1.8, 1, -1);
glVertex3f(1.8, 1.7, -1);
glVertex3f(2, 1.7, -1);
glVertex3f(2, 1, -1);
glEnd();
// Front
glNormal3f(0.0, 0.0, 1.0);
glBegin(GL_POLYGON);
glVertex3f(2, 0, 1);
glVertex3f(2, 1, 1);
glVertex3f(0, 1, 1);
glVertex3f(0, 0, 1);
glEnd();
glNormal3f(0.0, 0.0, 1.0);
glBegin(GL_POLYGON);
glVertex3f(2, 1.7, 1);
glVertex3f(2, 2, 1);
glVertex3f(0, 2, 1);
glVertex3f(0, 1.7, 1);
glEnd();
glNormal3f(0.0, 0.0, 1.0);
glBegin(GL_POLYGON);
glVertex3f(0.2, 1, 1);
glVertex3f(0.2, 1.7, 1);
glVertex3f(0, 1.7, 1);
glVertex3f(0, 1, 1);
glEnd();
glNormal3f(0.0, 0.0, 1.0);
glBegin(GL_POLYGON);
glVertex3f(2, 1, 1);
glVertex3f(2, 1.7, 1);
glVertex3f(1.8, 1.7, 1);
glVertex3f(1.8, 1, 1);
glEnd();
// Floor
glNormal3f(0.0, -1.0, 0.0);
glBegin(GL_POLYGON);
glVertex3f(2, 0, -1);
glVertex3f(2, 0, 1);
glVertex3f(0, 0, 1);
glVertex3f(0, 0, -1);
glEnd();
// Top
glNormal3f(0.0, 1.0, 0.0);
glBegin(GL_POLYGON);
glVertex3f(2, 2, 1);
glVertex3f(2, 2, -1);
glVertex3f(0, 2, -1);
glVertex3f(0, 2, 1);
glEnd();
// Right
glNormal3f(1.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex3f(2, 0, -1);
glVertex3f(2, 1, -1);
glVertex3f(2, 1, 1);
glVertex3f(2, 0, 1);
glEnd();
glNormal3f(1.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex3f(2, 1.7, -1);
glVertex3f(2, 2, -1);
glVertex3f(2, 2, 1);
glVertex3f(2, 1.7, 1);
glEnd();
glNormal3f(1.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex3f(2, 1, -1);
glVertex3f(2, 1.7, -1);
glVertex3f(2, 1.7, -0.8);
glVertex3f(2, 1, -0.8);
glEnd();
glNormal3f(1.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex3f(2, 1, 0.8);
glVertex3f(2, 1.7, 0.8);
glVertex3f(2, 1.7, 1);
glVertex3f(2, 1, 1);
glEnd();
// Left
glNormal3f(-1.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex3f(0, 0, -1);
glVertex3f(0, 0, 1);
glVertex3f(0, 1, 1);
glVertex3f(0, 1, -1);
glEnd();
glNormal3f(-1.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex3f(0, 1.7, -1);
glVertex3f(0, 1.7, 1);
glVertex3f(0, 2, 1);
glVertex3f(0, 2, -1);
glEnd();
glNormal3f(-1.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex3f(0, 1, -1);
glVertex3f(0, 1, -0.8);
glVertex3f(0, 1.7, -0.8);
glVertex3f(0, 1.7, -1);
glEnd();
glNormal3f(-1.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex3f(0, 1, 0.8);
glVertex3f(0, 1, 1);
glVertex3f(0, 1.7, 1);
glVertex3f(0, 1.7, 0.8);
glEnd();
}
void darwCabin__FINAL(){
glPushMatrix();
glTranslatef(4.0 * cos(radian__IN_RANGE), 7.0 + 4.0 * sin(radian__IN_RANGE) - 3, 0.0);
glRotatef(angle, 0, 1, 0);
glPushMatrix();
glTranslatef(-1, 0, 0);
DrawCabin();
glPopMatrix();
glRotatef(-angle, 0, 1, 0);
glPopMatrix();
}
void display(void)
{
for (int i = 0; i < 2; i++) {
glutSetWindow(window[i]); // set the current window to window[i]
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 64);
if (i == 1) {
gluLookAt(0.7, 0, 0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glRotatef(-angle, 0, 1, 0);
glTranslatef(-4.0 * cos(radian__IN_RANGE), -5.4 + 4.0 * sin(radian__IN_RANGE), 0);
glRotatef(-angle, 0, 1, 0);
}
else if (i == 0) {
cpos[0] = zoom * cos(beta) * sin(alpha);
cpos[1] = zoom * sin(beta);
cpos[2] = zoom * cos(beta) * cos(alpha);
gluLookAt(cpos[0], cpos[1], cpos[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}
if (lightSource == true){
glLightfv(GL_LIGHT0, GL_POSITION, lpos);
glMaterialfv(GL_FRONT, GL_EMISSION, white);
glPushMatrix();
glTranslatef(lpos[0], lpos[1], lpos[2]);
glutSolidSphere(0.1, 10, 8);
glPopMatrix();
glMaterialfv(GL_FRONT, GL_EMISSION, black);
}
DrawYardFloor();
DrawSticksArroundYard();
DrawCenterPin();
DrawBase();
DrawTop();
glRotatef(angle, 0, 1, 0);
for (int j = 0; j < 4; j++){
glMaterialfv(GL_FRONT, GL_SPECULAR, white);
glMaterialf(GL_FRONT, GL_SHININESS, 64);
if (id % 4 == 0)
{
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, black);
}
else if (id % 4 == 1)
{
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, black);
}
else if (id % 4 == 2)
{
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, white);
glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, black);
}
else if (id % 4 == 3)
{
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cyan);
glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, black);
}
glPushMatrix();
glRotatef(j * 360 / 4, 0, 1, 0);
keepTrackOfID();
DrawHorizontalStick();
DrawVerticalStick();
darwCabin__FINAL();
id++;
glPopMatrix();
}
glRotatef(-angle, 0, 1, 0);
glFlush();
glutSwapBuffers();
}
}
void keyboard(unsigned char key, int x, int y)
{
static int polygonmode[2];
switch (key) {
case 27:
exit(0);
break;
case 'x':
if (lightSource == true)
lpos[0] = lpos[0] + 0.2;
glutPostRedisplay();
break;
case 'X':
if (lightSource == true)
lpos[0] = lpos[0] - 0.2;
glutPostRedisplay();
break;
case 'y':
if (lightSource == true)
lpos[1] = lpos[1] + 0.2;
glutPostRedisplay();
break;
case 'Y':
if (lightSource == true)
lpos[1] = lpos[1] - 0.2;
glutPostRedisplay();
break;
case 'z':
if (lightSource == true)
lpos[2] = lpos[2] + 0.2;
glutPostRedisplay();
break;
case 'Z':
if (lightSource == true)
lpos[2] = lpos[2] - 0.2;
glutPostRedisplay();
break;
case '+':
if (zoom != 1.5)zoom = zoom - 0.5;
glutPostRedisplay();
break;
case '-':
if (zoom != 30)zoom = zoom + 0.5;
glutPostRedisplay();
break;
case '0':
if (lightSource == true){
glDisable(GL_LIGHT0);
lightSource = false;
}
else{
glEnable(GL_LIGHT0);
lightSource = true;
}
glutPostRedisplay();
break;
case 'e':
if (fenceHeight < 2)
fenceHeight += 0.5;
glutPostRedisplay();
break;
case 'd':
if (fenceHeight > -0.5)
fenceHeight -= 0.5;
glutPostRedisplay();
break;
case 'w':
glGetIntegerv(GL_POLYGON_MODE, polygonmode);
if (polygonmode[0] == GL_FILL)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
else glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glutPostRedisplay();
break;
case 'n':
angle++;
processAngle();
setRadian_IN_RANGE();
glutPostRedisplay();
break;
case 'm':
angle--;
processAngle();
setRadian_IN_RANGE();
glutPostRedisplay();
break;
default:
break;
}
}
void mouse(int button, int state, int x, int y)
{
switch (button) {
case GLUT_LEFT_BUTTON:
signal = 0;
if (speed <= 15)
speed++;
break;
case GLUT_MIDDLE_BUTTON:
case GLUT_RIGHT_BUTTON:
signal = 1;
if (speed >= 1)
speed--;
break;
default:
break;
}
}
void specialkey(GLint key, int x, int y)
{
switch (key) {
case GLUT_KEY_RIGHT:
alpha = alpha + PI / 180;
if (alpha > 2 * PI) alpha = alpha - 2 * PI;
glutPostRedisplay();
break;
case GLUT_KEY_LEFT:
alpha = alpha - PI / 180;
if (alpha < 0) alpha = alpha + 2 * PI;
glutPostRedisplay();
break;
case GLUT_KEY_UP:
if (beta < 0.45*PI) beta = beta + PI / 180;
glutPostRedisplay();
break;
case GLUT_KEY_DOWN:
if (beta > -0.05*PI) beta = beta - PI / 180;
glutPostRedisplay();
break;
default:
break;
}
}
void anim(){
if (signal == 0){
angle++;
glutPostRedisplay();
Sleep((int)(50 / speed));
}
else if (signal == 1){
if (speed != 0){
angle++;
glutPostRedisplay();
Sleep((int)(50 / speed));
}
}
}
int main(int argc, char** argv)
{
writemessage();
fillArray();
processAngle();
setRadian_IN_RANGE();
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(500, 500);
glutInitWindowPosition(0, 0);
window[0] = glutCreateWindow("First");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutIdleFunc(anim);
glutMouseFunc(mouse);
glutKeyboardFunc(keyboard);
glutSpecialFunc(specialkey);
glutInitWindowSize(500, 500);
glutInitWindowPosition(600, 10);
window[1] = glutCreateWindow("Second");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutIdleFunc(anim);
glutMouseFunc(mouse);
glutKeyboardFunc(keyboard);
glutSpecialFunc(specialkey);
glutMainLoop();
return 0;
}
Lighting for lines works just the same as for other objects. The color/brightness is calculated based on normals, and the lighting and material parameters.
If you're using immediate mode draw commands, you can specify normals with glNormal3f() before the glVertex3f() calls you make for the lines. If you don't specify the normal this way, whatever is the current normal based on earlier calls to glNormal*() will be used as the normal for your lines.
Now, the obvious follow-up question is: What is the normal of a line?
The simple answer is: Whatever you want it to be, to give you the desired result.
For a typical example, if you draw an analytic surface in wireframe mode, the normals of this analytic surface can be used as the normals. This will give a wireframe model where the shading/brightness corresponds to the shape of the surface.
In your example, the most obvious and arguably best approach is to not draw lines, but represent the geometry with polygons, using some kind of thin beam/cylinder. But as an exercise, we can figure out how this would work with lines anyway.
In this case, you want the line to represent an infinitely thin cylinder. An actual cylinder would have normals pointing outwards for each vertex. But since the line has only two vertices, you have to pick one single direction among the infinite set of vectors that point outwards from the end point, and are orthogonal to the line.
I believe you would get reasonable results by choosing the normal vector that is closest to pointing towards the viewpoint. This would result in the brightness you would get from looking at the center line of the cylinder if you actually used a cylinder. These normals could be calculated by:
Apply your model transformation to the original end points of the line, v1 and v2. Let's called the transformed end points v1t and v2t.
Calculate the direction vector of the transformed line as:
v1d = v2t - v1t
v1d.normalize()
Calculate the vector from line end point to view point vp, and orthogonalize it relative to the direction of the line, and normalize it:
v1n = vp - v1
v1n -= dot(v1d * v1n) * v1d
v1n.normalize()
Apply the inverse model transform to v1n to get the normal in the original object space.
Perform equivalent calculation for second vertex.
You could achieve the same result by doing the inverse transformation on the view point, and then calculating the normals directly in object space.
I'm trying to combine lighting with 3D graphics.There's sphere that is on depth 100, and it has 100 as radius.I use translatef to make it be far from the eye position.
But nothing is displayed on the screen:
#import <OpenGL/OpenGL.h>
#import <GLUT/GLUT.h>
GLfloat width=500, height=500;
GLfloat angle=0.0;
void makeRound (GLfloat* angle)
{
if(*angle>360.0)
{
*angle-=360.0;
}
else if(*angle<0.0)
{
*angle+=360.0;
}
}
void init(void)
{
GLfloat mat_specular[] = { 1.0, 0.0, 0.0, 0.0 };
GLfloat mat_diffuse[] = { 0.9, 0.0, 0.0, 0.0 };
GLfloat mat_shininess[] = { 50.0 };
GLfloat light_position[] = { 5.0, 5.0, 5.0, 1.0 };
GLfloat white_light[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat lmodel_ambient[] = { 0.1, 0.5, 0.1, 1.0 };
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, 0, 0, 0, 100, 0, 1, 0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, 1, 1, 1000);
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel (GL_SMOOTH);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);
glLightfv(GL_LIGHT0, GL_SPECULAR,white_light);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,lmodel_ambient);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
}
void display(void)
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glRotatef(angle, 0, 1, 0);
glTranslatef(0, 0, 100);
glutSolidSphere (100.0, 80, 64);
glPopMatrix();
glutSwapBuffers();
}
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case '+':
angle+=5.0;
makeRound(&angle);
glutPostRedisplay();
break;
case '-':
angle-=5.0;
makeRound(&angle);
glutPostRedisplay();
break;
default:
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize (width, height);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
init ();
glutMainLoop();
return 0;
}
UPDATE
This is what I see with :
glTranslatef(0,0,-200);
As a result of your translate you are actually positioned on the edge of the sphere. That means the polys actually go though "you". You won't see anything as a result of your near clip plane and thanks to back-face culling you can't see the tris on the other side of the sphere.
Set either:
glCullFace( GL_FRONT );
Or set the transform to push the sphere further away:
glTranslatef(0, 0, -200);