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