Merge branch 'nouveau-import'
[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 = sqrtf (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 " gl_FragColor = diffuse * dotProd + specular * pow (dotProd, 20.0);\n"
212 "}\n"
213 ;
214 static const char *vertShaderText =
215 "varying vec3 normal;\n"
216 "void main () {\n"
217 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
218 " normal = gl_NormalMatrix * gl_Normal;\n"
219 "}\n"
220 ;
221
222 if (!glutExtensionSupported ("GL_ARB_fragment_shader"))
223 {
224 printf ("Sorry, this demo requires GL_ARB_fragment_shader\n");
225 exit(1);
226 }
227 if (!glutExtensionSupported ("GL_ARB_shader_objects"))
228 {
229 printf ("Sorry, this demo requires GL_ARB_shader_objects\n");
230 exit(1);
231 }
232 if (!glutExtensionSupported ("GL_ARB_shading_language_100"))
233 {
234 printf ("Sorry, this demo requires GL_ARB_shading_language_100\n");
235 exit(1);
236 }
237 if (!glutExtensionSupported ("GL_ARB_vertex_shader"))
238 {
239 printf ("Sorry, this demo requires GL_ARB_vertex_shader\n");
240 exit(1);
241 }
242
243 glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) GETPROCADDRESS ("glCreateShaderObjectARB");
244 glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) GETPROCADDRESS ("glShaderSourceARB");
245 glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) GETPROCADDRESS ("glCompileShaderARB");
246 glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) GETPROCADDRESS ("glCreateProgramObjectARB");
247 glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) GETPROCADDRESS ("glAttachObjectARB");
248 glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) GETPROCADDRESS ("glLinkProgramARB");
249 glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) GETPROCADDRESS ("glUseProgramObjectARB");
250 glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) GETPROCADDRESS ("glGetUniformLocationARB");
251 glUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) GETPROCADDRESS ("glUniform3fvARB");
252 glUniform4fvARB = (PFNGLUNIFORM3FVARBPROC) GETPROCADDRESS ("glUniform4fvARB");
253
254 fragShader = glCreateShaderObjectARB (GL_FRAGMENT_SHADER_ARB);
255 glShaderSourceARB (fragShader, 1, &fragShaderText, NULL);
256 glCompileShaderARB (fragShader);
257
258 vertShader = glCreateShaderObjectARB (GL_VERTEX_SHADER_ARB);
259 glShaderSourceARB (vertShader, 1, &vertShaderText, NULL);
260 glCompileShaderARB (vertShader);
261
262 program = glCreateProgramObjectARB ();
263 glAttachObjectARB (program, fragShader);
264 glAttachObjectARB (program, vertShader);
265 glLinkProgramARB (program);
266 glUseProgramObjectARB (program);
267
268 uLightPos = glGetUniformLocationARB (program, "lightPos");
269 uDiffuse = glGetUniformLocationARB (program, "diffuse");
270 uSpecular = glGetUniformLocationARB (program, "specular");
271
272 glUniform4fvARB (uDiffuse, 1, diffuse);
273 glUniform4fvARB (uSpecular, 1, specular);
274
275 glClearColor (0.3f, 0.3f, 0.3f, 0.0f);
276 glEnable (GL_DEPTH_TEST);
277 glEnable (GL_LIGHT0);
278 glEnable (GL_LIGHTING);
279 glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
280 glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular);
281 glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 20.0f);
282
283 printf ("GL_RENDERER = %s\n", (const char *) glGetString (GL_RENDERER));
284 printf ("Press p to toggle between per-pixel and per-vertex lighting\n");
285 }
286
287 int main (int argc, char *argv[])
288 {
289 glutInit (&argc, argv);
290 glutInitWindowPosition ( 0, 0);
291 glutInitWindowSize (200, 200);
292 glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
293 glutCreateWindow (argv[0]);
294 glutReshapeFunc (Reshape);
295 glutKeyboardFunc (Key);
296 glutSpecialFunc (SpecialKey);
297 glutDisplayFunc (Redisplay);
298 if (anim)
299 glutIdleFunc (Idle);
300 Init ();
301 glutMainLoop ();
302 return 0;
303 }
304