2 * Test OpenGL 2.0 vertex/fragment shaders.
6 * Based on ARB version by:
10 * Based on the original demo by:
21 #include "glut_wrap.h"
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
;
46 static GLboolean anim
= GL_TRUE
;
47 static GLboolean wire
= GL_FALSE
;
48 static GLboolean pixelLight
= GL_TRUE
;
51 static GLint frames
= 0;
53 static GLfloat xRot
= 90.0f
, yRot
= 0.0f
;
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
;
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
);
79 glUseProgram(program
);
80 glDisable(GL_LIGHTING
);
84 glEnable(GL_LIGHTING
);
88 glRotatef(xRot
, 1.0f
, 0.0f
, 0.0f
);
89 glRotatef(yRot
, 0.0f
, 1.0f
, 0.0f
);
91 glutSolidSphere(2.0, 10, 5);
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
);
117 lightPos
[0] += delta
;
118 if (lightPos
[0] > 25.0f
|| lightPos
[0] < -25.0f
)
125 Reshape(int width
, int height
)
127 glViewport(0, 0, width
, height
);
128 glMatrixMode(GL_PROJECTION
);
130 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
131 glMatrixMode(GL_MODELVIEW
);
133 glTranslatef(0.0f
, 0.0f
, -15.0f
);
140 glDeleteShader(fragShader
);
141 glDeleteShader(vertShader
);
142 glDeleteProgram(program
);
143 glutDestroyWindow(win
);
148 Key(unsigned char key
, int x
, int y
)
171 glPolygonMode(GL_FRONT_AND_BACK
, GL_LINE
);
173 glPolygonMode(GL_FRONT_AND_BACK
, GL_FILL
);
176 if (CurList
== SphereList
)
179 CurList
= SphereList
;
182 pixelLight
= !pixelLight
;
184 printf("Per-pixel lighting\n");
186 printf("Conventional lighting\n");
198 SpecialKey(int key
, int x
, int y
)
200 const GLfloat step
= 3.0f
;
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 */
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
);
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 */
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
++) {
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
);
280 GLubyte image0
[SZ0
][SZ0
][SZ0
][4];
281 GLubyte image1
[SZ1
][SZ1
][SZ1
][4];
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) {
291 image0
[i
][j
][k
][2] = 200;
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;
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
);
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);
354 gluDeleteQuadric(obj
);
358 VertAttrib(GLint index
, float x
, float y
)
361 glVertexAttrib2f(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(shader
, 1, (const GLchar
**) &text
, NULL
);
391 glCompileShader(shader
);
393 glGetShaderiv(shader
, GL_COMPILE_STATUS
, &stat
);
397 glGetShaderInfoLog(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(prog
, GL_LINK_STATUS
, &stat
);
439 glGetProgramInfoLog(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"
466 if (!GLEW_VERSION_2_0
) {
467 printf("This program requires OpenGL 2.x or higher\n");
471 fragShader
= glCreateShader(GL_FRAGMENT_SHADER
);
473 ReadShader(fragShader
, FragProgFile
);
475 LoadAndCompileShader(fragShader
, fragShaderText
);
478 vertShader
= glCreateShader(GL_VERTEX_SHADER
);
480 ReadShader(vertShader
, VertProgFile
);
482 LoadAndCompileShader(vertShader
, vertShaderText
);
484 program
= glCreateProgram();
485 glAttachShader(program
, fragShader
);
486 glAttachShader(program
, vertShader
);
487 glLinkProgram(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);*/
501 glUniform1i(uTexture
, 2); /* use texture unit 2 */
503 /*assert(glGetError() == 0);*/
507 glBindAttribLocation(program
, CoordAttrib
, "coord");
508 i
= glGetAttribLocation(program
, "coord");
510 if (i
!= CoordAttrib
) {
511 printf("Hmmm, NVIDIA bug?\n");
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
);
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
);
532 CurList
= SphereList
;
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() */
543 GLsizei len
= strlen(fragShaderText
) + 1;
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);
553 assert(glIsProgram(program
));
554 assert(glIsShader(fragShader
));
555 assert(glIsShader(vertShader
));
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
);
570 (void) TestFunctions
;
576 ParseOptions(int argc
, char *argv
[])
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
];
587 fprintf(stderr
, "unknown option %s\n", argv
[i
]);
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]);
602 glutReshapeFunc(Reshape
);
603 glutKeyboardFunc(Key
);
604 glutSpecialFunc(SpecialKey
);
605 glutDisplayFunc(Redisplay
);
608 ParseOptions(argc
, argv
);