Skip to content

Instantly share code, notes, and snippets.

@davidwparker
Created October 10, 2011 19:57
Show Gist options
  • Select an option

  • Save davidwparker/1276355 to your computer and use it in GitHub Desktop.

Select an option

Save davidwparker/1276355 to your computer and use it in GitHub Desktop.
OpenGL Screencast 12: Lighting and material part 1
/* Poor man's approximation of PI */
#define PI 3.1415926535898
/* Macro for sin & cos in degrees */
#define Cos(th) cos(PI/180*(th))
#define Sin(th) sin(PI/180*(th))
/* Common #defines */
/* Defaults for window sizing */
#define DEF_WINDOW_HEIGHT 450
#define DEF_WINDOW_WIDTH 500
/* Projection */
#define DEF_ASP 1
#define DEF_DIM 10
#define DEF_TH 340
#define DEF_PH 30
#define DEF_FOV 55
#define DEF_ECX 2
#define DEF_ECY 0
#define DEF_ECZ 4
/* Draw defaults */
#define DEF_AXES 1
#define DEF_PARMS 1
/* Shape degrees */
#define DEF_D 5
/* Lighting */
#define DEF_LIGHT 1
#define DEF_DISTANCE 10
#define DEF_AMBIENT 35
#define DEF_DIFFUSE 100
#define DEF_EMISSION 0
#define DEF_SPECULAR 0
#define DEF_SHININESS 0
#define DEF_L_Y 0
#define DEF_L_PH 90
#include "screencasts.h"
/*
* displayInit
* -------
* Initializes display
*/
void displayInit(void)
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glLoadIdentity();
}
/*
* displayEye()
* ------
* Set the eye position
*/
void displayEye(void)
{
double Ex = -2*dim*Sin(th)*Cos(ph);
double Ey = +2*dim *Sin(ph);
double Ez = +2*dim*Cos(th)*Cos(ph);
/* camera/eye position, aim of camera lens, up-vector */
gluLookAt(Ex+ecX,Ey,Ez+ecZ , ecX,ecY,ecZ , 0,Cos(ph),0);
}
/*
* displayReshape()
* ------
* GLUT calls this routine when the window is resized
*/
void displayReshape(int width,int height)
{
asp = (height>0) ? (double)width/height : 1;
glViewport(0,0, width,height);
displayProject(fov,asp,dim);
}
/*
* displayProject()
* ------
* Sets the projection
*/
void displayProject(double fov, double asp, double dim)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(fov,asp,dim/16,16*dim);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
/*
* display()
* ------
* Display the scene
*/
void display(void)
{
/* setup functions */
displayInit();
displayEye();
/* Draw Scene */
drawScene();
glFlush();
glutSwapBuffers();
errCheck("display sanity check");
}
/*
* redisplayAll
* ------
* This is called whenever we need to draw the display
*/
void redisplayAll(void)
{
displayReshape(windowWidth, windowHeight);
glutPostRedisplay();
}
void displayInit(void);
void displayEye(void);
void displayReshape(int width,int height);
void displayProject(double fov,double asp,double dim);
void display(void);
void redisplayAll(void);
#include "screencasts.h"
/* Global descriptions on screencasts.h */
/* ID-used to keep screencasts separate */
int screencastID = 0;
/* WINDOW */
char *windowName="OpenGL screenscasts XX: Placeholder";
int windowHeight=DEF_WINDOW_HEIGHT;
int windowWidth=DEF_WINDOW_WIDTH;
/* TOGGLE DRAW DISPLAYS */
int toggleAxes=DEF_AXES;
int toggleParms=DEF_PARMS;
/* PROJECTION */
double asp=DEF_ASP;
double dim=DEF_DIM;
int th=DEF_TH;
int ph=DEF_PH;
int fov=DEF_FOV;
double ecX=DEF_ECX;
double ecY=DEF_ECY;
double ecZ=DEF_ECZ;
/* LIGHTING */
int toggleLight=DEF_LIGHT;
int distance=DEF_DISTANCE;
int ambient=DEF_AMBIENT;
int diffuse=DEF_DIFFUSE;
int emission=DEF_EMISSION;
int specular=DEF_SPECULAR;
int shininess=DEF_SHININESS;
float shinyvec[1]={1};
float lightY=DEF_L_Y;
float white[]={1,1,1,1};
int lightPh=DEF_L_PH;
#include "screencasts.h"
void initializeGlobals()
{
/* WINDOW */
windowHeight=DEF_WINDOW_HEIGHT;
windowWidth=DEF_WINDOW_WIDTH;
/* TOGGLE */
toggleAxes=DEF_AXES;
toggleParms=DEF_PARMS;
/* PROJECTION */
dim=DEF_DIM;
th=DEF_TH;
ph=DEF_PH;
fov=DEF_FOV;
asp=DEF_ASP;
ecX=DEF_ECX;
ecY=DEF_ECY;
ecZ=DEF_ECZ;
/* LIGHTING */
toggleLight=DEF_LIGHT;
distance=DEF_DISTANCE;
ambient=DEF_AMBIENT;
diffuse=DEF_DIFFUSE;
emission=DEF_EMISSION;
specular=DEF_SPECULAR;
shininess=DEF_SHININESS;
lightY=DEF_L_Y;
lightPh=DEF_L_PH;
}
#include "screencasts.h"
/*
* windowKey()
* ------
* GLUT calls this routine when a non-special key is pressed
*/
void windowKey(unsigned char key,int x,int y)
{
/* Exit on ESC */
if (key == 27) exit(0);
else if (key == 'x' || key == 'X') toggleAxes = 1-toggleAxes;
else if (key == 'v' || key == 'V') toggleParms = 1-toggleParms;
/* Change field of view angle */
else if (key == '-' && key>1) fov--;
else if (key == '+' && key<179) fov++;
/* Change dimensions */
else if (key == 'I') dim += 0.2;
else if (key == 'i' && dim>1) dim -= 0.2;
/* BEGIN LIGHTING FUNCTIONALITY */
/* Toggle lighting */
else if (key == 'l' || key == 'L') toggleLight = 1-toggleLight;
/* Move light (rotation) */
else if (key == '<') lightPh -= 5;
else if (key == '>') lightPh += 5;
/* Light elevation */
else if (key == '[') lightY -= 0.5;
else if (key == ']') lightY += 0.5;
/* Light distance */
else if (key == '{') distance -= 1;
else if (key == '}') distance += 1;
/* Ambient level */
else if (key == 'a' && ambient>0) ambient -= 5;
else if (key == 'A' && ambient<100) ambient += 5;
/* Diffuse level */
else if (key == 'd' && diffuse>0) diffuse -= 5;
else if (key == 'D' && diffuse<100) diffuse += 5;
/* Specular level */
else if (key == 's' && specular>0) specular -= 5;
else if (key == 'S' && specular<100) specular += 5;
/* Emission level */
else if (key == 'e' && emission>0) emission -= 5;
else if (key == 'E' && emission<100) emission += 5;
/* Shininess level */
else if (key == 'n' && shininess>-1) shininess -= 1;
else if (key == 'N' && shininess<7) shininess += 1;
/* Translate shininess power to value (-1 => 0) */
shinyvec[0] = shininess<0 ? 0 : pow(2.0,shininess);
redisplayAll();
}
/*
* windowMenu
* ------
* Window menu is the same as the keyboard clicks
*/
void windowMenu(int value)
{
windowKey((unsigned char)value, 0, 0);
}
/*
* windowSpecial()
* ------
* GLUT calls this routine when an arrow key is pressed
*/
void windowSpecial(int key,int x,int y)
{
int modifiers = glutGetModifiers();
/* If holding shift, then rotate/elevate */
if (modifiers == GLUT_ACTIVE_SHIFT) {
/* Right/Left - rotate */
if (key == GLUT_KEY_RIGHT) th += 5;
else if (key == GLUT_KEY_LEFT) th -= 5;
/* Up/Down - elevation */
else if (key == GLUT_KEY_UP) ph += 5;
else if (key == GLUT_KEY_DOWN) ph -= 5;
}
/* Otherwise, just shift the screen */
else {
/* Shift */
if (key == GLUT_KEY_RIGHT) ecX -= .5;
else if (key == GLUT_KEY_LEFT) ecX += .5;
else if (key == GLUT_KEY_UP) ecZ += .5;
else if (key == GLUT_KEY_DOWN) ecZ -= .5;
}
/* Keep angles to +/-360 degrees */
th %= 360;
ph %= 360;
redisplayAll();
}
# Target to build
#TARGET = 011 012
TARGET = 012
#EXECS = ./executables/011 ./executables/012
EXECS = ./executables/012
# Libraries - LINUX
#LIBS=-lglut -lGLU
# Libraries - OSX
LIBS=-framework OpenGL -framework GLUT
all: $(TARGET)
# Generic compile rules
.c.o:
gcc -c -O -Wall $<
# Generic compile and link
%: %.c screencasts.a
gcc -Wall -O3 -o ./executables/$@ $^ $(LIBS)
clean:
rm -f $(EXECS) *.o *.a
# without .h => globals.o
screencasts.a:globals.o print.o error.o shapes.o models.o interaction.o initialization.o draw.o display.o
ar -rcs screencasts.a $^
#ifndef SCREENCASTS
#define SCREENCASTS
/* standard headers */
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <math.h>
#include <time.h>
/* OpenGL and friends */
#ifdef USEGLEW
#include <GL/glew.h>
#endif
#define GL_GLEXT_PROTOTYPES
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
/* includes */
#include "common.h" /* common is just defines */
#include "print.h" /* printing functions */
#include "error.h" /* error convenience */
#include "shapes.h" /* basic shapes (cube, cone, etc) */
#include "models.h" /* complex objects */
#include "interaction.h" /* user interactions (keyboard, mouse, etc) */
#include "initialization.h" /* initialization */
#include "draw.h" /* draw -> draw whatever objects in the scene */
#include "display.h" /* display -> setup scene to draw */
/* GLOBALS (externs required here) */
/* Don't forget to initialize globals! */
extern int screencastID;
/* window info */
extern char *windowName;
extern int windowWidth;
extern int windowHeight;
/* toggle views */
extern int toggleAxes; /* toggle axes on and off */
extern int toggleParms; /* toggle parameters on and off */
/* view */
extern double asp;/* aspect ratio */
extern double dim;/* dimension of orthogonal box */
extern int th; /* azimuth of view angle */
extern int ph; /* elevation of view angle */
extern int fov; /* field of view for perspective */
extern double ecX; /* eye center position x */
extern double ecY; /* eye center position y */
extern double ecZ; /* eye center position z */
/* lighting */
extern int toggleLight; /* toggle light */
extern int distance; /* light distance */
extern int ambient; /* ambient intensity % */
extern int diffuse; /* diffuse intensity % */
extern int emission; /* emission intensity % */
extern int specular; /* specular intensity % */
extern int shininess; /* shininess (power of two) */
extern float shinyvec[1]; /* shininess (value) */
extern float lightY; /* elevation of light */
extern float white[]; /* the color white */
extern int lightPh; /* light movement */
#endif
#include "screencasts.h"
/*
* cone
* ------
* Draws a cone
* at (x,y,z)
* with radius r and height h
* with 360/deg sides
*/
void cone(double x,double y,double z,
double r,double h,int deg)
{
int k;
glPushMatrix();
/* Transform */
glTranslated(x,y,z);
glScaled(r,h,r);
glRotated(-90,1,0,0);
/* sides */
glBegin(GL_TRIANGLES);
for (k=0;k<=360;k+=deg){
glColor3f(0.0,0.0,1.0);
glVertex3f(0,0,1);
glColor3f(0.0,1.0,1.0);
glVertex3f(Cos(k),Sin(k),0);
glColor3f(1.0,0.0,1.0);
glVertex3f(Cos(k+deg),Sin(k+deg),0);
}
glEnd();
/* bottom circle */
/* rotate back */
glRotated(90,1,0,0);
glBegin(GL_TRIANGLES);
glColor3f(1.0,1.0,0.0);
for (k=0;k<=360;k+=deg) {
glVertex3f(0,0,0);
glVertex3f(Cos(k),0,Sin(k));
glVertex3f(Cos(k+deg),0,Sin(k+deg));
}
glEnd();
glPopMatrix();
}
/*
* cube
* ------
* Draw a cube
* at (x,y,z)
* dimensions (dx,dy,dz)
* rotated th about the y axis
*/
void cube(double x,double y,double z,
double dx,double dy,double dz,
double th)
{
/* Cube vertices */
GLfloat vertA[3] = { 0.5, 0.5, 0.5};
GLfloat vertB[3] = {-0.5, 0.5, 0.5};
GLfloat vertC[3] = {-0.5,-0.5, 0.5};
GLfloat vertD[3] = { 0.5,-0.5, 0.5};
GLfloat vertE[3] = { 0.5, 0.5,-0.5};
GLfloat vertF[3] = {-0.5, 0.5,-0.5};
GLfloat vertG[3] = {-0.5,-0.5,-0.5};
GLfloat vertH[3] = { 0.5,-0.5,-0.5};
glPushMatrix();
/* Transform */
glTranslated(x,y,z);
glRotated(th,0,1,0);
glScaled(dx,dy,dz);
/* Cube */
glBegin(GL_QUADS);
/* front => ABCD yellow */
glNormal3f(0,0,1);
glColor3f(1.0,1.0,0.0);
glVertex3fv(vertA);
glVertex3fv(vertB);
glVertex3fv(vertC);
glVertex3fv(vertD);
/* back => FEHG red */
glNormal3f(0,0,-1);
glColor3f(1.0,0.0,0.0);
glVertex3fv(vertF);
glVertex3fv(vertE);
glVertex3fv(vertH);
glVertex3fv(vertG);
/* right => EADH green */
glNormal3f(1,0,0);
glColor3f(0.0,1.0,0.0);
glVertex3fv(vertE);
glVertex3fv(vertA);
glVertex3fv(vertD);
glVertex3fv(vertH);
/* left => BFGC blue */
glNormal3f(-1,0,0);
glColor3f(0.0,0.0,1.0);
glVertex3fv(vertB);
glVertex3fv(vertF);
glVertex3fv(vertG);
glVertex3fv(vertC);
/* top => EFBA turquoise */
glNormal3f(0,1,0);
glColor3f(0.0,1.0,1.0);
glVertex3fv(vertE);
glVertex3fv(vertF);
glVertex3fv(vertB);
glVertex3fv(vertA);
/* bottom => DCGH pink */
glNormal3f(0,-1,0);
glColor3f(1.0,0.0,1.0);
glVertex3fv(vertD);
glVertex3fv(vertC);
glVertex3fv(vertG);
glVertex3fv(vertH);
glEnd();
glPopMatrix();
}
/*
* sphere
* ------
* Draw a sphere
* at (x,y,z)
* radius (r)
* rotated rot around the y axis
*/
void sphere(double x,double y,double z,double r,double rot)
{
int th,ph;
float yellow[] = {1.0,1.0,0.0,1.0};
float emissions[] = {0.0,0.0,0.01*emission,1.0};
/*
Material shininess = specular exponent
Material specular = specular color of material
Material emission = simulates original lighting from an object
*/
glMaterialfv(GL_FRONT,GL_SHININESS,shinyvec);
glMaterialfv(GL_FRONT,GL_SPECULAR,yellow);
glMaterialfv(GL_FRONT,GL_EMISSION,emissions);
glPushMatrix();
/* Transform */
glTranslated(x,y,z);
glScaled(r,r,r);
glRotated(rot,0,1,0);
/* Bands of latitude */
for (ph=-90;ph<90;ph+=DEF_D) {
glBegin(GL_QUAD_STRIP);
for (th=0;th<=360;th+=2*DEF_D) {
vertex(th,ph);
vertex(th,ph+DEF_D);
}
glEnd();
}
glPopMatrix();
}
/*
* vertex
* ------
* Draw vertex in polar coordinates with normal
*/
void vertex(double th,double ph)
{
double x = Sin(th)*Cos(ph);
double y = Cos(th)*Cos(ph);
double z = Sin(ph);
/* For a sphere at the origin, the position
and normal vectors are the same */
glNormal3d(x,y,z);
glVertex3d(x,y,z);
}
void cone(double x,double y,double z,
double r,double h,int deg);
void cube(double x,double y,double z,
double dx,double dy,double dz,
double th);
void sphere(double x,double y,double z,
double r,double rot);
void vertex(double th,double ph);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment