WIP - port to Mali EGL
[mesa-demos/mali.git] / src / demos / fslight.c
blob773108a44c877e3731c232a25c572012a97eea89
1 /**
2 * Test OpenGL 2.0 vertex/fragment shaders.
3 * Brian Paul
4 * 1 November 2006
6 * Based on ARB version by:
7 * Michal Krol
8 * 20 February 2006
10 * Based on the original demo by:
11 * Brian Paul
12 * 17 April 2003
15 #include <assert.h>
16 #include <string.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <math.h>
20 #include <GL/glew.h>
21 #include "glut_wrap.h"
24 #define TEXTURE 0
26 static GLint CoordAttrib = 0;
28 static char *FragProgFile = NULL;
29 static char *VertProgFile = NULL;
31 static GLfloat diffuse[4] = { 0.5f, 0.5f, 1.0f, 1.0f };
32 static GLfloat specular[4] = { 0.8f, 0.8f, 0.8f, 1.0f };
33 static GLfloat lightPos[4] = { 0.0f, 10.0f, 20.0f, 0.0f };
34 static GLfloat delta = 1.0f;
36 static GLuint fragShader;
37 static GLuint vertShader;
38 static GLuint program;
40 static GLint uDiffuse;
41 static GLint uSpecular;
42 static GLint uTexture;
44 static GLuint SphereList, RectList, CurList;
45 static GLint win = 0;
46 static GLboolean anim = GL_TRUE;
47 static GLboolean wire = GL_FALSE;
48 static GLboolean pixelLight = GL_TRUE;
50 static GLint t0 = 0;
51 static GLint frames = 0;
53 static GLfloat xRot = 90.0f, yRot = 0.0f;
56 static void
57 normalize(GLfloat *dst, const GLfloat *src)
59 GLfloat len = sqrt(src[0] * src[0] + src[1] * src[1] + src[2] * src[2]);
60 dst[0] = src[0] / len;
61 dst[1] = src[1] / len;
62 dst[2] = src[2] / len;
63 dst[3] = src[3];
67 static void
68 Redisplay(void)
70 GLfloat vec[4];
72 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
74 /* update light position */
75 normalize(vec, lightPos);
76 glLightfv(GL_LIGHT0, GL_POSITION, vec);
78 if (pixelLight) {
79 glUseProgram(program);
80 glDisable(GL_LIGHTING);
82 else {
83 glUseProgram(0);
84 glEnable(GL_LIGHTING);
87 glPushMatrix();
88 glRotatef(xRot, 1.0f, 0.0f, 0.0f);
89 glRotatef(yRot, 0.0f, 1.0f, 0.0f);
91 glutSolidSphere(2.0, 10, 5);
93 glCallList(CurList);
94 glPopMatrix();
96 glutSwapBuffers();
97 frames++;
99 if (anim) {
100 GLint t = glutGet(GLUT_ELAPSED_TIME);
101 if (t - t0 >= 5000) {
102 GLfloat seconds =(GLfloat)(t - t0) / 1000.0f;
103 GLfloat fps = frames / seconds;
104 printf("%d frames in %6.3f seconds = %6.3f FPS\n",
105 frames, seconds, fps);
106 fflush(stdout);
107 t0 = t;
108 frames = 0;
114 static void
115 Idle(void)
117 lightPos[0] += delta;
118 if (lightPos[0] > 25.0f || lightPos[0] < -25.0f)
119 delta = -delta;
120 glutPostRedisplay();
124 static void
125 Reshape(int width, int height)
127 glViewport(0, 0, width, height);
128 glMatrixMode(GL_PROJECTION);
129 glLoadIdentity();
130 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
131 glMatrixMode(GL_MODELVIEW);
132 glLoadIdentity();
133 glTranslatef(0.0f, 0.0f, -15.0f);
137 static void
138 CleanUp(void)
140 glDeleteShader(fragShader);
141 glDeleteShader(vertShader);
142 glDeleteProgram(program);
143 glutDestroyWindow(win);
147 static void
148 Key(unsigned char key, int x, int y)
150 (void) x;
151 (void) y;
153 switch(key) {
154 case ' ':
155 case 'a':
156 anim = !anim;
157 if (anim)
158 glutIdleFunc(Idle);
159 else
160 glutIdleFunc(NULL);
161 break;
162 case 'x':
163 lightPos[0] -= 1.0f;
164 break;
165 case 'X':
166 lightPos[0] += 1.0f;
167 break;
168 case 'w':
169 wire = !wire;
170 if (wire)
171 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
172 else
173 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
174 break;
175 case 'o':
176 if (CurList == SphereList)
177 CurList = RectList;
178 else
179 CurList = SphereList;
180 break;
181 case 'p':
182 pixelLight = !pixelLight;
183 if (pixelLight)
184 printf("Per-pixel lighting\n");
185 else
186 printf("Conventional lighting\n");
187 break;
188 case 27:
189 CleanUp();
190 exit(0);
191 break;
193 glutPostRedisplay();
197 static void
198 SpecialKey(int key, int x, int y)
200 const GLfloat step = 3.0f;
202 (void) x;
203 (void) y;
205 switch(key) {
206 case GLUT_KEY_UP:
207 xRot -= step;
208 break;
209 case GLUT_KEY_DOWN:
210 xRot += step;
211 break;
212 case GLUT_KEY_LEFT:
213 yRot -= step;
214 break;
215 case GLUT_KEY_RIGHT:
216 yRot += step;
217 break;
219 glutPostRedisplay();
223 static void
224 TestFunctions(void)
226 printf("Error 0x%x at line %d\n", glGetError(), __LINE__);
228 assert(glIsProgram(program));
229 assert(glIsShader(fragShader));
230 assert(glIsShader(vertShader));
232 /* attached shaders */
234 GLuint shaders[20];
235 GLsizei count;
236 int i;
237 glGetAttachedShaders(program, 20, &count, shaders);
238 for (i = 0; i < count; i++) {
239 printf("Attached: %u\n", shaders[i]);
240 assert(shaders[i] == fragShader ||
241 shaders[i] == vertShader);
246 GLchar log[1000];
247 GLsizei len;
248 glGetShaderInfoLog(vertShader, 1000, &len, log);
249 printf("Vert Shader Info Log: %s\n", log);
250 glGetShaderInfoLog(fragShader, 1000, &len, log);
251 printf("Frag Shader Info Log: %s\n", log);
252 glGetProgramInfoLog(program, 1000, &len, log);
253 printf("Program Info Log: %s\n", log);
256 /* active uniforms */
258 GLint n, max, i;
259 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &n);
260 glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max);
261 printf("Num uniforms: %d Max name length: %d\n", n, max);
262 for (i = 0; i < n; i++) {
263 GLint size, len;
264 GLenum type;
265 char name[100];
266 glGetActiveUniform(program, i, 100, &len, &size, &type, name);
267 printf(" %d: %s nameLen=%d size=%d type=0x%x\n",
268 i, name, len, size, type);
274 #if TEXTURE
275 static void
276 MakeTexture(void)
278 #define SZ0 64
279 #define SZ1 32
280 GLubyte image0[SZ0][SZ0][SZ0][4];
281 GLubyte image1[SZ1][SZ1][SZ1][4];
282 GLuint i, j, k;
284 /* level 0: two-tone gray checkboard */
285 for (i = 0; i < SZ0; i++) {
286 for (j = 0; j < SZ0; j++) {
287 for (k = 0; k < SZ0; k++) {
288 if ((i/8 + j/8 + k/8) & 1) {
289 image0[i][j][k][0] =
290 image0[i][j][k][1] =
291 image0[i][j][k][2] = 200;
293 else {
294 image0[i][j][k][0] =
295 image0[i][j][k][1] =
296 image0[i][j][k][2] = 100;
298 image0[i][j][k][3] = 255;
303 /* level 1: two-tone green checkboard */
304 for (i = 0; i < SZ1; i++) {
305 for (j = 0; j < SZ1; j++) {
306 for (k = 0; k < SZ1; k++) {
307 if ((i/8 + j/8 + k/8) & 1) {
308 image1[i][j][k][0] = 0;
309 image1[i][j][k][1] = 250;
310 image1[i][j][k][2] = 0;
312 else {
313 image1[i][j][k][0] = 0;
314 image1[i][j][k][1] = 200;
315 image1[i][j][k][2] = 0;
317 image1[i][j][k][3] = 255;
322 glActiveTexture(GL_TEXTURE2); /* unit 2 */
323 glBindTexture(GL_TEXTURE_2D, 42);
324 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SZ0, SZ0, 0,
325 GL_RGBA, GL_UNSIGNED_BYTE, image0);
326 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, SZ1, SZ1, 0,
327 GL_RGBA, GL_UNSIGNED_BYTE, image1);
328 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
329 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
330 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
332 glActiveTexture(GL_TEXTURE4); /* unit 4 */
333 glBindTexture(GL_TEXTURE_3D, 43);
334 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, SZ0, SZ0, SZ0, 0,
335 GL_RGBA, GL_UNSIGNED_BYTE, image0);
336 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA, SZ1, SZ1, SZ1, 0,
337 GL_RGBA, GL_UNSIGNED_BYTE, image1);
338 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1);
339 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
340 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
342 #endif
345 static void
346 MakeSphere(void)
348 GLUquadricObj *obj = gluNewQuadric();
349 SphereList = glGenLists(1);
350 gluQuadricTexture(obj, GL_TRUE);
351 glNewList(SphereList, GL_COMPILE);
352 gluSphere(obj, 2.0f, 10, 5);
353 glEndList();
354 gluDeleteQuadric(obj);
357 static void
358 VertAttrib(GLint index, float x, float y)
360 #if 1
361 glVertexAttrib2f(index, x, y);
362 #else
363 glTexCoord2f(x, y);
364 #endif
367 static void
368 MakeRect(void)
370 RectList = glGenLists(1);
371 glNewList(RectList, GL_COMPILE);
372 glNormal3f(0, 0, 1);
373 glBegin(GL_POLYGON);
374 VertAttrib(CoordAttrib, 0, 0); glVertex2f(-2, -2);
375 VertAttrib(CoordAttrib, 1, 0); glVertex2f( 2, -2);
376 VertAttrib(CoordAttrib, 1, 1); glVertex2f( 2, 2);
377 VertAttrib(CoordAttrib, 0, 1); glVertex2f(-2, 2);
378 glEnd(); /* XXX omit this and crash! */
379 glEndList();
384 static void
385 LoadAndCompileShader(GLuint shader, const char *text)
387 GLint stat;
389 glShaderSource(shader, 1, (const GLchar **) &text, NULL);
391 glCompileShader(shader);
393 glGetShaderiv(shader, GL_COMPILE_STATUS, &stat);
394 if (!stat) {
395 GLchar log[1000];
396 GLsizei len;
397 glGetShaderInfoLog(shader, 1000, &len, log);
398 fprintf(stderr, "fslight: problem compiling shader:\n%s\n", log);
399 exit(1);
405 * Read a shader from a file.
407 static void
408 ReadShader(GLuint shader, const char *filename)
410 const int max = 100*1000;
411 int n;
412 char *buffer = (char*) malloc(max);
413 FILE *f = fopen(filename, "r");
414 if (!f) {
415 fprintf(stderr, "fslight: Unable to open shader file %s\n", filename);
416 exit(1);
419 n = fread(buffer, 1, max, f);
420 printf("fslight: read %d bytes from shader file %s\n", n, filename);
421 if (n > 0) {
422 buffer[n] = 0;
423 LoadAndCompileShader(shader, buffer);
426 fclose(f);
427 free(buffer);
431 static void
432 CheckLink(GLuint prog)
434 GLint stat;
435 glGetProgramiv(prog, GL_LINK_STATUS, &stat);
436 if (!stat) {
437 GLchar log[1000];
438 GLsizei len;
439 glGetProgramInfoLog(prog, 1000, &len, log);
440 fprintf(stderr, "Linker error:\n%s\n", log);
445 static void
446 Init(void)
448 static const char *fragShaderText =
449 "uniform vec4 diffuse;\n"
450 "uniform vec4 specular;\n"
451 "varying vec3 normal;\n"
452 "void main() {\n"
453 " // Compute dot product of light direction and normal vector\n"
454 " float dotProd = max(dot(gl_LightSource[0].position.xyz, \n"
455 " normalize(normal)), 0.0);\n"
456 " // Compute diffuse and specular contributions\n"
457 " gl_FragColor = diffuse * dotProd + specular * pow(dotProd, 20.0);\n"
458 "}\n";
459 static const char *vertShaderText =
460 "varying vec3 normal;\n"
461 "void main() {\n"
462 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
463 " normal = gl_NormalMatrix * gl_Normal;\n"
464 "}\n";
466 if (!GLEW_VERSION_2_0) {
467 printf("This program requires OpenGL 2.x or higher\n");
468 exit(1);
471 fragShader = glCreateShader(GL_FRAGMENT_SHADER);
472 if (FragProgFile)
473 ReadShader(fragShader, FragProgFile);
474 else
475 LoadAndCompileShader(fragShader, fragShaderText);
478 vertShader = glCreateShader(GL_VERTEX_SHADER);
479 if (VertProgFile)
480 ReadShader(vertShader, VertProgFile);
481 else
482 LoadAndCompileShader(vertShader, vertShaderText);
484 program = glCreateProgram();
485 glAttachShader(program, fragShader);
486 glAttachShader(program, vertShader);
487 glLinkProgram(program);
488 CheckLink(program);
489 glUseProgram(program);
491 uDiffuse = glGetUniformLocation(program, "diffuse");
492 uSpecular = glGetUniformLocation(program, "specular");
493 uTexture = glGetUniformLocation(program, "texture");
494 printf("DiffusePos %d SpecularPos %d TexturePos %d\n",
495 uDiffuse, uSpecular, uTexture);
497 glUniform4fv(uDiffuse, 1, diffuse);
498 glUniform4fv(uSpecular, 1, specular);
499 /* assert(glGetError() == 0);*/
500 #if TEXTURE
501 glUniform1i(uTexture, 2); /* use texture unit 2 */
502 #endif
503 /*assert(glGetError() == 0);*/
505 if (CoordAttrib) {
506 int i;
507 glBindAttribLocation(program, CoordAttrib, "coord");
508 i = glGetAttribLocation(program, "coord");
509 assert(i >= 0);
510 if (i != CoordAttrib) {
511 printf("Hmmm, NVIDIA bug?\n");
512 CoordAttrib = i;
514 else {
515 printf("Mesa bind attrib: coord = %d\n", i);
519 /*assert(glGetError() == 0);*/
521 glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
522 glEnable(GL_DEPTH_TEST);
523 glEnable(GL_LIGHT0);
524 glEnable(GL_LIGHTING);
525 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
526 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
527 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 20.0f);
529 MakeSphere();
530 MakeRect();
532 CurList = SphereList;
534 #if TEXTURE
535 MakeTexture();
536 #endif
538 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
539 printf("Press p to toggle between per-pixel and per-vertex lighting\n");
541 /* test glGetShaderSource() */
542 if (0) {
543 GLsizei len = strlen(fragShaderText) + 1;
544 GLsizei lenOut;
545 GLchar *src =(GLchar *) malloc(len * sizeof(GLchar));
546 glGetShaderSource(fragShader, 0, NULL, src);
547 glGetShaderSource(fragShader, len, &lenOut, src);
548 assert(len == lenOut + 1);
549 assert(strcmp(src, fragShaderText) == 0);
550 free(src);
553 assert(glIsProgram(program));
554 assert(glIsShader(fragShader));
555 assert(glIsShader(vertShader));
557 glColor3f(1, 0, 0);
559 /* for testing state vars */
561 static GLfloat fc[4] = { 1, 1, 0, 0 };
562 static GLfloat amb[4] = { 1, 0, 1, 0 };
563 glFogfv(GL_FOG_COLOR, fc);
564 glLightfv(GL_LIGHT1, GL_AMBIENT, amb);
567 #if 0
568 TestFunctions();
569 #else
570 (void) TestFunctions;
571 #endif
575 static void
576 ParseOptions(int argc, char *argv[])
578 int i;
579 for (i = 1; i < argc; i++) {
580 if (strcmp(argv[i], "-fs") == 0) {
581 FragProgFile = argv[++i];
583 else if (strcmp(argv[i], "-vs") == 0) {
584 VertProgFile = argv[++i];
586 else {
587 fprintf(stderr, "unknown option %s\n", argv[i]);
588 break;
595 main(int argc, char *argv[])
597 glutInitWindowSize(200, 200);
598 glutInit(&argc, argv);
599 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
600 win = glutCreateWindow(argv[0]);
601 glewInit();
602 glutReshapeFunc(Reshape);
603 glutKeyboardFunc(Key);
604 glutSpecialFunc(SpecialKey);
605 glutDisplayFunc(Redisplay);
606 if (anim)
607 glutIdleFunc(Idle);
608 ParseOptions(argc, argv);
609 Init();
610 glutMainLoop();
611 return 0;