WIP - port to Mali EGL
[mesa-demos/mali.git] / src / demos / arbfplight.c
blob4c0d21d0c43af575cff8e88999e6d769ea7649b8
1 /*
2 * Use GL_ARB_fragment_program and GL_ARB_vertex_program to implement
3 * simple per-pixel lighting.
5 * Brian Paul
6 * 17 April 2003
7 */
9 #include <assert.h>
10 #include <string.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <math.h>
14 #include <GL/glew.h>
15 #include "glut_wrap.h"
18 static GLfloat Diffuse[4] = { 0.5, 0.5, 1.0, 1.0 };
19 static GLfloat Specular[4] = { 0.8, 0.8, 0.8, 1.0 };
20 static GLfloat LightPos[4] = { 0.0, 10.0, 20.0, 1.0 };
21 static GLfloat Delta = 1.0;
23 static GLuint FragProg;
24 static GLuint VertProg;
25 static GLboolean Anim = GL_TRUE;
26 static GLboolean Wire = GL_FALSE;
27 static GLboolean PixelLight = GL_TRUE;
28 static GLint Win;
30 static GLint T0 = 0;
31 static GLint Frames = 0;
33 static GLfloat Xrot = 0, Yrot = 0;
36 /* These must match the indexes used in the fragment program */
37 #define LIGHTPOS 3
39 /* Set to one to test ARB_fog_linear program option */
40 #define DO_FRAGMENT_FOG 0
42 static void normalize (GLfloat *dst, const GLfloat *src)
44 GLfloat len = sqrt (src[0] * src[0] + src[1] * src[1] + src[2] * src[2]);
45 dst[0] = src[0] / len;
46 dst[1] = src[1] / len;
47 dst[2] = src[2] / len;
50 static void Redisplay( void )
52 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
54 if (PixelLight) {
55 GLfloat pos[4];
57 normalize( pos, LightPos );
58 pos[3] = LightPos[3];
59 glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB,
60 LIGHTPOS, pos);
61 glEnable(GL_FRAGMENT_PROGRAM_ARB);
62 glEnable(GL_VERTEX_PROGRAM_ARB);
63 glDisable(GL_LIGHTING);
65 else {
66 glLightfv(GL_LIGHT0, GL_POSITION, LightPos);
67 glDisable(GL_FRAGMENT_PROGRAM_ARB);
68 glDisable(GL_VERTEX_PROGRAM_ARB);
69 glEnable(GL_LIGHTING);
72 glPushMatrix();
73 glRotatef(Xrot, 1, 0, 0);
74 glRotatef(Yrot, 0, 1, 0);
75 glutSolidSphere(2.0, 10, 5);
76 glPopMatrix();
78 glutSwapBuffers();
80 Frames++;
82 if (Anim) {
83 GLint t = glutGet(GLUT_ELAPSED_TIME);
84 if (t - T0 >= 5000) {
85 GLfloat seconds = (t - T0) / 1000.0;
86 GLfloat fps = Frames / seconds;
87 printf("%d frames in %6.3f seconds = %6.3f FPS\n", Frames, seconds, fps);
88 fflush(stdout);
89 T0 = t;
90 Frames = 0;
96 static void Idle(void)
98 LightPos[0] += Delta;
99 if (LightPos[0] > 25.0)
100 Delta = -1.0;
101 else if (LightPos[0] <- 25.0)
102 Delta = 1.0;
103 glutPostRedisplay();
107 static void Reshape( int width, int height )
109 glViewport( 0, 0, width, height );
110 glMatrixMode( GL_PROJECTION );
111 glLoadIdentity();
112 glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 25.0 );
113 glMatrixMode( GL_MODELVIEW );
114 glLoadIdentity();
115 glTranslatef( 0.0, 0.0, -15.0 );
119 static void Key( unsigned char key, int x, int y )
121 (void) x;
122 (void) y;
123 switch (key) {
124 case ' ':
125 case 'a':
126 Anim = !Anim;
127 if (Anim)
128 glutIdleFunc(Idle);
129 else
130 glutIdleFunc(NULL);
131 break;
132 case 'x':
133 LightPos[0] -= 1.0;
134 break;
135 case 'X':
136 LightPos[0] += 1.0;
137 break;
138 case 'w':
139 Wire = !Wire;
140 if (Wire)
141 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
142 else
143 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
144 break;
145 case 'p':
146 PixelLight = !PixelLight;
147 if (PixelLight) {
148 printf("Per-pixel lighting\n");
150 else {
151 printf("Conventional lighting\n");
153 break;
154 case 27:
155 glDeleteProgramsARB(1, &VertProg);
156 glDeleteProgramsARB(1, &FragProg);
157 glutDestroyWindow(Win);
158 exit(0);
159 break;
161 glutPostRedisplay();
164 static void SpecialKey( int key, int x, int y )
166 const GLfloat step = 3.0;
167 (void) x;
168 (void) y;
169 switch (key) {
170 case GLUT_KEY_UP:
171 Xrot -= step;
172 break;
173 case GLUT_KEY_DOWN:
174 Xrot += step;
175 break;
176 case GLUT_KEY_LEFT:
177 Yrot -= step;
178 break;
179 case GLUT_KEY_RIGHT:
180 Yrot += step;
181 break;
183 glutPostRedisplay();
187 /* A helper for finding errors in program strings */
188 static int FindLine( const char *program, int position )
190 int i, line = 1;
191 for (i = 0; i < position; i++) {
192 if (program[i] == '\n')
193 line++;
195 return line;
199 static void Init( void )
201 GLint errorPos;
203 /* Yes, this could be expressed more efficiently */
204 static const char *fragProgramText =
205 "!!ARBfp1.0\n"
206 #if DO_FRAGMENT_FOG
207 "OPTION ARB_fog_linear; \n"
208 #endif
209 "PARAM Diffuse = state.material.diffuse; \n"
210 "PARAM Specular = state.material.specular; \n"
211 "PARAM LightPos = program.local[3]; \n"
212 "TEMP normal, len; \n"
213 "TEMP dotProd, specAtten; \n"
214 "TEMP diffuseColor, specularColor; \n"
216 "# Compute normalized normal \n"
217 "DP3 len.x, fragment.texcoord[0], fragment.texcoord[0]; \n"
218 "RSQ len.y, len.x; \n"
219 "MUL normal.xyz, fragment.texcoord[0], len.y; \n"
221 "# Compute dot product of light direction and normal vector\n"
222 "DP3_SAT dotProd.x, LightPos, normal; # limited to [0,1]\n"
224 "MUL diffuseColor.xyz, Diffuse, dotProd.x; # diffuse attenuation\n"
226 "POW specAtten.x, dotProd.x, {20.0}.x; # specular exponent\n"
228 "MUL specularColor.xyz, Specular, specAtten.x; # specular attenuation\n"
230 "MOV result.color.w, Diffuse; \n"
231 #if DO_FRAGMENT_FOG
232 "# need to clamp color to [0,1] before fogging \n"
233 "ADD_SAT result.color.xyz, diffuseColor, specularColor; # add colors\n"
234 #else
235 "# clamping will be done after program's finished \n"
236 "ADD result.color.xyz, diffuseColor, specularColor; # add colors\n"
237 #endif
238 "END \n"
241 static const char *vertProgramText =
242 "!!ARBvp1.0\n"
243 "ATTRIB pos = vertex.position; \n"
244 "ATTRIB norm = vertex.normal; \n"
245 "PARAM modelview[4] = { state.matrix.modelview }; \n"
246 "PARAM modelviewProj[4] = { state.matrix.mvp }; \n"
247 "PARAM invModelview[4] = { state.matrix.modelview.invtrans }; \n"
249 "# typical modelview/projection transform \n"
250 "DP4 result.position.x, pos, modelviewProj[0]; \n"
251 "DP4 result.position.y, pos, modelviewProj[1]; \n"
252 "DP4 result.position.z, pos, modelviewProj[2]; \n"
253 "DP4 result.position.w, pos, modelviewProj[3]; \n"
255 "# transform normal by inv transpose of modelview, put in tex0 \n"
256 "DP3 result.texcoord[0].x, norm, invModelview[0]; \n"
257 "DP3 result.texcoord[0].y, norm, invModelview[1]; \n"
258 "DP3 result.texcoord[0].z, norm, invModelview[2]; \n"
259 "DP3 result.texcoord[0].w, norm, invModelview[3]; \n"
261 #if DO_FRAGMENT_FOG
262 "# compute fog coordinate = vertex eye-space Z coord (negated)\n"
263 "DP4 result.fogcoord, -pos, modelview[2]; \n"
264 #endif
265 "END\n";
268 if (!glutExtensionSupported("GL_ARB_vertex_program")) {
269 printf("Sorry, this demo requires GL_ARB_vertex_program\n");
270 exit(1);
272 if (!glutExtensionSupported("GL_ARB_fragment_program")) {
273 printf("Sorry, this demo requires GL_ARB_fragment_program\n");
274 exit(1);
278 * Fragment program
280 glGenProgramsARB(1, &FragProg);
281 assert(FragProg > 0);
282 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, FragProg);
283 glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB,
284 GL_PROGRAM_FORMAT_ASCII_ARB,
285 strlen(fragProgramText),
286 (const GLubyte *) fragProgramText);
287 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
288 if (glGetError() != GL_NO_ERROR || errorPos != -1) {
289 int l = FindLine(fragProgramText, errorPos);
290 printf("Fragment Program Error (pos=%d line=%d): %s\n", errorPos, l,
291 (char *) glGetString(GL_PROGRAM_ERROR_STRING_ARB));
292 exit(0);
294 assert(glIsProgramARB(FragProg));
297 * Do some sanity tests
300 GLdouble v[4];
301 glProgramLocalParameter4dARB(GL_FRAGMENT_PROGRAM_ARB, 8,
302 10.0, 20.0, 30.0, 40.0);
303 glGetProgramLocalParameterdvARB(GL_FRAGMENT_PROGRAM_ARB, 8, v);
304 assert(v[0] == 10.0);
305 assert(v[1] == 20.0);
306 assert(v[2] == 30.0);
307 assert(v[3] == 40.0);
311 * Vertex program
313 glGenProgramsARB(1, &VertProg);
314 assert(VertProg > 0);
315 glBindProgramARB(GL_VERTEX_PROGRAM_ARB, VertProg);
316 glProgramStringARB(GL_VERTEX_PROGRAM_ARB,
317 GL_PROGRAM_FORMAT_ASCII_ARB,
318 strlen(vertProgramText),
319 (const GLubyte *) vertProgramText);
320 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
321 if (glGetError() != GL_NO_ERROR || errorPos != -1) {
322 int l = FindLine(vertProgramText, errorPos);
323 printf("Vertex Program Error (pos=%d line=%d): %s\n", errorPos, l,
324 (char *) glGetString(GL_PROGRAM_ERROR_STRING_ARB));
325 exit(0);
327 assert(glIsProgramARB(VertProg));
330 * Misc init
332 glClearColor(0.3, 0.3, 0.3, 0.0);
333 glEnable(GL_DEPTH_TEST);
334 glEnable(GL_LIGHT0);
335 glEnable(GL_LIGHTING);
336 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Diffuse);
337 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, Specular);
338 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 20.0);
340 #if DO_FRAGMENT_FOG
342 /* Green-ish fog color */
343 static const GLfloat fogColor[4] = {0.5, 1.0, 0.5, 0};
344 glFogfv(GL_FOG_COLOR, fogColor);
345 glFogf(GL_FOG_START, 5.0);
346 glFogf(GL_FOG_END, 25.0);
348 #endif
350 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
351 printf("Press p to toggle between per-pixel and per-vertex lighting\n");
355 int main( int argc, char *argv[] )
357 glutInitWindowSize( 200, 200 );
358 glutInit( &argc, argv );
359 glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
360 Win = glutCreateWindow(argv[0]);
361 glewInit();
362 glutReshapeFunc( Reshape );
363 glutKeyboardFunc( Key );
364 glutSpecialFunc( SpecialKey );
365 glutDisplayFunc( Redisplay );
366 if (Anim)
367 glutIdleFunc(Idle);
368 Init();
369 glutMainLoop();
370 return 0;