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
);
119 lightPos
[0] += delta
;
120 if (lightPos
[0] > 25.0f
|| lightPos
[0] < -25.0f
)
127 Reshape(int width
, int height
)
129 glViewport(0, 0, width
, height
);
130 glMatrixMode(GL_PROJECTION
);
132 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
133 glMatrixMode(GL_MODELVIEW
);
135 glTranslatef(0.0f
, 0.0f
, -15.0f
);
142 glDeleteShader_func(fragShader
);
143 glDeleteShader_func(vertShader
);
144 glDeleteProgram_func(program
);
145 glutDestroyWindow(win
);
150 Key(unsigned char key
, int x
, int y
)
173 glPolygonMode(GL_FRONT_AND_BACK
, GL_LINE
);
175 glPolygonMode(GL_FRONT_AND_BACK
, GL_FILL
);
178 if (CurList
== SphereList
)
181 CurList
= SphereList
;
184 pixelLight
= !pixelLight
;
186 printf("Per-pixel lighting\n");
188 printf("Conventional lighting\n");
200 SpecialKey(int key
, int x
, int y
)
202 const GLfloat step
= 3.0f
;
228 printf("Error 0x%x at line %d\n", glGetError(), __LINE__
);
230 assert(glIsProgram_func(program
));
231 assert(glIsShader_func(fragShader
));
232 assert(glIsShader_func(vertShader
));
234 /* attached shaders */
239 glGetAttachedShaders_func(program
, 20, &count
, shaders
);
240 for (i
= 0; i
< count
; i
++) {
241 printf("Attached: %u\n", shaders
[i
]);
242 assert(shaders
[i
] == fragShader
||
243 shaders
[i
] == vertShader
);
250 glGetShaderInfoLog_func(vertShader
, 1000, &len
, log
);
251 printf("Vert Shader Info Log: %s\n", log
);
252 glGetShaderInfoLog_func(fragShader
, 1000, &len
, log
);
253 printf("Frag Shader Info Log: %s\n", log
);
254 glGetProgramInfoLog_func(program
, 1000, &len
, log
);
255 printf("Program Info Log: %s\n", log
);
258 /* active uniforms */
261 glGetProgramiv_func(program
, GL_ACTIVE_UNIFORMS
, &n
);
262 glGetProgramiv_func(program
, GL_ACTIVE_UNIFORM_MAX_LENGTH
, &max
);
263 printf("Num uniforms: %d Max name length: %d\n", n
, max
);
264 for (i
= 0; i
< n
; i
++) {
268 glGetActiveUniform_func(program
, i
, 100, &len
, &size
, &type
, name
);
269 printf(" %d: %s nameLen=%d size=%d type=0x%x\n",
270 i
, name
, len
, size
, type
);
282 GLubyte image0
[SZ0
][SZ0
][SZ0
][4];
283 GLubyte image1
[SZ1
][SZ1
][SZ1
][4];
286 /* level 0: two-tone gray checkboard */
287 for (i
= 0; i
< SZ0
; i
++) {
288 for (j
= 0; j
< SZ0
; j
++) {
289 for (k
= 0; k
< SZ0
; k
++) {
290 if ((i
/8 + j
/8 + k
/8) & 1) {
293 image0
[i
][j
][k
][2] = 200;
298 image0
[i
][j
][k
][2] = 100;
300 image0
[i
][j
][k
][3] = 255;
305 /* level 1: two-tone green checkboard */
306 for (i
= 0; i
< SZ1
; i
++) {
307 for (j
= 0; j
< SZ1
; j
++) {
308 for (k
= 0; k
< SZ1
; k
++) {
309 if ((i
/8 + j
/8 + k
/8) & 1) {
310 image1
[i
][j
][k
][0] = 0;
311 image1
[i
][j
][k
][1] = 250;
312 image1
[i
][j
][k
][2] = 0;
315 image1
[i
][j
][k
][0] = 0;
316 image1
[i
][j
][k
][1] = 200;
317 image1
[i
][j
][k
][2] = 0;
319 image1
[i
][j
][k
][3] = 255;
324 glActiveTexture(GL_TEXTURE2
); /* unit 2 */
325 glBindTexture(GL_TEXTURE_2D
, 42);
326 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, SZ0
, SZ0
, 0,
327 GL_RGBA
, GL_UNSIGNED_BYTE
, image0
);
328 glTexImage2D(GL_TEXTURE_2D
, 1, GL_RGBA
, SZ1
, SZ1
, 0,
329 GL_RGBA
, GL_UNSIGNED_BYTE
, image1
);
330 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAX_LEVEL
, 1);
331 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
332 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
334 glActiveTexture(GL_TEXTURE4
); /* unit 4 */
335 glBindTexture(GL_TEXTURE_3D
, 43);
336 glTexImage3D(GL_TEXTURE_3D
, 0, GL_RGBA
, SZ0
, SZ0
, SZ0
, 0,
337 GL_RGBA
, GL_UNSIGNED_BYTE
, image0
);
338 glTexImage3D(GL_TEXTURE_3D
, 1, GL_RGBA
, SZ1
, SZ1
, SZ1
, 0,
339 GL_RGBA
, GL_UNSIGNED_BYTE
, image1
);
340 glTexParameteri(GL_TEXTURE_3D
, GL_TEXTURE_MAX_LEVEL
, 1);
341 glTexParameteri(GL_TEXTURE_3D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
342 glTexParameteri(GL_TEXTURE_3D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
350 GLUquadricObj
*obj
= gluNewQuadric();
351 SphereList
= glGenLists(1);
352 gluQuadricTexture(obj
, GL_TRUE
);
353 glNewList(SphereList
, GL_COMPILE
);
354 gluSphere(obj
, 2.0f
, 10, 5);
359 VertAttrib(GLint index
, float x
, float y
)
362 glVertexAttrib2f_func(index
, x
, y
);
371 RectList
= glGenLists(1);
372 glNewList(RectList
, GL_COMPILE
);
375 VertAttrib(CoordAttrib
, 0, 0); glVertex2f(-2, -2);
376 VertAttrib(CoordAttrib
, 1, 0); glVertex2f( 2, -2);
377 VertAttrib(CoordAttrib
, 1, 1); glVertex2f( 2, 2);
378 VertAttrib(CoordAttrib
, 0, 1); glVertex2f(-2, 2);
379 glEnd(); /* XXX omit this and crash! */
386 LoadAndCompileShader(GLuint shader
, const char *text
)
390 glShaderSource_func(shader
, 1, (const GLchar
**) &text
, NULL
);
392 glCompileShader_func(shader
);
394 glGetShaderiv_func(shader
, GL_COMPILE_STATUS
, &stat
);
398 glGetShaderInfoLog_func(shader
, 1000, &len
, log
);
399 fprintf(stderr
, "fslight: problem compiling shader:\n%s\n", log
);
406 * Read a shader from a file.
409 ReadShader(GLuint shader
, const char *filename
)
411 const int max
= 100*1000;
413 char *buffer
= (char*) malloc(max
);
414 FILE *f
= fopen(filename
, "r");
416 fprintf(stderr
, "fslight: Unable to open shader file %s\n", filename
);
420 n
= fread(buffer
, 1, max
, f
);
421 printf("fslight: read %d bytes from shader file %s\n", n
, filename
);
424 LoadAndCompileShader(shader
, buffer
);
433 CheckLink(GLuint prog
)
436 glGetProgramiv_func(prog
, GL_LINK_STATUS
, &stat
);
440 glGetProgramInfoLog_func(prog
, 1000, &len
, log
);
441 fprintf(stderr
, "Linker error:\n%s\n", log
);
449 static const char *fragShaderText
=
450 "uniform vec4 diffuse;\n"
451 "uniform vec4 specular;\n"
452 "varying vec3 normal;\n"
454 " // Compute dot product of light direction and normal vector\n"
455 " float dotProd = max(dot(gl_LightSource[0].position.xyz, \n"
456 " normalize(normal)), 0.0);\n"
457 " // Compute diffuse and specular contributions\n"
458 " gl_FragColor = diffuse * dotProd + specular * pow(dotProd, 20.0);\n"
460 static const char *vertShaderText
=
461 "varying vec3 normal;\n"
463 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
464 " normal = gl_NormalMatrix * gl_Normal;\n"
468 version
= (const char *) glGetString(GL_VERSION
);
469 if (version
[0] != '2' || version
[1] != '.') {
470 printf("This program requires OpenGL 2.x, found %s\n", version
);
476 fragShader
= glCreateShader_func(GL_FRAGMENT_SHADER
);
478 ReadShader(fragShader
, FragProgFile
);
480 LoadAndCompileShader(fragShader
, fragShaderText
);
483 vertShader
= glCreateShader_func(GL_VERTEX_SHADER
);
485 ReadShader(vertShader
, VertProgFile
);
487 LoadAndCompileShader(vertShader
, vertShaderText
);
489 program
= glCreateProgram_func();
490 glAttachShader_func(program
, fragShader
);
491 glAttachShader_func(program
, vertShader
);
492 glLinkProgram_func(program
);
494 glUseProgram_func(program
);
496 uDiffuse
= glGetUniformLocation_func(program
, "diffuse");
497 uSpecular
= glGetUniformLocation_func(program
, "specular");
498 uTexture
= glGetUniformLocation_func(program
, "texture");
499 printf("DiffusePos %d SpecularPos %d TexturePos %d\n",
500 uDiffuse
, uSpecular
, uTexture
);
502 glUniform4fv_func(uDiffuse
, 1, diffuse
);
503 glUniform4fv_func(uSpecular
, 1, specular
);
504 /* assert(glGetError() == 0);*/
506 glUniform1i_func(uTexture
, 2); /* use texture unit 2 */
508 /*assert(glGetError() == 0);*/
512 glBindAttribLocation_func(program
, CoordAttrib
, "coord");
513 i
= glGetAttribLocation_func(program
, "coord");
515 if (i
!= CoordAttrib
) {
516 printf("Hmmm, NVIDIA bug?\n");
520 printf("Mesa bind attrib: coord = %d\n", i
);
524 /*assert(glGetError() == 0);*/
526 glClearColor(0.3f
, 0.3f
, 0.3f
, 0.0f
);
527 glEnable(GL_DEPTH_TEST
);
529 glEnable(GL_LIGHTING
);
530 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, diffuse
);
531 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, specular
);
532 glMaterialf(GL_FRONT_AND_BACK
, GL_SHININESS
, 20.0f
);
537 CurList
= SphereList
;
543 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER
));
544 printf("Press p to toggle between per-pixel and per-vertex lighting\n");
546 /* test glGetShaderSource() */
548 GLsizei len
= strlen(fragShaderText
) + 1;
550 GLchar
*src
=(GLchar
*) malloc(len
* sizeof(GLchar
));
551 glGetShaderSource_func(fragShader
, 0, NULL
, src
);
552 glGetShaderSource_func(fragShader
, len
, &lenOut
, src
);
553 assert(len
== lenOut
+ 1);
554 assert(strcmp(src
, fragShaderText
) == 0);
558 assert(glIsProgram_func(program
));
559 assert(glIsShader_func(fragShader
));
560 assert(glIsShader_func(vertShader
));
564 /* for testing state vars */
566 static GLfloat fc
[4] = { 1, 1, 0, 0 };
567 static GLfloat amb
[4] = { 1, 0, 1, 0 };
568 glFogfv(GL_FOG_COLOR
, fc
);
569 glLightfv(GL_LIGHT1
, GL_AMBIENT
, amb
);
575 (void) TestFunctions
;
581 ParseOptions(int argc
, char *argv
[])
584 for (i
= 1; i
< argc
; i
++) {
585 if (strcmp(argv
[i
], "-fs") == 0) {
586 FragProgFile
= argv
[++i
];
588 else if (strcmp(argv
[i
], "-vs") == 0) {
589 VertProgFile
= argv
[++i
];
592 fprintf(stderr
, "unknown option %s\n", argv
[i
]);
600 main(int argc
, char *argv
[])
602 glutInit(&argc
, argv
);
603 glutInitWindowPosition( 0, 0);
604 glutInitWindowSize(200, 200);
605 glutInitDisplayMode(GLUT_RGB
| GLUT_DOUBLE
| GLUT_DEPTH
);
606 win
= glutCreateWindow(argv
[0]);
607 glutReshapeFunc(Reshape
);
608 glutKeyboardFunc(Key
);
609 glutSpecialFunc(SpecialKey
);
610 glutDisplayFunc(Redisplay
);
613 ParseOptions(argc
, argv
);