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__
);
229 assert(glIsProgram_func(program
));
230 assert(glIsShader_func(fragShader
));
231 assert(glIsShader_func(vertShader
));
233 /* attached shaders */
238 glGetAttachedShaders_func(program
, 20, &count
, shaders
);
239 for (i
= 0; i
< count
; i
++) {
240 printf("Attached: %u\n", shaders
[i
]);
241 assert(shaders
[i
] == fragShader
||
242 shaders
[i
] == vertShader
);
249 glGetShaderInfoLog_func(vertShader
, 1000, &len
, log
);
250 printf("Vert Shader Info Log: %s\n", log
);
251 glGetShaderInfoLog_func(fragShader
, 1000, &len
, log
);
252 printf("Frag Shader Info Log: %s\n", log
);
253 glGetProgramInfoLog_func(program
, 1000, &len
, log
);
254 printf("Program Info Log: %s\n", log
);
257 /* active uniforms */
260 glGetProgramiv_func(program
, GL_ACTIVE_UNIFORMS
, &n
);
261 glGetProgramiv_func(program
, GL_ACTIVE_UNIFORM_MAX_LENGTH
, &max
);
262 printf("Num uniforms: %d Max name length: %d\n", n
, max
);
263 for (i
= 0; i
< n
; i
++) {
267 glGetActiveUniform_func(program
, i
, 100, &len
, &size
, &type
, name
);
268 printf(" %d: %s nameLen=%d size=%d type=0x%x\n",
269 i
, name
, len
, size
, type
);
281 GLubyte image0
[SZ0
][SZ0
][SZ0
][4];
282 GLubyte image1
[SZ1
][SZ1
][SZ1
][4];
285 /* level 0: two-tone gray checkboard */
286 for (i
= 0; i
< SZ0
; i
++) {
287 for (j
= 0; j
< SZ0
; j
++) {
288 for (k
= 0; k
< SZ0
; k
++) {
289 if ((i
/8 + j
/8 + k
/8) & 1) {
292 image0
[i
][j
][k
][2] = 200;
297 image0
[i
][j
][k
][2] = 100;
299 image0
[i
][j
][k
][3] = 255;
304 /* level 1: two-tone green checkboard */
305 for (i
= 0; i
< SZ1
; i
++) {
306 for (j
= 0; j
< SZ1
; j
++) {
307 for (k
= 0; k
< SZ1
; k
++) {
308 if ((i
/8 + j
/8 + k
/8) & 1) {
309 image1
[i
][j
][k
][0] = 0;
310 image1
[i
][j
][k
][1] = 250;
311 image1
[i
][j
][k
][2] = 0;
314 image1
[i
][j
][k
][0] = 0;
315 image1
[i
][j
][k
][1] = 200;
316 image1
[i
][j
][k
][2] = 0;
318 image1
[i
][j
][k
][3] = 255;
323 glActiveTexture(GL_TEXTURE2
); /* unit 2 */
324 glBindTexture(GL_TEXTURE_2D
, 42);
325 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, SZ0
, SZ0
, 0,
326 GL_RGBA
, GL_UNSIGNED_BYTE
, image0
);
327 glTexImage2D(GL_TEXTURE_2D
, 1, GL_RGBA
, SZ1
, SZ1
, 0,
328 GL_RGBA
, GL_UNSIGNED_BYTE
, image1
);
329 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAX_LEVEL
, 1);
330 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
331 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
333 glActiveTexture(GL_TEXTURE4
); /* unit 4 */
334 glBindTexture(GL_TEXTURE_3D
, 43);
335 glTexImage3D(GL_TEXTURE_3D
, 0, GL_RGBA
, SZ0
, SZ0
, SZ0
, 0,
336 GL_RGBA
, GL_UNSIGNED_BYTE
, image0
);
337 glTexImage3D(GL_TEXTURE_3D
, 1, GL_RGBA
, SZ1
, SZ1
, SZ1
, 0,
338 GL_RGBA
, GL_UNSIGNED_BYTE
, image1
);
339 glTexParameteri(GL_TEXTURE_3D
, GL_TEXTURE_MAX_LEVEL
, 1);
340 glTexParameteri(GL_TEXTURE_3D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
341 glTexParameteri(GL_TEXTURE_3D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
349 GLUquadricObj
*obj
= gluNewQuadric();
350 SphereList
= glGenLists(1);
351 gluQuadricTexture(obj
, GL_TRUE
);
352 glNewList(SphereList
, GL_COMPILE
);
353 gluSphere(obj
, 2.0f
, 10, 5);
358 VertAttrib(GLint index
, float x
, float y
)
361 glVertexAttrib2f_func(index
, x
, y
);
370 RectList
= glGenLists(1);
371 glNewList(RectList
, GL_COMPILE
);
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! */
385 LoadAndCompileShader(GLuint shader
, const char *text
)
389 glShaderSource_func(shader
, 1, (const GLchar
**) &text
, NULL
);
391 glCompileShader_func(shader
);
393 glGetShaderiv_func(shader
, GL_COMPILE_STATUS
, &stat
);
397 glGetShaderInfoLog_func(shader
, 1000, &len
, log
);
398 fprintf(stderr
, "fslight: problem compiling shader:\n%s\n", log
);
405 * Read a shader from a file.
408 ReadShader(GLuint shader
, const char *filename
)
410 const int max
= 100*1000;
412 char *buffer
= (char*) malloc(max
);
413 FILE *f
= fopen(filename
, "r");
415 fprintf(stderr
, "fslight: Unable to open shader file %s\n", filename
);
419 n
= fread(buffer
, 1, max
, f
);
420 printf("fslight: read %d bytes from shader file %s\n", n
, filename
);
423 LoadAndCompileShader(shader
, buffer
);
432 CheckLink(GLuint prog
)
435 glGetProgramiv_func(prog
, GL_LINK_STATUS
, &stat
);
439 glGetProgramInfoLog_func(prog
, 1000, &len
, log
);
440 fprintf(stderr
, "Linker error:\n%s\n", log
);
448 static const char *fragShaderText
=
449 "uniform vec4 diffuse;\n"
450 "uniform vec4 specular;\n"
451 "varying vec3 normal;\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"
459 static const char *vertShaderText
=
460 "varying vec3 normal;\n"
462 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
463 " normal = gl_NormalMatrix * gl_Normal;\n"
467 version
= (const char *) glGetString(GL_VERSION
);
468 if (version
[0] != '2' || version
[1] != '.') {
469 printf("This program requires OpenGL 2.x, found %s\n", version
);
475 fragShader
= glCreateShader_func(GL_FRAGMENT_SHADER
);
477 ReadShader(fragShader
, FragProgFile
);
479 LoadAndCompileShader(fragShader
, fragShaderText
);
482 vertShader
= glCreateShader_func(GL_VERTEX_SHADER
);
484 ReadShader(vertShader
, VertProgFile
);
486 LoadAndCompileShader(vertShader
, vertShaderText
);
488 program
= glCreateProgram_func();
489 glAttachShader_func(program
, fragShader
);
490 glAttachShader_func(program
, vertShader
);
491 glLinkProgram_func(program
);
493 glUseProgram_func(program
);
495 uDiffuse
= glGetUniformLocation_func(program
, "diffuse");
496 uSpecular
= glGetUniformLocation_func(program
, "specular");
497 uTexture
= glGetUniformLocation_func(program
, "texture");
498 printf("DiffusePos %d SpecularPos %d TexturePos %d\n",
499 uDiffuse
, uSpecular
, uTexture
);
501 glUniform4fv_func(uDiffuse
, 1, diffuse
);
502 glUniform4fv_func(uSpecular
, 1, specular
);
503 /* assert(glGetError() == 0);*/
505 glUniform1i_func(uTexture
, 2); /* use texture unit 2 */
507 /*assert(glGetError() == 0);*/
511 glBindAttribLocation_func(program
, CoordAttrib
, "coord");
512 i
= glGetAttribLocation_func(program
, "coord");
514 if (i
!= CoordAttrib
) {
515 printf("Hmmm, NVIDIA bug?\n");
519 printf("Mesa bind attrib: coord = %d\n", i
);
523 /*assert(glGetError() == 0);*/
525 glClearColor(0.3f
, 0.3f
, 0.3f
, 0.0f
);
526 glEnable(GL_DEPTH_TEST
);
528 glEnable(GL_LIGHTING
);
529 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, diffuse
);
530 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, specular
);
531 glMaterialf(GL_FRONT_AND_BACK
, GL_SHININESS
, 20.0f
);
536 CurList
= SphereList
;
542 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER
));
543 printf("Press p to toggle between per-pixel and per-vertex lighting\n");
545 /* test glGetShaderSource() */
547 GLsizei len
= strlen(fragShaderText
) + 1;
549 GLchar
*src
=(GLchar
*) malloc(len
* sizeof(GLchar
));
550 glGetShaderSource_func(fragShader
, 0, NULL
, src
);
551 glGetShaderSource_func(fragShader
, len
, &lenOut
, src
);
552 assert(len
== lenOut
+ 1);
553 assert(strcmp(src
, fragShaderText
) == 0);
557 assert(glIsProgram_func(program
));
558 assert(glIsShader_func(fragShader
));
559 assert(glIsShader_func(vertShader
));
563 /* for testing state vars */
565 static GLfloat fc
[4] = { 1, 1, 0, 0 };
566 static GLfloat amb
[4] = { 1, 0, 1, 0 };
567 glFogfv(GL_FOG_COLOR
, fc
);
568 glLightfv(GL_LIGHT1
, GL_AMBIENT
, amb
);
574 (void) TestFunctions
;
580 ParseOptions(int argc
, char *argv
[])
583 for (i
= 1; i
< argc
; i
++) {
584 if (strcmp(argv
[i
], "-fs") == 0) {
585 FragProgFile
= argv
[i
+1];
587 else if (strcmp(argv
[i
], "-vs") == 0) {
588 VertProgFile
= argv
[i
+1];
595 main(int argc
, char *argv
[])
597 glutInit(&argc
, argv
);
598 glutInitWindowPosition( 0, 0);
599 glutInitWindowSize(200, 200);
600 glutInitDisplayMode(GLUT_RGB
| GLUT_DOUBLE
| GLUT_DEPTH
);
601 win
= glutCreateWindow(argv
[0]);
602 glutReshapeFunc(Reshape
);
603 glutKeyboardFunc(Key
);
604 glutSpecialFunc(SpecialKey
);
605 glutDisplayFunc(Redisplay
);
608 ParseOptions(argc
, argv
);