Home | History | Annotate | Line # | Download | only in demos
      1 
      2 /*
      3  * GLUT demonstration of texturing with specular highlights.
      4  *
      5  * When drawing a lit, textured surface one usually wants the specular
      6  * highlight to override the texture colors.  However, OpenGL applies
      7  * texturing after lighting so the specular highlight is modulated by
      8  * the texture.
      9  *
     10  * The solution here shown here is a two-pass algorithm:
     11  *  1. Draw the textured surface without specular lighting.
     12  *  2. Enable blending to add the next pass:
     13  *  3. Redraw the surface with a matte white material and only the
     14  *     specular components of light sources enabled.
     15  *
     16  * Brian Paul  February 1997
     17  */
     18 
     19 #include <stdio.h>
     20 #include <stdlib.h>
     21 #include <math.h>
     22 #include "glut_wrap.h"
     23 
     24 
     25 static GLUquadricObj *Quadric;
     26 static GLuint Sphere;
     27 static GLfloat LightPos[4] = {10.0, 10.0, 10.0, 1.0};
     28 static GLfloat Delta = 20.0;
     29 static GLint Mode = 4;
     30 
     31 /*static GLfloat Blue[4] = {0.0, 0.0, 1.0, 1.0};*/
     32 /*static GLfloat Gray[4] = {0.5, 0.5, 0.5, 1.0};*/
     33 static GLfloat Black[4] = {0.0, 0.0, 0.0, 1.0};
     34 static GLfloat White[4] = {1.0, 1.0, 1.0, 1.0};
     35 
     36 static GLboolean smooth = 1;
     37 
     38 static void
     39 Idle(void)
     40 {
     41    static double t0 = -1.;
     42    double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;;
     43    if (t0 < 0.0)
     44       t0 = t;
     45    dt = t - t0;
     46    t0 = t;
     47    LightPos[0] += Delta * dt;
     48    if (LightPos[0]>15.0 || LightPos[0]<-15.0)
     49       Delta = -Delta;
     50 
     51    glutPostRedisplay();
     52 }
     53 
     54 
     55 static void Display( void )
     56 {
     57    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
     58 
     59    glLightfv(GL_LIGHT0, GL_POSITION, LightPos);
     60 
     61    glPushMatrix();
     62    glRotatef(90.0, 1.0, 0.0, 0.0);
     63 
     64    if (Mode==0) {
     65       /* Typical method: diffuse + specular + texture */
     66       glEnable(GL_TEXTURE_2D);
     67       glLightfv(GL_LIGHT0, GL_DIFFUSE, White);  /* enable diffuse */
     68       glLightfv(GL_LIGHT0, GL_SPECULAR, White);  /* enable specular */
     69 #ifdef GL_VERSION_1_2
     70       glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR);
     71 #endif
     72       glCallList(Sphere);
     73    }
     74    else if (Mode==1) {
     75       /* just specular highlight */
     76       glDisable(GL_TEXTURE_2D);
     77       glLightfv(GL_LIGHT0, GL_DIFFUSE, Black);  /* disable diffuse */
     78       glLightfv(GL_LIGHT0, GL_SPECULAR, White);  /* enable specular */
     79 #ifdef GL_VERSION_1_2
     80       glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR);
     81 #endif
     82       glCallList(Sphere);
     83    }
     84    else if (Mode==2) {
     85       /* diffuse textured */
     86       glEnable(GL_TEXTURE_2D);
     87       glLightfv(GL_LIGHT0, GL_DIFFUSE, White);  /* enable diffuse */
     88       glLightfv(GL_LIGHT0, GL_SPECULAR, Black);  /* disable specular */
     89 #ifdef GL_VERSION_1_2
     90       glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR);
     91 #endif
     92       glCallList(Sphere);
     93    }
     94    else if (Mode==3) {
     95       /* 2-pass: diffuse textured then add specular highlight*/
     96       glEnable(GL_TEXTURE_2D);
     97       glLightfv(GL_LIGHT0, GL_DIFFUSE, White);  /* enable diffuse */
     98       glLightfv(GL_LIGHT0, GL_SPECULAR, Black);  /* disable specular */
     99 #ifdef GL_VERSION_1_2
    100       glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR);
    101 #endif
    102       glCallList(Sphere);
    103       /* specular highlight */
    104       glDepthFunc(GL_EQUAL);  /* redraw same pixels */
    105       glDisable(GL_TEXTURE_2D);
    106       glEnable(GL_BLEND);  /* add */
    107       glLightfv(GL_LIGHT0, GL_DIFFUSE, Black);  /* disable diffuse */
    108       glLightfv(GL_LIGHT0, GL_SPECULAR, White);  /* enable specular */
    109       glCallList(Sphere);
    110       glDepthFunc(GL_LESS);
    111       glDisable(GL_BLEND);
    112    }
    113    else if (Mode==4) {
    114       /* OpenGL 1.2's separate diffuse and specular color */
    115       glEnable(GL_TEXTURE_2D);
    116       glLightfv(GL_LIGHT0, GL_DIFFUSE, White);  /* enable diffuse */
    117       glLightfv(GL_LIGHT0, GL_SPECULAR, White);  /* enable specular */
    118 #ifdef GL_VERSION_1_2
    119       glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
    120 #endif
    121       glCallList(Sphere);
    122    }
    123 
    124    glPopMatrix();
    125 
    126    glutSwapBuffers();
    127 }
    128 
    129 
    130 static void Reshape( int width, int height )
    131 {
    132    glViewport( 0, 0, width, height );
    133    glMatrixMode( GL_PROJECTION );
    134    glLoadIdentity();
    135    glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 25.0 );
    136    glMatrixMode( GL_MODELVIEW );
    137    glLoadIdentity();
    138    glTranslatef( 0.0, 0.0, -12.0 );
    139 }
    140 
    141 
    142 static void Key( unsigned char key, int x, int y )
    143 {
    144    (void) x;
    145    (void) y;
    146    switch (key) {
    147    case 27:
    148       exit(0);
    149       break;
    150    case 's':
    151       smooth = !smooth;
    152       if (smooth)
    153          glShadeModel(GL_SMOOTH);
    154       else
    155          glShadeModel(GL_FLAT);
    156       break;
    157    }
    158    glutPostRedisplay();
    159 }
    160 
    161 
    162 static void SpecialKey( int key, int x, int y )
    163 {
    164    (void) x;
    165    (void) y;
    166    switch (key) {
    167       case GLUT_KEY_UP:
    168          break;
    169       case GLUT_KEY_DOWN:
    170          break;
    171    }
    172    glutPostRedisplay();
    173 }
    174 
    175 
    176 static void Init( void )
    177 {
    178    int i, j;
    179    GLubyte texImage[64][64][3];
    180 
    181    glEnable(GL_LIGHTING);
    182    glEnable(GL_LIGHT0);
    183    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
    184    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, Black);
    185 
    186    glShadeModel(GL_SMOOTH);
    187 
    188    glMaterialfv(GL_FRONT, GL_DIFFUSE, White);
    189    glMaterialfv(GL_FRONT, GL_SPECULAR, White);
    190    glMaterialf(GL_FRONT, GL_SHININESS, 20.0);
    191 
    192    /* Actually, these are set again later */
    193    glLightfv(GL_LIGHT0, GL_DIFFUSE, White);
    194    glLightfv(GL_LIGHT0, GL_SPECULAR, White);
    195 
    196    Quadric = gluNewQuadric();
    197    gluQuadricTexture( Quadric, GL_TRUE );
    198 
    199    Sphere= glGenLists(1);
    200    glNewList( Sphere, GL_COMPILE );
    201    gluSphere( Quadric, 1.0, 24, 24 );
    202    glEndList();
    203 
    204    glEnable(GL_DEPTH_TEST);
    205    glEnable(GL_CULL_FACE);
    206 
    207    for (i=0;i<64;i++) {
    208       for (j=0;j<64;j++) {
    209          int k = ((i>>3)&1) ^ ((j>>3)&1);
    210          texImage[i][j][0] = 255*k;
    211          texImage[i][j][1] = 255*(1-k);
    212          texImage[i][j][2] = 0;
    213       }
    214    }
    215 
    216    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    217    glTexImage2D( GL_TEXTURE_2D,
    218                  0,
    219                  3,
    220                  64, 64,
    221                  0,
    222                  GL_RGB, GL_UNSIGNED_BYTE,
    223                  texImage );
    224    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    225    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    226    glEnable(GL_TEXTURE_2D);
    227 
    228    glBlendFunc(GL_ONE, GL_ONE);
    229 }
    230 
    231 
    232 static void ModeMenu(int entry)
    233 {
    234    if (entry==99)
    235       exit(0);
    236    Mode = entry;
    237 }
    238 
    239 
    240 int main( int argc, char *argv[] )
    241 {
    242    glutInitWindowSize( 300, 300 );
    243    glutInit( &argc, argv );
    244    glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
    245    glutCreateWindow( "spectex" );
    246 
    247    Init();
    248 
    249    glutReshapeFunc( Reshape );
    250    glutKeyboardFunc( Key );
    251    glutSpecialFunc( SpecialKey );
    252    glutDisplayFunc( Display );
    253    glutIdleFunc( Idle );
    254 
    255    glutCreateMenu( ModeMenu );
    256    glutAddMenuEntry("1-pass lighting + texturing", 0);
    257    glutAddMenuEntry("specular lighting", 1);
    258    glutAddMenuEntry("diffuse lighting + texturing", 2);
    259    glutAddMenuEntry("2-pass lighting + texturing", 3);
    260 #ifdef GL_VERSION_1_2
    261    glutAddMenuEntry("OpenGL 1.2 separate specular", 4);
    262 #endif
    263    glutAddMenuEntry("Quit", 99);
    264    glutAttachMenu(GLUT_RIGHT_BUTTON);
    265 
    266    glutMainLoop();
    267    return 0;
    268 }
    269