2 * Simple shader test harness.
7 * shtest --vs vertShaderFile --fs fragShaderFile
9 * In this case the given vertex/frag shaders are read and compiled.
10 * Random values are assigned to the uniforms.
15 * In this case a config file is read that specifies the file names
16 * of the shaders plus initial values for uniforms.
18 * Example config file:
23 * uniform v1 1.0 0.5 0.2 0.3
37 #include "shaderutil.h"
48 static char *FragShaderFile
= NULL
;
49 static char *VertShaderFile
= NULL
;
50 static char *ConfigFile
= NULL
;
52 /* program/shader objects */
53 static GLuint fragShader
;
54 static GLuint vertShader
;
55 static GLuint Program
;
58 #define MAX_UNIFORMS 100
59 static struct uniform_info Uniforms
[MAX_UNIFORMS
];
60 static GLuint NumUniforms
= 0;
63 #define MAX_ATTRIBS 100
64 static struct attrib_info Attribs
[MAX_ATTRIBS
];
65 static GLuint NumAttribs
= 0;
85 static GLboolean Anim
= GL_FALSE
;
86 static GLfloat TexRot
= 0.0;
87 static GLfloat xRot
= 0.0f
, yRot
= 0.0f
, zRot
= 0.0f
;
88 static shape Object
= SPHERE
;
92 RandomFloat(float min
, float max
)
94 int k
= rand() % 10000;
95 float x
= min
+ (max
- min
) * k
/ 10000.0;
100 /** Set new random values for uniforms */
102 RandomUniformValues(void)
105 for (i
= 0; i
< NumUniforms
; i
++) {
106 if (Uniforms
[i
].type
== GL_FLOAT
) {
107 Uniforms
[i
].value
[0] = RandomFloat(0.0, 1.0);
110 Uniforms
[i
].value
[0] = RandomFloat(-1.0, 2.0);
111 Uniforms
[i
].value
[1] = RandomFloat(-1.0, 2.0);
112 Uniforms
[i
].value
[2] = RandomFloat(-1.0, 2.0);
113 Uniforms
[i
].value
[3] = RandomFloat(-1.0, 2.0);
131 SquareVertex(GLfloat s
, GLfloat t
, GLfloat size
)
133 GLfloat x
= -size
+ s
* 2.0 * size
;
134 GLfloat y
= -size
+ t
* 2.0 * size
;
141 * Draw a square, specifying normal and tangent vectors.
146 GLint tangentAttrib
= 1;
148 glVertexAttrib3f(tangentAttrib
, 1, 0, 0);
151 SquareVertex(0, 0, size
);
152 SquareVertex(1, 0, size
);
153 SquareVertex(1, 1, size
);
154 SquareVertex(0, 1, size
);
156 glTexCoord2f(0, 0); glVertex2f(-size
, -size
);
157 glTexCoord2f(1, 0); glVertex2f( size
, -size
);
158 glTexCoord2f(1, 1); glVertex2f( size
, size
);
159 glTexCoord2f(0, 1); glVertex2f(-size
, size
);
170 glRotatef(90, 0, 1, 0);
171 glTranslatef(0, 0, size
);
177 glRotatef(-90, 0, 1, 0);
178 glTranslatef(0, 0, size
);
184 glRotatef(90, 1, 0, 0);
185 glTranslatef(0, 0, size
);
191 glRotatef(-90, 1, 0, 0);
192 glTranslatef(0, 0, size
);
199 glTranslatef(0, 0, size
);
205 glRotatef(180, 0, 1, 0);
206 glTranslatef(0, 0, size
);
213 Sphere(GLfloat radius
, GLint slices
, GLint stacks
)
215 static GLUquadricObj
*q
= NULL
;
219 gluQuadricDrawStyle(q
, GLU_FILL
);
220 gluQuadricNormals(q
, GLU_SMOOTH
);
221 gluQuadricTexture(q
, GL_TRUE
);
224 gluSphere(q
, radius
, slices
, stacks
);
231 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
234 glRotatef(xRot
, 1.0f
, 0.0f
, 0.0f
);
235 glRotatef(yRot
, 0.0f
, 1.0f
, 0.0f
);
236 glRotatef(zRot
, 0.0f
, 0.0f
, 1.0f
);
238 glMatrixMode(GL_TEXTURE
);
240 glRotatef(TexRot
, 0.0f
, 1.0f
, 0.0f
);
241 glMatrixMode(GL_MODELVIEW
);
243 if (Object
== SPHERE
) {
246 else if (Object
== CUBE
) {
257 Reshape(int width
, int height
)
259 glViewport(0, 0, width
, height
);
260 glMatrixMode(GL_PROJECTION
);
262 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
263 glMatrixMode(GL_MODELVIEW
);
265 glTranslatef(0.0f
, 0.0f
, -15.0f
);
272 glDeleteShader(fragShader
);
273 glDeleteShader(vertShader
);
274 glDeleteProgram(Program
);
275 glutDestroyWindow(win
);
280 Key(unsigned char key
, int x
, int y
)
282 const GLfloat step
= 2.0;
301 Object
= (Object
+ 1) % NUM_SHAPES
;
304 RandomUniformValues();
305 SetUniformValues(Program
, Uniforms
);
306 PrintUniforms(Uniforms
);
318 SpecialKey(int key
, int x
, int y
)
320 const GLfloat step
= 2.0;
344 InitUniforms(const struct config_file
*conf
,
345 struct uniform_info uniforms
[])
349 for (i
= 0; i
< conf
->num_uniforms
; i
++) {
351 for (j
= 0; uniforms
[j
].name
; j
++) {
352 if (strcmp(uniforms
[j
].name
, conf
->uniforms
[i
].name
) == 0) {
353 uniforms
[j
].type
= conf
->uniforms
[i
].type
;
354 uniforms
[j
].value
[0] = conf
->uniforms
[i
].value
[0];
355 uniforms
[j
].value
[1] = conf
->uniforms
[i
].value
[1];
356 uniforms
[j
].value
[2] = conf
->uniforms
[i
].value
[2];
357 uniforms
[j
].value
[3] = conf
->uniforms
[i
].value
[3];
365 * Read a config file.
368 ReadConfigFile(const char *filename
, struct config_file
*conf
)
373 f
= fopen(filename
, "r");
375 fprintf(stderr
, "Unable to open config file %s\n", filename
);
379 conf
->num_uniforms
= 0;
381 /* ugly but functional parser */
383 fgets(line
, sizeof(line
), f
);
385 if (strncmp(line
, "vs ", 3) == 0) {
386 VertShaderFile
= strdup(line
+ 3);
387 VertShaderFile
[strlen(VertShaderFile
) - 1] = 0;
389 else if (strncmp(line
, "fs ", 3) == 0) {
390 FragShaderFile
= strdup(line
+ 3);
391 FragShaderFile
[strlen(FragShaderFile
) - 1] = 0;
393 else if (strncmp(line
, "uniform ", 8) == 0) {
396 float v1
, v2
, v3
, v4
;
399 k
= sscanf(line
+ 8, "%s %f %f %f %f", name
, &v1
, &v2
, &v3
, &v4
);
410 type
= GL_FLOAT_VEC2
;
413 type
= GL_FLOAT_VEC3
;
416 type
= GL_FLOAT_VEC4
;
420 strcpy(conf
->uniforms
[conf
->num_uniforms
].name
, name
);
421 conf
->uniforms
[conf
->num_uniforms
].value
[0] = v1
;
422 conf
->uniforms
[conf
->num_uniforms
].value
[1] = v2
;
423 conf
->uniforms
[conf
->num_uniforms
].value
[2] = v3
;
424 conf
->uniforms
[conf
->num_uniforms
].value
[3] = v4
;
425 conf
->uniforms
[conf
->num_uniforms
].type
= type
;
426 conf
->num_uniforms
++;
429 if (strlen(line
) > 1) {
430 fprintf(stderr
, "syntax error in: %s\n", line
);
444 struct config_file config
;
445 memset(&config
, 0, sizeof(config
));
448 ReadConfigFile(ConfigFile
, &config
);
450 if (!VertShaderFile
) {
451 fprintf(stderr
, "Error: no vertex shader\n");
455 if (!FragShaderFile
) {
456 fprintf(stderr
, "Error: no fragment shader\n");
460 if (!ShadersSupported())
463 vertShader
= CompileShaderFile(GL_VERTEX_SHADER
, VertShaderFile
);
464 fragShader
= CompileShaderFile(GL_FRAGMENT_SHADER
, FragShaderFile
);
465 Program
= LinkShaders(vertShader
, fragShader
);
467 glUseProgram(Program
);
469 NumUniforms
= GetUniforms(Program
, Uniforms
);
470 if (config
.num_uniforms
) {
471 InitUniforms(&config
, Uniforms
);
474 RandomUniformValues();
476 SetUniformValues(Program
, Uniforms
);
477 PrintUniforms(Uniforms
);
479 NumAttribs
= GetAttribs(Program
, Attribs
);
480 PrintAttribs(Attribs
);
482 //assert(glGetError() == 0);
484 glClearColor(0.4f
, 0.4f
, 0.8f
, 0.0f
);
486 glEnable(GL_DEPTH_TEST
);
495 printf("Keyboard:\n");
496 printf(" a Animation toggle\n");
497 printf(" r Randomize uniform values\n");
498 printf(" o Change object\n");
499 printf(" arrows Rotate object\n");
500 printf(" ESC Exit\n");
508 printf(" shtest config.shtest\n");
509 printf(" Run w/ given config file.\n");
510 printf(" shtest --vs vertShader --fs fragShader\n");
511 printf(" Load/compile given shaders.\n");
516 ParseOptions(int argc
, char *argv
[])
525 for (i
= 1; i
< argc
; i
++) {
526 if (strcmp(argv
[i
], "--fs") == 0) {
527 FragShaderFile
= argv
[i
+1];
530 else if (strcmp(argv
[i
], "--vs") == 0) {
531 VertShaderFile
= argv
[i
+1];
535 /* assume the arg is a config file */
536 ConfigFile
= argv
[i
];
544 main(int argc
, char *argv
[])
546 glutInit(&argc
, argv
);
547 glutInitWindowPosition( 0, 0);
548 glutInitWindowSize(400, 400);
549 glutInitDisplayMode(GLUT_RGB
| GLUT_DOUBLE
| GLUT_DEPTH
);
550 win
= glutCreateWindow(argv
[0]);
552 glutReshapeFunc(Reshape
);
553 glutKeyboardFunc(Key
);
554 glutSpecialFunc(SpecialKey
);
555 glutDisplayFunc(Redisplay
);
556 ParseOptions(argc
, argv
);