Merge branch 'mesa_7_7_branch'
[mesa.git] / progs / demos / arbfslight.c
1 /*
2 * Use GL_ARB_fragment_shader and GL_ARB_vertex_shader to implement
3 * simple per-pixel lighting.
4 *
5 * Michal Krol
6 * 20 February 2006
7 *
8 * Based on the original demo by:
9 * Brian Paul
10 * 17 April 2003
11 */
12
13 #ifdef WIN32
14 #include <windows.h>
15 #endif
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <math.h>
20 #include <GL/gl.h>
21 #include <GL/glut.h>
22 #include <GL/glext.h>
23
24 #ifdef WIN32
25 #define GETPROCADDRESS wglGetProcAddress
26 #else
27 #define GETPROCADDRESS glutGetProcAddress
28 #endif
29
30 static GLfloat diffuse[4] = { 0.5f, 0.5f, 1.0f, 1.0f };
31 static GLfloat specular[4] = { 0.8f, 0.8f, 0.8f, 1.0f };
32 static GLfloat lightPos[4] = { 0.0f, 10.0f, 20.0f, 1.0f };
33 static GLfloat delta = 1.0f;
34
35 static GLhandleARB fragShader;
36 static GLhandleARB vertShader;
37 static GLhandleARB program;
38
39 static GLint uLightPos;
40 static GLint uDiffuse;
41 static GLint uSpecular;
42
43 static GLboolean anim = GL_TRUE;
44 static GLboolean wire = GL_FALSE;
45 static GLboolean pixelLight = GL_TRUE;
46
47 static GLint t0 = 0;
48 static GLint frames = 0;
49
50 static GLfloat xRot = 0.0f, yRot = 0.0f;
51
52 static PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB = NULL;
53 static PFNGLSHADERSOURCEARBPROC glShaderSourceARB = NULL;
54 static PFNGLCOMPILESHADERARBPROC glCompileShaderARB = NULL;
55 static PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB = NULL;
56 static PFNGLATTACHOBJECTARBPROC glAttachObjectARB = NULL;
57 static PFNGLLINKPROGRAMARBPROC glLinkProgramARB = NULL;
58 static PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB = NULL;
59 static PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB = NULL;
60 static PFNGLUNIFORM3FVARBPROC glUniform3fvARB = NULL;
61 static PFNGLUNIFORM3FVARBPROC glUniform4fvARB = NULL;
62
63 static void normalize (GLfloat *dst, const GLfloat *src)
64 {
65 GLfloat len = sqrt (src[0] * src[0] + src[1] * src[1] + src[2] * src[2]);
66 dst[0] = src[0] / len;
67 dst[1] = src[1] / len;
68 dst[2] = src[2] / len;
69 }
70
71 static void Redisplay (void)
72 {
73 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
74
75 if (pixelLight)
76 {
77 GLfloat vec[3];
78
79 glUseProgramObjectARB (program);
80 normalize (vec, lightPos);
81 glUniform3fvARB (uLightPos, 1, vec);
82 glDisable(GL_LIGHTING);
83 }
84 else
85 {
86 glUseProgramObjectARB (0);
87 glLightfv (GL_LIGHT0, GL_POSITION, lightPos);
88 glEnable(GL_LIGHTING);
89 }
90
91 glPushMatrix ();
92 glRotatef (xRot, 1.0f, 0.0f, 0.0f);
93 glRotatef (yRot, 0.0f, 1.0f, 0.0f);
94 glutSolidSphere (2.0, 10, 5);
95 glPopMatrix ();
96
97 glutSwapBuffers();
98 frames++;
99
100 if (anim)
101 {
102 GLint t = glutGet (GLUT_ELAPSED_TIME);
103 if (t - t0 >= 5000)
104 {
105 GLfloat seconds = (GLfloat) (t - t0) / 1000.0f;
106 GLfloat fps = frames / seconds;
107 printf ("%d frames in %6.3f seconds = %6.3f FPS\n", frames, seconds, fps);
108 fflush(stdout);
109 t0 = t;
110 frames = 0;
111 }
112 }
113 }
114
115 static void Idle (void)
116 {
117 lightPos[0] += delta;
118 if (lightPos[0] > 25.0f || lightPos[0] < -25.0f)
119 delta = -delta;
120 glutPostRedisplay ();
121 }
122
123 static void Reshape (int width, int height)
124 {
125 glViewport (0, 0, width, height);
126 glMatrixMode (GL_PROJECTION);
127 glLoadIdentity ();
128 glFrustum (-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
129 glMatrixMode (GL_MODELVIEW);
130 glLoadIdentity ();
131 glTranslatef (0.0f, 0.0f, -15.0f);
132 }
133
134 static void Key (unsigned char key, int x, int y)
135 {
136 (void) x;
137 (void) y;
138
139 switch (key)
140 {
141 case ' ':
142 case 'a':
143 anim = !anim;
144 if (anim)
145 glutIdleFunc (Idle);
146 else
147 glutIdleFunc (NULL);
148 break;
149 case 'x':
150 lightPos[0] -= 1.0f;
151 break;
152 case 'X':
153 lightPos[0] += 1.0f;
154 break;
155 case 'w':
156 wire = !wire;
157 if (wire)
158 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
159 else
160 glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
161 break;
162 case 'p':
163 pixelLight = !pixelLight;
164 if (pixelLight)
165 printf ("Per-pixel lighting\n");
166 else
167 printf ("Conventional lighting\n");
168 break;
169 case 27:
170 exit(0);
171 break;
172 }
173 glutPostRedisplay ();
174 }
175
176 static void SpecialKey (int key, int x, int y)
177 {
178 const GLfloat step = 3.0f;
179
180 (void) x;
181 (void) y;
182
183 switch (key)
184 {
185 case GLUT_KEY_UP:
186 xRot -= step;
187 break;
188 case GLUT_KEY_DOWN:
189 xRot += step;
190 break;
191 case GLUT_KEY_LEFT:
192 yRot -= step;
193 break;
194 case GLUT_KEY_RIGHT:
195 yRot += step;
196 break;
197 }
198 glutPostRedisplay ();
199 }
200
201 static void Init (void)
202 {
203 static const char *fragShaderText =
204 "uniform vec3 lightPos;\n"
205 "uniform vec4 diffuse;\n"
206 "uniform vec4 specular;\n"
207 "varying vec3 normal;\n"
208 "void main () {\n"
209 " // Compute dot product of light direction and normal vector\n"
210 " float dotProd = max (dot (lightPos, normalize (normal)), 0.0);\n"
211 " // Compute diffuse and specular contributions\n"
212 #if 1
213 " gl_FragColor = diffuse * dotProd + specular * pow (dotProd, 20.0);\n"
214 #elif 1 /* test IF/ELSE/ENDIF */
215 " if (normal.y > 0.0) { \n"
216 " gl_FragColor = diffuse * dotProd + specular * pow (dotProd, 20.0);\n"
217 " } \n"
218 " else { \n"
219 " if (normal.x < 0.0) { \n"
220 " gl_FragColor = vec4(1, 0, 0, 0); \n"
221 " } \n"
222 " else { \n"
223 " gl_FragColor = vec4(1, 1, 0, 0); \n"
224 " } \n"
225 " } \n"
226 #elif 1 /* test LOOP */
227 " while (1) { \n"
228 " if (normal.y >= 0.0) { \n"
229 " gl_FragColor = vec4(1, 0, 0, 0); \n"
230 " break; \n"
231 " } else { \n"
232 " gl_FragColor = diffuse * dotProd + specular * pow (dotProd, 20.0);\n"
233 " break; \n"
234 " } \n"
235 " } \n"
236 #endif
237 "}\n"
238 ;
239 static const char *vertShaderText =
240 "varying vec3 normal;\n"
241 "void main () {\n"
242 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
243 " normal = gl_NormalMatrix * gl_Normal;\n"
244 "}\n"
245 ;
246
247 if (!glutExtensionSupported ("GL_ARB_fragment_shader"))
248 {
249 printf ("Sorry, this demo requires GL_ARB_fragment_shader\n");
250 exit(1);
251 }
252 if (!glutExtensionSupported ("GL_ARB_shader_objects"))
253 {
254 printf ("Sorry, this demo requires GL_ARB_shader_objects\n");
255 exit(1);
256 }
257 if (!glutExtensionSupported ("GL_ARB_shading_language_100"))
258 {
259 printf ("Sorry, this demo requires GL_ARB_shading_language_100\n");
260 exit(1);
261 }
262 if (!glutExtensionSupported ("GL_ARB_vertex_shader"))
263 {
264 printf ("Sorry, this demo requires GL_ARB_vertex_shader\n");
265 exit(1);
266 }
267
268 glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) GETPROCADDRESS ("glCreateShaderObjectARB");
269 glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) GETPROCADDRESS ("glShaderSourceARB");
270 glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) GETPROCADDRESS ("glCompileShaderARB");
271 glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) GETPROCADDRESS ("glCreateProgramObjectARB");
272 glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) GETPROCADDRESS ("glAttachObjectARB");
273 glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) GETPROCADDRESS ("glLinkProgramARB");
274 glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) GETPROCADDRESS ("glUseProgramObjectARB");
275 glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) GETPROCADDRESS ("glGetUniformLocationARB");
276 glUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) GETPROCADDRESS ("glUniform3fvARB");
277 glUniform4fvARB = (PFNGLUNIFORM3FVARBPROC) GETPROCADDRESS ("glUniform4fvARB");
278
279 fragShader = glCreateShaderObjectARB (GL_FRAGMENT_SHADER_ARB);
280 glShaderSourceARB (fragShader, 1, &fragShaderText, NULL);
281 glCompileShaderARB (fragShader);
282
283 vertShader = glCreateShaderObjectARB (GL_VERTEX_SHADER_ARB);
284 glShaderSourceARB (vertShader, 1, &vertShaderText, NULL);
285 glCompileShaderARB (vertShader);
286
287 program = glCreateProgramObjectARB ();
288 glAttachObjectARB (program, fragShader);
289 glAttachObjectARB (program, vertShader);
290 glLinkProgramARB (program);
291 glUseProgramObjectARB (program);
292
293 uLightPos = glGetUniformLocationARB (program, "lightPos");
294 uDiffuse = glGetUniformLocationARB (program, "diffuse");
295 uSpecular = glGetUniformLocationARB (program, "specular");
296
297 glUniform4fvARB (uDiffuse, 1, diffuse);
298 glUniform4fvARB (uSpecular, 1, specular);
299
300 glClearColor (0.3f, 0.3f, 0.3f, 0.0f);
301 glEnable (GL_DEPTH_TEST);
302 glEnable (GL_LIGHT0);
303 glEnable (GL_LIGHTING);
304 glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
305 glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular);
306 glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 20.0f);
307
308 printf ("GL_RENDERER = %s\n", (const char *) glGetString (GL_RENDERER));
309 printf ("Press p to toggle between per-pixel and per-vertex lighting\n");
310 }
311
312 int main (int argc, char *argv[])
313 {
314 glutInitWindowSize (200, 200);
315 glutInit (&argc, argv);
316 glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
317 glutCreateWindow (argv[0]);
318 glutReshapeFunc (Reshape);
319 glutKeyboardFunc (Key);
320 glutSpecialFunc (SpecialKey);
321 glutDisplayFunc (Redisplay);
322 if (anim)
323 glutIdleFunc (Idle);
324 Init ();
325 glutMainLoop ();
326 return 0;
327 }
328