Merge commit 'origin/gallium-master-merge'
[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 t0 = t;
109 frames = 0;
110 }
111 }
112 }
113
114 static void Idle (void)
115 {
116 lightPos[0] += delta;
117 if (lightPos[0] > 25.0f || lightPos[0] < -25.0f)
118 delta = -delta;
119 glutPostRedisplay ();
120 }
121
122 static void Reshape (int width, int height)
123 {
124 glViewport (0, 0, width, height);
125 glMatrixMode (GL_PROJECTION);
126 glLoadIdentity ();
127 glFrustum (-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
128 glMatrixMode (GL_MODELVIEW);
129 glLoadIdentity ();
130 glTranslatef (0.0f, 0.0f, -15.0f);
131 }
132
133 static void Key (unsigned char key, int x, int y)
134 {
135 (void) x;
136 (void) y;
137
138 switch (key)
139 {
140 case ' ':
141 case 'a':
142 anim = !anim;
143 if (anim)
144 glutIdleFunc (Idle);
145 else
146 glutIdleFunc (NULL);
147 break;
148 case 'x':
149 lightPos[0] -= 1.0f;
150 break;
151 case 'X':
152 lightPos[0] += 1.0f;
153 break;
154 case 'w':
155 wire = !wire;
156 if (wire)
157 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
158 else
159 glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
160 break;
161 case 'p':
162 pixelLight = !pixelLight;
163 if (pixelLight)
164 printf ("Per-pixel lighting\n");
165 else
166 printf ("Conventional lighting\n");
167 break;
168 case 27:
169 exit(0);
170 break;
171 }
172 glutPostRedisplay ();
173 }
174
175 static void SpecialKey (int key, int x, int y)
176 {
177 const GLfloat step = 3.0f;
178
179 (void) x;
180 (void) y;
181
182 switch (key)
183 {
184 case GLUT_KEY_UP:
185 xRot -= step;
186 break;
187 case GLUT_KEY_DOWN:
188 xRot += step;
189 break;
190 case GLUT_KEY_LEFT:
191 yRot -= step;
192 break;
193 case GLUT_KEY_RIGHT:
194 yRot += step;
195 break;
196 }
197 glutPostRedisplay ();
198 }
199
200 static void Init (void)
201 {
202 static const char *fragShaderText =
203 "uniform vec3 lightPos;\n"
204 "uniform vec4 diffuse;\n"
205 "uniform vec4 specular;\n"
206 "varying vec3 normal;\n"
207 "void main () {\n"
208 " // Compute dot product of light direction and normal vector\n"
209 " float dotProd = max (dot (lightPos, normalize (normal)), 0.0);\n"
210 " // Compute diffuse and specular contributions\n"
211 #if 1
212 " gl_FragColor = diffuse * dotProd + specular * pow (dotProd, 20.0);\n"
213 #elif 1 /* test IF/ELSE/ENDIF */
214 " if (normal.y > 0.0) { \n"
215 " gl_FragColor = diffuse * dotProd + specular * pow (dotProd, 20.0);\n"
216 " } \n"
217 " else { \n"
218 " if (normal.x < 0.0) { \n"
219 " gl_FragColor = vec4(1, 0, 0, 0); \n"
220 " } \n"
221 " else { \n"
222 " gl_FragColor = vec4(1, 1, 0, 0); \n"
223 " } \n"
224 " } \n"
225 #elif 1 /* test LOOP */
226 " while (1) { \n"
227 " if (normal.y >= 0.0) { \n"
228 " gl_FragColor = vec4(1, 0, 0, 0); \n"
229 " break; \n"
230 " } else { \n"
231 " gl_FragColor = diffuse * dotProd + specular * pow (dotProd, 20.0);\n"
232 " break; \n"
233 " } \n"
234 " } \n"
235 #endif
236 "}\n"
237 ;
238 static const char *vertShaderText =
239 "varying vec3 normal;\n"
240 "void main () {\n"
241 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
242 " normal = gl_NormalMatrix * gl_Normal;\n"
243 "}\n"
244 ;
245
246 if (!glutExtensionSupported ("GL_ARB_fragment_shader"))
247 {
248 printf ("Sorry, this demo requires GL_ARB_fragment_shader\n");
249 exit(1);
250 }
251 if (!glutExtensionSupported ("GL_ARB_shader_objects"))
252 {
253 printf ("Sorry, this demo requires GL_ARB_shader_objects\n");
254 exit(1);
255 }
256 if (!glutExtensionSupported ("GL_ARB_shading_language_100"))
257 {
258 printf ("Sorry, this demo requires GL_ARB_shading_language_100\n");
259 exit(1);
260 }
261 if (!glutExtensionSupported ("GL_ARB_vertex_shader"))
262 {
263 printf ("Sorry, this demo requires GL_ARB_vertex_shader\n");
264 exit(1);
265 }
266
267 glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) GETPROCADDRESS ("glCreateShaderObjectARB");
268 glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) GETPROCADDRESS ("glShaderSourceARB");
269 glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) GETPROCADDRESS ("glCompileShaderARB");
270 glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) GETPROCADDRESS ("glCreateProgramObjectARB");
271 glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) GETPROCADDRESS ("glAttachObjectARB");
272 glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) GETPROCADDRESS ("glLinkProgramARB");
273 glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) GETPROCADDRESS ("glUseProgramObjectARB");
274 glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) GETPROCADDRESS ("glGetUniformLocationARB");
275 glUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) GETPROCADDRESS ("glUniform3fvARB");
276 glUniform4fvARB = (PFNGLUNIFORM3FVARBPROC) GETPROCADDRESS ("glUniform4fvARB");
277
278 fragShader = glCreateShaderObjectARB (GL_FRAGMENT_SHADER_ARB);
279 glShaderSourceARB (fragShader, 1, &fragShaderText, NULL);
280 glCompileShaderARB (fragShader);
281
282 vertShader = glCreateShaderObjectARB (GL_VERTEX_SHADER_ARB);
283 glShaderSourceARB (vertShader, 1, &vertShaderText, NULL);
284 glCompileShaderARB (vertShader);
285
286 program = glCreateProgramObjectARB ();
287 glAttachObjectARB (program, fragShader);
288 glAttachObjectARB (program, vertShader);
289 glLinkProgramARB (program);
290 glUseProgramObjectARB (program);
291
292 uLightPos = glGetUniformLocationARB (program, "lightPos");
293 uDiffuse = glGetUniformLocationARB (program, "diffuse");
294 uSpecular = glGetUniformLocationARB (program, "specular");
295
296 glUniform4fvARB (uDiffuse, 1, diffuse);
297 glUniform4fvARB (uSpecular, 1, specular);
298
299 glClearColor (0.3f, 0.3f, 0.3f, 0.0f);
300 glEnable (GL_DEPTH_TEST);
301 glEnable (GL_LIGHT0);
302 glEnable (GL_LIGHTING);
303 glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
304 glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular);
305 glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 20.0f);
306
307 printf ("GL_RENDERER = %s\n", (const char *) glGetString (GL_RENDERER));
308 printf ("Press p to toggle between per-pixel and per-vertex lighting\n");
309 }
310
311 int main (int argc, char *argv[])
312 {
313 glutInit (&argc, argv);
314 glutInitWindowPosition ( 0, 0);
315 glutInitWindowSize (200, 200);
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