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