Merge commit 'origin/master' into gallium-0.2
[mesa.git] / progs / demos / spectex.c
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 <GL/glut.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
243 glutInit( &argc, argv );
244 glutInitWindowPosition( 0, 0 );
245 glutInitWindowSize( 300, 300 );
246
247 glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
248
249 glutCreateWindow( "spectex" );
250
251 Init();
252
253 glutReshapeFunc( Reshape );
254 glutKeyboardFunc( Key );
255 glutSpecialFunc( SpecialKey );
256 glutDisplayFunc( Display );
257 glutIdleFunc( Idle );
258
259 glutCreateMenu( ModeMenu );
260 glutAddMenuEntry("1-pass lighting + texturing", 0);
261 glutAddMenuEntry("specular lighting", 1);
262 glutAddMenuEntry("diffuse lighting + texturing", 2);
263 glutAddMenuEntry("2-pass lighting + texturing", 3);
264 #ifdef GL_VERSION_1_2
265 glutAddMenuEntry("OpenGL 1.2 separate specular", 4);
266 #endif
267 glutAddMenuEntry("Quit", 99);
268 glutAttachMenu(GLUT_RIGHT_BUTTON);
269
270 glutMainLoop();
271 return 0;
272 }