2 * Test OpenGL 2.0 vertex/fragment shaders.
6 * Based on ARB version by:
10 * Based on the original demo by:
25 static char *FragProgFile
= NULL
;
26 static char *VertProgFile
= NULL
;
28 static GLfloat diffuse
[4] = { 0.5f
, 0.5f
, 1.0f
, 1.0f
};
29 static GLfloat specular
[4] = { 0.8f
, 0.8f
, 0.8f
, 1.0f
};
30 static GLfloat lightPos
[4] = { 0.0f
, 10.0f
, 20.0f
, 1.0f
};
31 static GLfloat delta
= 1.0f
;
33 static GLuint fragShader
;
34 static GLuint vertShader
;
35 static GLuint program
;
37 static GLint uLightPos
;
38 static GLint uDiffuse
;
39 static GLint uSpecular
;
42 static GLboolean anim
= GL_FALSE
;
43 static GLboolean wire
= GL_FALSE
;
44 static GLboolean pixelLight
= GL_TRUE
;
47 static GLint frames
= 0;
49 static GLfloat xRot
= 0.0f
, yRot
= 0.0f
;
53 normalize(GLfloat
*dst
, const GLfloat
*src
)
55 GLfloat len
= sqrtf(src
[0] * src
[0] + src
[1] * src
[1] + src
[2] * src
[2]);
56 dst
[0] = src
[0] / len
;
57 dst
[1] = src
[1] / len
;
58 dst
[2] = src
[2] / len
;
65 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
69 glUseProgram_func(program
);
70 normalize(vec
, lightPos
);
71 glUniform3fv_func(uLightPos
, 1, vec
);
72 glDisable(GL_LIGHTING
);
76 glLightfv(GL_LIGHT0
, GL_POSITION
, lightPos
);
77 glEnable(GL_LIGHTING
);
81 glRotatef(xRot
, 1.0f
, 0.0f
, 0.0f
);
82 glRotatef(yRot
, 0.0f
, 1.0f
, 0.0f
);
83 glutSolidSphere(2.0, 10, 5);
90 GLint t
= glutGet(GLUT_ELAPSED_TIME
);
92 GLfloat seconds
=(GLfloat
)(t
- t0
) / 1000.0f
;
93 GLfloat fps
= frames
/ seconds
;
94 printf("%d frames in %6.3f seconds = %6.3f FPS\n",
95 frames
, seconds
, fps
);
106 lightPos
[0] += delta
;
107 if (lightPos
[0] > 25.0f
|| lightPos
[0] < -25.0f
)
114 Reshape(int width
, int height
)
116 glViewport(0, 0, width
, height
);
117 glMatrixMode(GL_PROJECTION
);
119 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
120 glMatrixMode(GL_MODELVIEW
);
122 glTranslatef(0.0f
, 0.0f
, -15.0f
);
129 glDeleteShader_func(fragShader
);
130 glDeleteShader_func(vertShader
);
131 glDeleteProgram_func(program
);
132 glutDestroyWindow(win
);
137 Key(unsigned char key
, int x
, int y
)
160 glPolygonMode(GL_FRONT_AND_BACK
, GL_LINE
);
162 glPolygonMode(GL_FRONT_AND_BACK
, GL_FILL
);
165 pixelLight
= !pixelLight
;
167 printf("Per-pixel lighting\n");
169 printf("Conventional lighting\n");
181 SpecialKey(int key
, int x
, int y
)
183 const GLfloat step
= 3.0f
;
209 printf("Error 0x%x at line %d\n", glGetError(), __LINE__
);
212 glUniform3fv_func(uLightPos
, 1, lightPos
);
213 glGetUniformfv_func(program
, uLightPos
, pos
);
214 printf("Error 0x%x at line %d\n", glGetError(), __LINE__
);
215 printf("Light pos %g %g %g\n", pos
[0], pos
[1], pos
[2]);
220 GLfloat m
[16], result
[16];
224 for (i
= 0; i
< 16; i
++)
227 mPos
= glGetUniformLocation_func(program
, "m");
228 printf("Error 0x%x at line %d\n", glGetError(), __LINE__
);
229 glUniformMatrix4fv_func(mPos
, 1, GL_FALSE
, m
);
230 printf("Error 0x%x at line %d\n", glGetError(), __LINE__
);
232 glGetUniformfv_func(program
, mPos
, result
);
233 printf("Error 0x%x at line %d\n", glGetError(), __LINE__
);
235 for (i
= 0; i
< 16; i
++) {
236 printf("%8g %8g\n", m
[i
], result
[i
]);
240 assert(glIsProgram_func(program
));
241 assert(glIsShader_func(fragShader
));
242 assert(glIsShader_func(vertShader
));
244 /* attached shaders */
249 glGetAttachedShaders_func(program
, 20, &count
, shaders
);
250 for (i
= 0; i
< count
; i
++) {
251 printf("Attached: %u\n", shaders
[i
]);
252 assert(shaders
[i
] == fragShader
||
253 shaders
[i
] == vertShader
);
260 glGetShaderInfoLog_func(vertShader
, 1000, &len
, log
);
261 printf("Vert Shader Info Log: %s\n", log
);
262 glGetShaderInfoLog_func(fragShader
, 1000, &len
, log
);
263 printf("Frag Shader Info Log: %s\n", log
);
264 glGetProgramInfoLog_func(program
, 1000, &len
, log
);
265 printf("Program Info Log: %s\n", log
);
271 LoadAndCompileShader(GLuint shader
, const char *text
)
275 glShaderSource_func(shader
, 1, (const GLchar
**) &text
, NULL
);
277 glCompileShader_func(shader
);
279 glGetShaderiv_func(shader
, GL_COMPILE_STATUS
, &stat
);
283 glGetShaderInfoLog_func(shader
, 1000, &len
, log
);
284 fprintf(stderr
, "Problem compiling shader: %s\n", log
);
291 * Read a shader from a file.
294 ReadShader(GLuint shader
, const char *filename
)
296 const int max
= 100*1000;
298 char *buffer
= (char*) malloc(max
);
299 FILE *f
= fopen(filename
, "r");
301 fprintf(stderr
, "Unable to open shader file %s\n", filename
);
305 n
= fread(buffer
, 1, max
, f
);
306 printf("Read %d bytes from shader file %s\n", n
, filename
);
309 LoadAndCompileShader(shader
, buffer
);
318 CheckLink(GLuint prog
)
321 glGetProgramiv_func(prog
, GL_LINK_STATUS
, &stat
);
325 glGetProgramInfoLog_func(prog
, 1000, &len
, log
);
326 fprintf(stderr
, "Linker error:\n%s\n", log
);
334 static const char *fragShaderText
=
335 "uniform vec3 lightPos;\n"
336 "uniform vec4 diffuse;\n"
337 "uniform vec4 specular;\n"
338 "varying vec3 normal;\n"
340 " // Compute dot product of light direction and normal vector\n"
341 " float dotProd = max(dot(lightPos, normalize(normal)), 0.0);\n"
342 " // Compute diffuse and specular contributions\n"
343 " gl_FragColor = diffuse * dotProd + specular * pow(dotProd, 20.0);\n"
345 static const char *vertShaderText
=
346 "varying vec3 normal;\n"
348 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
349 " normal = gl_NormalMatrix * gl_Normal;\n"
353 version
= (const char *) glGetString(GL_VERSION
);
354 if (version
[0] != '2' || version
[1] != '.') {
355 printf("Warning: this program expects OpenGL 2.0\n");
361 fragShader
= glCreateShader_func(GL_FRAGMENT_SHADER
);
363 ReadShader(fragShader
, FragProgFile
);
365 LoadAndCompileShader(fragShader
, fragShaderText
);
368 vertShader
= glCreateShader_func(GL_VERTEX_SHADER
);
370 ReadShader(vertShader
, VertProgFile
);
372 LoadAndCompileShader(vertShader
, vertShaderText
);
374 program
= glCreateProgram_func();
375 glAttachShader_func(program
, fragShader
);
376 glAttachShader_func(program
, vertShader
);
377 glLinkProgram_func(program
);
379 glUseProgram_func(program
);
381 uLightPos
= glGetUniformLocation_func(program
, "lightPos");
382 uDiffuse
= glGetUniformLocation_func(program
, "diffuse");
383 uSpecular
= glGetUniformLocation_func(program
, "specular");
384 printf("LightPos %d DiffusePos %d SpecularPos %d\n",
385 uLightPos
, uDiffuse
, uSpecular
);
387 glUniform4fv_func(uDiffuse
, 1, diffuse
);
388 glUniform4fv_func(uSpecular
, 1, specular
);
390 glClearColor(0.3f
, 0.3f
, 0.3f
, 0.0f
);
391 glEnable(GL_DEPTH_TEST
);
393 glEnable(GL_LIGHTING
);
394 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, diffuse
);
395 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, specular
);
396 glMaterialf(GL_FRONT_AND_BACK
, GL_SHININESS
, 20.0f
);
398 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER
));
399 printf("Press p to toggle between per-pixel and per-vertex lighting\n");
401 /* test glGetShaderSource() */
403 GLsizei len
= strlen(fragShaderText
) + 1;
405 GLchar
*src
=(GLchar
*) malloc(len
* sizeof(GLchar
));
406 glGetShaderSource_func(fragShader
, 0, NULL
, src
);
407 glGetShaderSource_func(fragShader
, len
, &lenOut
, src
);
408 assert(len
== lenOut
+ 1);
409 assert(strcmp(src
, fragShaderText
) == 0);
413 assert(glIsProgram_func(program
));
414 assert(glIsShader_func(fragShader
));
415 assert(glIsShader_func(vertShader
));
425 ParseOptions(int argc
, char *argv
[])
428 for (i
= 1; i
< argc
; i
++) {
429 if (strcmp(argv
[i
], "-fs") == 0) {
430 FragProgFile
= argv
[i
+1];
432 else if (strcmp(argv
[i
], "-vs") == 0) {
433 VertProgFile
= argv
[i
+1];
440 main(int argc
, char *argv
[])
442 glutInit(&argc
, argv
);
443 glutInitWindowPosition( 0, 0);
444 glutInitWindowSize(100, 100);
445 glutInitDisplayMode(GLUT_RGB
| GLUT_DOUBLE
| GLUT_DEPTH
);
446 win
= glutCreateWindow(argv
[0]);
447 glutReshapeFunc(Reshape
);
448 glutKeyboardFunc(Key
);
449 glutSpecialFunc(SpecialKey
);
450 glutDisplayFunc(Redisplay
);
453 ParseOptions(argc
, argv
);