2 * Test OpenGL 2.0 vertex/fragment shaders.
6 * Based on ARB version by:
10 * Based on the original demo by:
28 static GLint CoordAttrib
= 0;
30 static char *FragProgFile
= NULL
;
31 static char *VertProgFile
= NULL
;
33 static GLfloat diffuse
[4] = { 0.5f
, 0.5f
, 1.0f
, 1.0f
};
34 static GLfloat specular
[4] = { 0.8f
, 0.8f
, 0.8f
, 1.0f
};
35 static GLfloat lightPos
[4] = { 0.0f
, 10.0f
, 20.0f
, 0.0f
};
36 static GLfloat delta
= 1.0f
;
38 static GLuint fragShader
;
39 static GLuint vertShader
;
40 static GLuint program
;
42 static GLint uDiffuse
;
43 static GLint uSpecular
;
44 static GLint uTexture
;
46 static GLuint SphereList
, RectList
, CurList
;
48 static GLboolean anim
= GL_TRUE
;
49 static GLboolean wire
= GL_FALSE
;
50 static GLboolean pixelLight
= GL_TRUE
;
53 static GLint frames
= 0;
55 static GLfloat xRot
= 90.0f
, yRot
= 0.0f
;
59 normalize(GLfloat
*dst
, const GLfloat
*src
)
61 GLfloat len
= sqrt(src
[0] * src
[0] + src
[1] * src
[1] + src
[2] * src
[2]);
62 dst
[0] = src
[0] / len
;
63 dst
[1] = src
[1] / len
;
64 dst
[2] = src
[2] / len
;
74 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
76 /* update light position */
77 normalize(vec
, lightPos
);
78 glLightfv(GL_LIGHT0
, GL_POSITION
, vec
);
81 glUseProgram_func(program
);
82 glDisable(GL_LIGHTING
);
86 glEnable(GL_LIGHTING
);
90 glRotatef(xRot
, 1.0f
, 0.0f
, 0.0f
);
91 glRotatef(yRot
, 0.0f
, 1.0f
, 0.0f
);
93 glutSolidSphere(2.0, 10, 5);
102 GLint t
= glutGet(GLUT_ELAPSED_TIME
);
103 if (t
- t0
>= 5000) {
104 GLfloat seconds
=(GLfloat
)(t
- t0
) / 1000.0f
;
105 GLfloat fps
= frames
/ seconds
;
106 printf("%d frames in %6.3f seconds = %6.3f FPS\n",
107 frames
, seconds
, fps
);
118 lightPos
[0] += delta
;
119 if (lightPos
[0] > 25.0f
|| lightPos
[0] < -25.0f
)
126 Reshape(int width
, int height
)
128 glViewport(0, 0, width
, height
);
129 glMatrixMode(GL_PROJECTION
);
131 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
132 glMatrixMode(GL_MODELVIEW
);
134 glTranslatef(0.0f
, 0.0f
, -15.0f
);
141 glDeleteShader_func(fragShader
);
142 glDeleteShader_func(vertShader
);
143 glDeleteProgram_func(program
);
144 glutDestroyWindow(win
);
149 Key(unsigned char key
, int x
, int y
)
172 glPolygonMode(GL_FRONT_AND_BACK
, GL_LINE
);
174 glPolygonMode(GL_FRONT_AND_BACK
, GL_FILL
);
177 if (CurList
== SphereList
)
180 CurList
= SphereList
;
183 pixelLight
= !pixelLight
;
185 printf("Per-pixel lighting\n");
187 printf("Conventional lighting\n");
199 SpecialKey(int key
, int x
, int y
)
201 const GLfloat step
= 3.0f
;
227 printf("Error 0x%x at line %d\n", glGetError(), __LINE__
);
230 printf("Error 0x%x at line %d\n", glGetError(), __LINE__
);
231 printf("Light pos %g %g %g\n", pos
[0], pos
[1], pos
[2]);
236 GLfloat m
[16], result
[16];
240 for (i
= 0; i
< 16; i
++)
243 mPos
= glGetUniformLocation_func(program
, "m");
244 printf("Error 0x%x at line %d\n", glGetError(), __LINE__
);
245 glUniformMatrix4fv_func(mPos
, 1, GL_FALSE
, m
);
246 printf("Error 0x%x at line %d\n", glGetError(), __LINE__
);
248 glGetUniformfv_func(program
, mPos
, result
);
249 printf("Error 0x%x at line %d\n", glGetError(), __LINE__
);
251 for (i
= 0; i
< 16; i
++) {
252 printf("%8g %8g\n", m
[i
], result
[i
]);
256 assert(glIsProgram_func(program
));
257 assert(glIsShader_func(fragShader
));
258 assert(glIsShader_func(vertShader
));
260 /* attached shaders */
265 glGetAttachedShaders_func(program
, 20, &count
, shaders
);
266 for (i
= 0; i
< count
; i
++) {
267 printf("Attached: %u\n", shaders
[i
]);
268 assert(shaders
[i
] == fragShader
||
269 shaders
[i
] == vertShader
);
276 glGetShaderInfoLog_func(vertShader
, 1000, &len
, log
);
277 printf("Vert Shader Info Log: %s\n", log
);
278 glGetShaderInfoLog_func(fragShader
, 1000, &len
, log
);
279 printf("Frag Shader Info Log: %s\n", log
);
280 glGetProgramInfoLog_func(program
, 1000, &len
, log
);
281 printf("Program Info Log: %s\n", log
);
292 GLubyte image0
[SZ0
][SZ0
][SZ0
][4];
293 GLubyte image1
[SZ1
][SZ1
][SZ1
][4];
296 /* level 0: two-tone gray checkboard */
297 for (i
= 0; i
< SZ0
; i
++) {
298 for (j
= 0; j
< SZ0
; j
++) {
299 for (k
= 0; k
< SZ0
; k
++) {
300 if ((i
/8 + j
/8 + k
/8) & 1) {
303 image0
[i
][j
][k
][2] = 200;
308 image0
[i
][j
][k
][2] = 100;
310 image0
[i
][j
][k
][3] = 255;
315 /* level 1: two-tone green checkboard */
316 for (i
= 0; i
< SZ1
; i
++) {
317 for (j
= 0; j
< SZ1
; j
++) {
318 for (k
= 0; k
< SZ1
; k
++) {
319 if ((i
/8 + j
/8 + k
/8) & 1) {
320 image1
[i
][j
][k
][0] = 0;
321 image1
[i
][j
][k
][1] = 250;
322 image1
[i
][j
][k
][2] = 0;
325 image1
[i
][j
][k
][0] = 0;
326 image1
[i
][j
][k
][1] = 200;
327 image1
[i
][j
][k
][2] = 0;
329 image1
[i
][j
][k
][3] = 255;
334 glActiveTexture(GL_TEXTURE2
); /* unit 2 */
335 glBindTexture(GL_TEXTURE_2D
, 42);
336 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, SZ0
, SZ0
, 0,
337 GL_RGBA
, GL_UNSIGNED_BYTE
, image0
);
338 glTexImage2D(GL_TEXTURE_2D
, 1, GL_RGBA
, SZ1
, SZ1
, 0,
339 GL_RGBA
, GL_UNSIGNED_BYTE
, image1
);
340 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAX_LEVEL
, 1);
341 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
342 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
344 glActiveTexture(GL_TEXTURE4
); /* unit 4 */
345 glBindTexture(GL_TEXTURE_3D
, 43);
346 glTexImage3D(GL_TEXTURE_3D
, 0, GL_RGBA
, SZ0
, SZ0
, SZ0
, 0,
347 GL_RGBA
, GL_UNSIGNED_BYTE
, image0
);
348 glTexImage3D(GL_TEXTURE_3D
, 1, GL_RGBA
, SZ1
, SZ1
, SZ1
, 0,
349 GL_RGBA
, GL_UNSIGNED_BYTE
, image1
);
350 glTexParameteri(GL_TEXTURE_3D
, GL_TEXTURE_MAX_LEVEL
, 1);
351 glTexParameteri(GL_TEXTURE_3D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
352 glTexParameteri(GL_TEXTURE_3D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
360 GLUquadricObj
*obj
= gluNewQuadric();
361 SphereList
= glGenLists(1);
362 gluQuadricTexture(obj
, GL_TRUE
);
363 glNewList(SphereList
, GL_COMPILE
);
364 gluSphere(obj
, 2.0f
, 10, 5);
369 VertAttrib(GLint index
, float x
, float y
)
372 glVertexAttrib2f_func(index
, x
, y
);
381 RectList
= glGenLists(1);
382 glNewList(RectList
, GL_COMPILE
);
385 VertAttrib(CoordAttrib
, 0, 0); glVertex2f(-2, -2);
386 VertAttrib(CoordAttrib
, 1, 0); glVertex2f( 2, -2);
387 VertAttrib(CoordAttrib
, 1, 1); glVertex2f( 2, 2);
388 VertAttrib(CoordAttrib
, 0, 1); glVertex2f(-2, 2);
389 glEnd(); /* XXX omit this and crash! */
396 LoadAndCompileShader(GLuint shader
, const char *text
)
400 glShaderSource_func(shader
, 1, (const GLchar
**) &text
, NULL
);
402 glCompileShader_func(shader
);
404 glGetShaderiv_func(shader
, GL_COMPILE_STATUS
, &stat
);
408 glGetShaderInfoLog_func(shader
, 1000, &len
, log
);
409 fprintf(stderr
, "fslight: problem compiling shader:\n%s\n", log
);
416 * Read a shader from a file.
419 ReadShader(GLuint shader
, const char *filename
)
421 const int max
= 100*1000;
423 char *buffer
= (char*) malloc(max
);
424 FILE *f
= fopen(filename
, "r");
426 fprintf(stderr
, "fslight: Unable to open shader file %s\n", filename
);
430 n
= fread(buffer
, 1, max
, f
);
431 printf("fslight: read %d bytes from shader file %s\n", n
, filename
);
434 LoadAndCompileShader(shader
, buffer
);
443 CheckLink(GLuint prog
)
446 glGetProgramiv_func(prog
, GL_LINK_STATUS
, &stat
);
450 glGetProgramInfoLog_func(prog
, 1000, &len
, log
);
451 fprintf(stderr
, "Linker error:\n%s\n", log
);
459 static const char *fragShaderText
=
460 "uniform vec4 diffuse;\n"
461 "uniform vec4 specular;\n"
462 "varying vec3 normal;\n"
464 " // Compute dot product of light direction and normal vector\n"
465 " float dotProd = max(dot(gl_LightSource[0].position.xyz, \n"
466 " normalize(normal)), 0.0);\n"
467 " // Compute diffuse and specular contributions\n"
468 " gl_FragColor = diffuse * dotProd + specular * pow(dotProd, 20.0);\n"
470 static const char *vertShaderText
=
471 "varying vec3 normal;\n"
473 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
474 " normal = gl_NormalMatrix * gl_Normal;\n"
478 version
= (const char *) glGetString(GL_VERSION
);
479 if (version
[0] != '2' || version
[1] != '.') {
480 printf("This program requires OpenGL 2.x, found %s\n", version
);
486 fragShader
= glCreateShader_func(GL_FRAGMENT_SHADER
);
488 ReadShader(fragShader
, FragProgFile
);
490 LoadAndCompileShader(fragShader
, fragShaderText
);
493 vertShader
= glCreateShader_func(GL_VERTEX_SHADER
);
495 ReadShader(vertShader
, VertProgFile
);
497 LoadAndCompileShader(vertShader
, vertShaderText
);
499 program
= glCreateProgram_func();
500 glAttachShader_func(program
, fragShader
);
501 glAttachShader_func(program
, vertShader
);
502 glLinkProgram_func(program
);
504 glUseProgram_func(program
);
506 uDiffuse
= glGetUniformLocation_func(program
, "diffuse");
507 uSpecular
= glGetUniformLocation_func(program
, "specular");
508 uTexture
= glGetUniformLocation_func(program
, "texture");
509 printf("DiffusePos %d SpecularPos %d TexturePos %d\n",
510 uDiffuse
, uSpecular
, uTexture
);
512 glUniform4fv_func(uDiffuse
, 1, diffuse
);
513 glUniform4fv_func(uSpecular
, 1, specular
);
514 /* assert(glGetError() == 0);*/
515 glUniform1i_func(uTexture
, 2); /* use texture unit 2 */
516 /*assert(glGetError() == 0);*/
520 glBindAttribLocation_func(program
, CoordAttrib
, "coord");
521 i
= glGetAttribLocation_func(program
, "coord");
523 if (i
!= CoordAttrib
) {
524 printf("Hmmm, NVIDIA bug?\n");
528 printf("Mesa bind attrib: coord = %d\n", i
);
532 /*assert(glGetError() == 0);*/
534 glClearColor(0.3f
, 0.3f
, 0.3f
, 0.0f
);
535 glEnable(GL_DEPTH_TEST
);
537 glEnable(GL_LIGHTING
);
538 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, diffuse
);
539 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, specular
);
540 glMaterialf(GL_FRONT_AND_BACK
, GL_SHININESS
, 20.0f
);
545 CurList
= SphereList
;
551 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER
));
552 printf("Press p to toggle between per-pixel and per-vertex lighting\n");
554 /* test glGetShaderSource() */
556 GLsizei len
= strlen(fragShaderText
) + 1;
558 GLchar
*src
=(GLchar
*) malloc(len
* sizeof(GLchar
));
559 glGetShaderSource_func(fragShader
, 0, NULL
, src
);
560 glGetShaderSource_func(fragShader
, len
, &lenOut
, src
);
561 assert(len
== lenOut
+ 1);
562 assert(strcmp(src
, fragShaderText
) == 0);
566 assert(glIsProgram_func(program
));
567 assert(glIsShader_func(fragShader
));
568 assert(glIsShader_func(vertShader
));
572 /* for testing state vars */
574 static GLfloat fc
[4] = { 1, 1, 0, 0 };
575 static GLfloat amb
[4] = { 1, 0, 1, 0 };
576 glFogfv(GL_FOG_COLOR
, fc
);
577 glLightfv(GL_LIGHT1
, GL_AMBIENT
, amb
);
583 (void) TestFunctions
;
589 ParseOptions(int argc
, char *argv
[])
592 for (i
= 1; i
< argc
; i
++) {
593 if (strcmp(argv
[i
], "-fs") == 0) {
594 FragProgFile
= argv
[i
+1];
596 else if (strcmp(argv
[i
], "-vs") == 0) {
597 VertProgFile
= argv
[i
+1];
604 main(int argc
, char *argv
[])
606 glutInit(&argc
, argv
);
607 glutInitWindowPosition( 0, 0);
608 glutInitWindowSize(200, 200);
609 glutInitDisplayMode(GLUT_RGB
| GLUT_DOUBLE
| GLUT_DEPTH
);
610 win
= glutCreateWindow(argv
[0]);
611 glutReshapeFunc(Reshape
);
612 glutKeyboardFunc(Key
);
613 glutSpecialFunc(SpecialKey
);
614 glutDisplayFunc(Redisplay
);
617 ParseOptions(argc
, argv
);