132001f49Smrg 232001f49Smrg/* 332001f49Smrg * GLUT demonstration of texturing with specular highlights. 432001f49Smrg * 532001f49Smrg * When drawing a lit, textured surface one usually wants the specular 632001f49Smrg * highlight to override the texture colors. However, OpenGL applies 732001f49Smrg * texturing after lighting so the specular highlight is modulated by 832001f49Smrg * the texture. 932001f49Smrg * 1032001f49Smrg * The solution here shown here is a two-pass algorithm: 1132001f49Smrg * 1. Draw the textured surface without specular lighting. 1232001f49Smrg * 2. Enable blending to add the next pass: 1332001f49Smrg * 3. Redraw the surface with a matte white material and only the 1432001f49Smrg * specular components of light sources enabled. 1532001f49Smrg * 1632001f49Smrg * Brian Paul February 1997 1732001f49Smrg */ 1832001f49Smrg 1932001f49Smrg#include <stdio.h> 2032001f49Smrg#include <stdlib.h> 2132001f49Smrg#include <math.h> 2232001f49Smrg#include "glut_wrap.h" 2332001f49Smrg 2432001f49Smrg 2532001f49Smrgstatic GLUquadricObj *Quadric; 2632001f49Smrgstatic GLuint Sphere; 2732001f49Smrgstatic GLfloat LightPos[4] = {10.0, 10.0, 10.0, 1.0}; 2832001f49Smrgstatic GLfloat Delta = 20.0; 2932001f49Smrgstatic GLint Mode = 4; 3032001f49Smrg 3132001f49Smrg/*static GLfloat Blue[4] = {0.0, 0.0, 1.0, 1.0};*/ 3232001f49Smrg/*static GLfloat Gray[4] = {0.5, 0.5, 0.5, 1.0};*/ 3332001f49Smrgstatic GLfloat Black[4] = {0.0, 0.0, 0.0, 1.0}; 3432001f49Smrgstatic GLfloat White[4] = {1.0, 1.0, 1.0, 1.0}; 3532001f49Smrg 3632001f49Smrgstatic GLboolean smooth = 1; 3732001f49Smrg 3832001f49Smrgstatic void 3932001f49SmrgIdle(void) 4032001f49Smrg{ 4132001f49Smrg static double t0 = -1.; 4232001f49Smrg double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;; 4332001f49Smrg if (t0 < 0.0) 4432001f49Smrg t0 = t; 4532001f49Smrg dt = t - t0; 4632001f49Smrg t0 = t; 4732001f49Smrg LightPos[0] += Delta * dt; 4832001f49Smrg if (LightPos[0]>15.0 || LightPos[0]<-15.0) 4932001f49Smrg Delta = -Delta; 5032001f49Smrg 5132001f49Smrg glutPostRedisplay(); 5232001f49Smrg} 5332001f49Smrg 5432001f49Smrg 5532001f49Smrgstatic void Display( void ) 5632001f49Smrg{ 5732001f49Smrg glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 5832001f49Smrg 5932001f49Smrg glLightfv(GL_LIGHT0, GL_POSITION, LightPos); 6032001f49Smrg 6132001f49Smrg glPushMatrix(); 6232001f49Smrg glRotatef(90.0, 1.0, 0.0, 0.0); 6332001f49Smrg 6432001f49Smrg if (Mode==0) { 6532001f49Smrg /* Typical method: diffuse + specular + texture */ 6632001f49Smrg glEnable(GL_TEXTURE_2D); 6732001f49Smrg glLightfv(GL_LIGHT0, GL_DIFFUSE, White); /* enable diffuse */ 6832001f49Smrg glLightfv(GL_LIGHT0, GL_SPECULAR, White); /* enable specular */ 6932001f49Smrg#ifdef GL_VERSION_1_2 7032001f49Smrg glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); 7132001f49Smrg#endif 7232001f49Smrg glCallList(Sphere); 7332001f49Smrg } 7432001f49Smrg else if (Mode==1) { 7532001f49Smrg /* just specular highlight */ 7632001f49Smrg glDisable(GL_TEXTURE_2D); 7732001f49Smrg glLightfv(GL_LIGHT0, GL_DIFFUSE, Black); /* disable diffuse */ 7832001f49Smrg glLightfv(GL_LIGHT0, GL_SPECULAR, White); /* enable specular */ 7932001f49Smrg#ifdef GL_VERSION_1_2 8032001f49Smrg glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); 8132001f49Smrg#endif 8232001f49Smrg glCallList(Sphere); 8332001f49Smrg } 8432001f49Smrg else if (Mode==2) { 8532001f49Smrg /* diffuse textured */ 8632001f49Smrg glEnable(GL_TEXTURE_2D); 8732001f49Smrg glLightfv(GL_LIGHT0, GL_DIFFUSE, White); /* enable diffuse */ 8832001f49Smrg glLightfv(GL_LIGHT0, GL_SPECULAR, Black); /* disable specular */ 8932001f49Smrg#ifdef GL_VERSION_1_2 9032001f49Smrg glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); 9132001f49Smrg#endif 9232001f49Smrg glCallList(Sphere); 9332001f49Smrg } 9432001f49Smrg else if (Mode==3) { 9532001f49Smrg /* 2-pass: diffuse textured then add specular highlight*/ 9632001f49Smrg glEnable(GL_TEXTURE_2D); 9732001f49Smrg glLightfv(GL_LIGHT0, GL_DIFFUSE, White); /* enable diffuse */ 9832001f49Smrg glLightfv(GL_LIGHT0, GL_SPECULAR, Black); /* disable specular */ 9932001f49Smrg#ifdef GL_VERSION_1_2 10032001f49Smrg glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); 10132001f49Smrg#endif 10232001f49Smrg glCallList(Sphere); 10332001f49Smrg /* specular highlight */ 10432001f49Smrg glDepthFunc(GL_EQUAL); /* redraw same pixels */ 10532001f49Smrg glDisable(GL_TEXTURE_2D); 10632001f49Smrg glEnable(GL_BLEND); /* add */ 10732001f49Smrg glLightfv(GL_LIGHT0, GL_DIFFUSE, Black); /* disable diffuse */ 10832001f49Smrg glLightfv(GL_LIGHT0, GL_SPECULAR, White); /* enable specular */ 10932001f49Smrg glCallList(Sphere); 11032001f49Smrg glDepthFunc(GL_LESS); 11132001f49Smrg glDisable(GL_BLEND); 11232001f49Smrg } 11332001f49Smrg else if (Mode==4) { 11432001f49Smrg /* OpenGL 1.2's separate diffuse and specular color */ 11532001f49Smrg glEnable(GL_TEXTURE_2D); 11632001f49Smrg glLightfv(GL_LIGHT0, GL_DIFFUSE, White); /* enable diffuse */ 11732001f49Smrg glLightfv(GL_LIGHT0, GL_SPECULAR, White); /* enable specular */ 11832001f49Smrg#ifdef GL_VERSION_1_2 11932001f49Smrg glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); 12032001f49Smrg#endif 12132001f49Smrg glCallList(Sphere); 12232001f49Smrg } 12332001f49Smrg 12432001f49Smrg glPopMatrix(); 12532001f49Smrg 12632001f49Smrg glutSwapBuffers(); 12732001f49Smrg} 12832001f49Smrg 12932001f49Smrg 13032001f49Smrgstatic void Reshape( int width, int height ) 13132001f49Smrg{ 13232001f49Smrg glViewport( 0, 0, width, height ); 13332001f49Smrg glMatrixMode( GL_PROJECTION ); 13432001f49Smrg glLoadIdentity(); 13532001f49Smrg glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 25.0 ); 13632001f49Smrg glMatrixMode( GL_MODELVIEW ); 13732001f49Smrg glLoadIdentity(); 13832001f49Smrg glTranslatef( 0.0, 0.0, -12.0 ); 13932001f49Smrg} 14032001f49Smrg 14132001f49Smrg 14232001f49Smrgstatic void Key( unsigned char key, int x, int y ) 14332001f49Smrg{ 14432001f49Smrg (void) x; 14532001f49Smrg (void) y; 14632001f49Smrg switch (key) { 14732001f49Smrg case 27: 14832001f49Smrg exit(0); 14932001f49Smrg break; 15032001f49Smrg case 's': 15132001f49Smrg smooth = !smooth; 15232001f49Smrg if (smooth) 15332001f49Smrg glShadeModel(GL_SMOOTH); 15432001f49Smrg else 15532001f49Smrg glShadeModel(GL_FLAT); 15632001f49Smrg break; 15732001f49Smrg } 15832001f49Smrg glutPostRedisplay(); 15932001f49Smrg} 16032001f49Smrg 16132001f49Smrg 16232001f49Smrgstatic void SpecialKey( int key, int x, int y ) 16332001f49Smrg{ 16432001f49Smrg (void) x; 16532001f49Smrg (void) y; 16632001f49Smrg switch (key) { 16732001f49Smrg case GLUT_KEY_UP: 16832001f49Smrg break; 16932001f49Smrg case GLUT_KEY_DOWN: 17032001f49Smrg break; 17132001f49Smrg } 17232001f49Smrg glutPostRedisplay(); 17332001f49Smrg} 17432001f49Smrg 17532001f49Smrg 17632001f49Smrgstatic void Init( void ) 17732001f49Smrg{ 17832001f49Smrg int i, j; 17932001f49Smrg GLubyte texImage[64][64][3]; 18032001f49Smrg 18132001f49Smrg glEnable(GL_LIGHTING); 18232001f49Smrg glEnable(GL_LIGHT0); 18332001f49Smrg glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); 18432001f49Smrg glLightModelfv(GL_LIGHT_MODEL_AMBIENT, Black); 18532001f49Smrg 18632001f49Smrg glShadeModel(GL_SMOOTH); 18732001f49Smrg 18832001f49Smrg glMaterialfv(GL_FRONT, GL_DIFFUSE, White); 18932001f49Smrg glMaterialfv(GL_FRONT, GL_SPECULAR, White); 19032001f49Smrg glMaterialf(GL_FRONT, GL_SHININESS, 20.0); 19132001f49Smrg 19232001f49Smrg /* Actually, these are set again later */ 19332001f49Smrg glLightfv(GL_LIGHT0, GL_DIFFUSE, White); 19432001f49Smrg glLightfv(GL_LIGHT0, GL_SPECULAR, White); 19532001f49Smrg 19632001f49Smrg Quadric = gluNewQuadric(); 19732001f49Smrg gluQuadricTexture( Quadric, GL_TRUE ); 19832001f49Smrg 19932001f49Smrg Sphere= glGenLists(1); 20032001f49Smrg glNewList( Sphere, GL_COMPILE ); 20132001f49Smrg gluSphere( Quadric, 1.0, 24, 24 ); 20232001f49Smrg glEndList(); 20332001f49Smrg 20432001f49Smrg glEnable(GL_DEPTH_TEST); 20532001f49Smrg glEnable(GL_CULL_FACE); 20632001f49Smrg 20732001f49Smrg for (i=0;i<64;i++) { 20832001f49Smrg for (j=0;j<64;j++) { 20932001f49Smrg int k = ((i>>3)&1) ^ ((j>>3)&1); 21032001f49Smrg texImage[i][j][0] = 255*k; 21132001f49Smrg texImage[i][j][1] = 255*(1-k); 21232001f49Smrg texImage[i][j][2] = 0; 21332001f49Smrg } 21432001f49Smrg } 21532001f49Smrg 21632001f49Smrg glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 21732001f49Smrg glTexImage2D( GL_TEXTURE_2D, 21832001f49Smrg 0, 21932001f49Smrg 3, 22032001f49Smrg 64, 64, 22132001f49Smrg 0, 22232001f49Smrg GL_RGB, GL_UNSIGNED_BYTE, 22332001f49Smrg texImage ); 22432001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 22532001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 22632001f49Smrg glEnable(GL_TEXTURE_2D); 22732001f49Smrg 22832001f49Smrg glBlendFunc(GL_ONE, GL_ONE); 22932001f49Smrg} 23032001f49Smrg 23132001f49Smrg 23232001f49Smrgstatic void ModeMenu(int entry) 23332001f49Smrg{ 23432001f49Smrg if (entry==99) 23532001f49Smrg exit(0); 23632001f49Smrg Mode = entry; 23732001f49Smrg} 23832001f49Smrg 23932001f49Smrg 24032001f49Smrgint main( int argc, char *argv[] ) 24132001f49Smrg{ 24232001f49Smrg glutInitWindowSize( 300, 300 ); 24332001f49Smrg glutInit( &argc, argv ); 24432001f49Smrg glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ); 24532001f49Smrg glutCreateWindow( "spectex" ); 24632001f49Smrg 24732001f49Smrg Init(); 24832001f49Smrg 24932001f49Smrg glutReshapeFunc( Reshape ); 25032001f49Smrg glutKeyboardFunc( Key ); 25132001f49Smrg glutSpecialFunc( SpecialKey ); 25232001f49Smrg glutDisplayFunc( Display ); 25332001f49Smrg glutIdleFunc( Idle ); 25432001f49Smrg 25532001f49Smrg glutCreateMenu( ModeMenu ); 25632001f49Smrg glutAddMenuEntry("1-pass lighting + texturing", 0); 25732001f49Smrg glutAddMenuEntry("specular lighting", 1); 25832001f49Smrg glutAddMenuEntry("diffuse lighting + texturing", 2); 25932001f49Smrg glutAddMenuEntry("2-pass lighting + texturing", 3); 26032001f49Smrg#ifdef GL_VERSION_1_2 26132001f49Smrg glutAddMenuEntry("OpenGL 1.2 separate specular", 4); 26232001f49Smrg#endif 26332001f49Smrg glutAddMenuEntry("Quit", 99); 26432001f49Smrg glutAttachMenu(GLUT_RIGHT_BUTTON); 26532001f49Smrg 26632001f49Smrg glutMainLoop(); 26732001f49Smrg return 0; 26832001f49Smrg} 269