blob: cfa7f74a21acdee0288f856d088e11b91213ba97 [file] [log] [blame]
jtgafb833d1999-08-19 00:55:39 +00001
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
jtgafb833d1999-08-19 00:55:39 +000019#include <stdio.h>
20#include <stdlib.h>
21#include <math.h>
22#include <GL/glut.h>
23
24
25static GLUquadricObj *Quadric;
26static GLuint Sphere;
27static GLfloat LightPos[4] = {10.0, 10.0, 10.0, 1.0};
Brian Paul92eddb02005-01-09 17:37:50 +000028static GLfloat Delta = 20.0;
29static GLint Mode = 4;
jtgafb833d1999-08-19 00:55:39 +000030
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};*/
33static GLfloat Black[4] = {0.0, 0.0, 0.0, 1.0};
34static GLfloat White[4] = {1.0, 1.0, 1.0, 1.0};
35
36
Brian Paul92eddb02005-01-09 17:37:50 +000037static void
38Idle(void)
jtgafb833d1999-08-19 00:55:39 +000039{
Brian Paul92eddb02005-01-09 17:37:50 +000040 static double t0 = -1.;
41 double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;;
42 if (t0 < 0.0)
43 t0 = t;
44 dt = t - t0;
45 t0 = t;
46 LightPos[0] += Delta * dt;
47 if (LightPos[0]>15.0 || LightPos[0]<-15.0)
48 Delta = -Delta;
jtgafb833d1999-08-19 00:55:39 +000049
50 glutPostRedisplay();
51}
52
53
54static void Display( void )
55{
56 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
57
58 glLightfv(GL_LIGHT0, GL_POSITION, LightPos);
59
60 glPushMatrix();
61 glRotatef(90.0, 1.0, 0.0, 0.0);
62
63 if (Mode==0) {
64 /* Typical method: diffuse + specular + texture */
65 glEnable(GL_TEXTURE_2D);
66 glLightfv(GL_LIGHT0, GL_DIFFUSE, White); /* enable diffuse */
67 glLightfv(GL_LIGHT0, GL_SPECULAR, White); /* enable specular */
68#ifdef GL_VERSION_1_2
69 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR);
70#endif
71 glCallList(Sphere);
72 }
73 else if (Mode==1) {
74 /* just specular highlight */
75 glDisable(GL_TEXTURE_2D);
76 glLightfv(GL_LIGHT0, GL_DIFFUSE, Black); /* disable diffuse */
77 glLightfv(GL_LIGHT0, GL_SPECULAR, White); /* enable specular */
78#ifdef GL_VERSION_1_2
79 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR);
80#endif
81 glCallList(Sphere);
82 }
83 else if (Mode==2) {
84 /* diffuse textured */
85 glEnable(GL_TEXTURE_2D);
86 glLightfv(GL_LIGHT0, GL_DIFFUSE, White); /* enable diffuse */
87 glLightfv(GL_LIGHT0, GL_SPECULAR, Black); /* disable specular */
88#ifdef GL_VERSION_1_2
89 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR);
90#endif
91 glCallList(Sphere);
92 }
93 else if (Mode==3) {
94 /* 2-pass: diffuse textured then add specular highlight*/
95 glEnable(GL_TEXTURE_2D);
96 glLightfv(GL_LIGHT0, GL_DIFFUSE, White); /* enable diffuse */
97 glLightfv(GL_LIGHT0, GL_SPECULAR, Black); /* disable specular */
98#ifdef GL_VERSION_1_2
99 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR);
100#endif
101 glCallList(Sphere);
102 /* specular highlight */
103 glDepthFunc(GL_EQUAL); /* redraw same pixels */
104 glDisable(GL_TEXTURE_2D);
105 glEnable(GL_BLEND); /* add */
106 glLightfv(GL_LIGHT0, GL_DIFFUSE, Black); /* disable diffuse */
107 glLightfv(GL_LIGHT0, GL_SPECULAR, White); /* enable specular */
108 glCallList(Sphere);
109 glDepthFunc(GL_LESS);
110 glDisable(GL_BLEND);
111 }
112 else if (Mode==4) {
113 /* OpenGL 1.2's separate diffuse and specular color */
114 glEnable(GL_TEXTURE_2D);
115 glLightfv(GL_LIGHT0, GL_DIFFUSE, White); /* enable diffuse */
116 glLightfv(GL_LIGHT0, GL_SPECULAR, White); /* enable specular */
117#ifdef GL_VERSION_1_2
118 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
119#endif
120 glCallList(Sphere);
121 }
122
123 glPopMatrix();
124
125 glutSwapBuffers();
126}
127
128
129static void Reshape( int width, int height )
130{
131 glViewport( 0, 0, width, height );
132 glMatrixMode( GL_PROJECTION );
133 glLoadIdentity();
134 glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 25.0 );
135 glMatrixMode( GL_MODELVIEW );
136 glLoadIdentity();
137 glTranslatef( 0.0, 0.0, -12.0 );
138}
139
140
141static void Key( unsigned char key, int x, int y )
142{
143 (void) x;
144 (void) y;
145 switch (key) {
146 case 27:
147 exit(0);
148 break;
149 }
150 glutPostRedisplay();
151}
152
153
154static void SpecialKey( int key, int x, int y )
155{
156 (void) x;
157 (void) y;
158 switch (key) {
159 case GLUT_KEY_UP:
160 break;
161 case GLUT_KEY_DOWN:
162 break;
163 }
164 glutPostRedisplay();
165}
166
167
168static void Init( void )
169{
170 int i, j;
171 GLubyte texImage[64][64][3];
172
173 glEnable(GL_LIGHTING);
174 glEnable(GL_LIGHT0);
175 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
176 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, Black);
177
178 glMaterialfv(GL_FRONT, GL_DIFFUSE, White);
179 glMaterialfv(GL_FRONT, GL_SPECULAR, White);
180 glMaterialf(GL_FRONT, GL_SHININESS, 20.0);
181
182 /* Actually, these are set again later */
183 glLightfv(GL_LIGHT0, GL_DIFFUSE, White);
184 glLightfv(GL_LIGHT0, GL_SPECULAR, White);
185
186 Quadric = gluNewQuadric();
187 gluQuadricTexture( Quadric, GL_TRUE );
188
189 Sphere= glGenLists(1);
190 glNewList( Sphere, GL_COMPILE );
191 gluSphere( Quadric, 1.0, 24, 24 );
192 glEndList();
193
194 glEnable(GL_DEPTH_TEST);
195 glEnable(GL_CULL_FACE);
196
197 for (i=0;i<64;i++) {
198 for (j=0;j<64;j++) {
199 int k = ((i>>3)&1) ^ ((j>>3)&1);
200 texImage[i][j][0] = 255*k;
201 texImage[i][j][1] = 255*(1-k);
202 texImage[i][j][2] = 0;
203 }
204 }
205
206 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
207 glTexImage2D( GL_TEXTURE_2D,
208 0,
209 3,
210 64, 64,
211 0,
212 GL_RGB, GL_UNSIGNED_BYTE,
213 texImage );
214 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
215 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
216 glEnable(GL_TEXTURE_2D);
217
218 glBlendFunc(GL_ONE, GL_ONE);
219}
220
221
222static void ModeMenu(int entry)
223{
224 if (entry==99)
225 exit(0);
226 Mode = entry;
227}
228
229
230int main( int argc, char *argv[] )
231{
232
233 glutInit( &argc, argv );
234 glutInitWindowPosition( 0, 0 );
235 glutInitWindowSize( 300, 300 );
236
237 glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
238
239 glutCreateWindow( "spectex" );
240
241 Init();
242
243 glutReshapeFunc( Reshape );
244 glutKeyboardFunc( Key );
245 glutSpecialFunc( SpecialKey );
246 glutDisplayFunc( Display );
247 glutIdleFunc( Idle );
248
249 glutCreateMenu( ModeMenu );
250 glutAddMenuEntry("1-pass lighting + texturing", 0);
251 glutAddMenuEntry("specular lighting", 1);
252 glutAddMenuEntry("diffuse lighting + texturing", 2);
253 glutAddMenuEntry("2-pass lighting + texturing", 3);
254#ifdef GL_VERSION_1_2
255 glutAddMenuEntry("OpenGL 1.2 separate specular", 4);
256#endif
257 glutAddMenuEntry("Quit", 99);
258 glutAttachMenu(GLUT_RIGHT_BUTTON);
259
260 glutMainLoop();
261 return 0;
262}