132001f49Smrg/* 232001f49Smrg * Simple shader test harness. 332001f49Smrg * Brian Paul 432001f49Smrg * 13 Aug 2009 532001f49Smrg * 632001f49Smrg * Usage: 732001f49Smrg * shtest --vs vertShaderFile --fs fragShaderFile 832001f49Smrg * 932001f49Smrg * In this case the given vertex/frag shaders are read and compiled. 1032001f49Smrg * Random values are assigned to the uniforms. 1132001f49Smrg * 1232001f49Smrg * or: 1332001f49Smrg * shtest configFile 1432001f49Smrg * 1532001f49Smrg * In this case a config file is read that specifies the file names 1632001f49Smrg * of the shaders plus initial values for uniforms. 1732001f49Smrg * 1832001f49Smrg * Example config file: 1932001f49Smrg * 2032001f49Smrg * vs shader.vert 2132001f49Smrg * fs shader.frag 2232001f49Smrg * uniform GL_FLOAT pi 3.14159 2332001f49Smrg * uniform GL_FLOAT_VEC4 v1 1.0 0.5 0.2 0.3 2432001f49Smrg * texture 0 2D texture0.rgb 2532001f49Smrg * texture 1 CUBE texture1.rgb 2632001f49Smrg * texture 2 RECT texture2.rgb 2732001f49Smrg * 2832001f49Smrg */ 2932001f49Smrg 3032001f49Smrg 3132001f49Smrg#include <assert.h> 3232001f49Smrg#include <stdio.h> 3332001f49Smrg#include <stdlib.h> 3432001f49Smrg#include <string.h> 3532001f49Smrg#include <math.h> 3632001f49Smrg#include <GL/glew.h> 3732001f49Smrg#include "glut_wrap.h" 3832001f49Smrg#include "shaderutil.h" 3932001f49Smrg#include "readtex.h" 4032001f49Smrg 4132001f49Smrg 4232001f49Smrgtypedef enum 4332001f49Smrg{ 4432001f49Smrg SPHERE, 4532001f49Smrg CUBE, 4632001f49Smrg NUM_SHAPES 4732001f49Smrg} shape; 4832001f49Smrg 4932001f49Smrg 5032001f49Smrgstatic char *FragShaderFile = NULL; 5132001f49Smrgstatic char *VertShaderFile = NULL; 5232001f49Smrgstatic char *ConfigFile = NULL; 5332001f49Smrg 5432001f49Smrg/* program/shader objects */ 5532001f49Smrgstatic GLuint fragShader; 5632001f49Smrgstatic GLuint vertShader; 5732001f49Smrgstatic GLuint Program; 5832001f49Smrg 5932001f49Smrg 6032001f49Smrg#define MAX_UNIFORMS 100 6132001f49Smrgstatic struct uniform_info Uniforms[MAX_UNIFORMS]; 6232001f49Smrgstatic GLuint NumUniforms = 0; 6332001f49Smrg 6432001f49Smrg 6532001f49Smrg#define MAX_ATTRIBS 100 6632001f49Smrgstatic struct attrib_info Attribs[MAX_ATTRIBS]; 6732001f49Smrgstatic GLuint NumAttribs = 0; 6832001f49Smrg 6932001f49Smrg 7032001f49Smrg/** 7132001f49Smrg * Config file info. 7232001f49Smrg */ 7332001f49Smrgstruct config_file 7432001f49Smrg{ 7532001f49Smrg struct name_value 7632001f49Smrg { 7732001f49Smrg char name[100]; 7832001f49Smrg float value[4]; 7932001f49Smrg int type; 8032001f49Smrg } uniforms[100]; 8132001f49Smrg 8232001f49Smrg int num_uniforms; 8332001f49Smrg}; 8432001f49Smrg 8532001f49Smrg 8632001f49Smrgstatic GLint win = 0; 8732001f49Smrgstatic GLboolean Anim = GL_FALSE; 8832001f49Smrgstatic GLfloat TexRot = 0.0; 8932001f49Smrgstatic GLfloat xRot = 0.0f, yRot = 0.0f, zRot = 0.0f; 9032001f49Smrgstatic shape Object = SPHERE; 9132001f49Smrg 9232001f49Smrg 9332001f49Smrgstatic float 9432001f49SmrgRandomFloat(float min, float max) 9532001f49Smrg{ 9632001f49Smrg int k = rand() % 10000; 9732001f49Smrg float x = min + (max - min) * k / 10000.0; 9832001f49Smrg return x; 9932001f49Smrg} 10032001f49Smrg 10132001f49Smrg 10232001f49Smrg/** Set new random values for uniforms */ 10332001f49Smrgstatic void 10432001f49SmrgRandomUniformValues(void) 10532001f49Smrg{ 10632001f49Smrg GLuint i; 10732001f49Smrg for (i = 0; i < NumUniforms; i++) { 10832001f49Smrg switch (Uniforms[i].type) { 10932001f49Smrg case GL_FLOAT: 11032001f49Smrg Uniforms[i].value[0] = RandomFloat(0.0, 1.0); 11132001f49Smrg break; 11232001f49Smrg case GL_SAMPLER_1D: 11332001f49Smrg case GL_SAMPLER_2D: 11432001f49Smrg case GL_SAMPLER_3D: 11532001f49Smrg case GL_SAMPLER_CUBE: 11632001f49Smrg case GL_SAMPLER_2D_RECT_ARB: 11732001f49Smrg /* don't change sampler values - random values are bad */ 11832001f49Smrg break; 11932001f49Smrg default: 12032001f49Smrg Uniforms[i].value[0] = RandomFloat(-1.0, 2.0); 12132001f49Smrg Uniforms[i].value[1] = RandomFloat(-1.0, 2.0); 12232001f49Smrg Uniforms[i].value[2] = RandomFloat(-1.0, 2.0); 12332001f49Smrg Uniforms[i].value[3] = RandomFloat(-1.0, 2.0); 12432001f49Smrg } 12532001f49Smrg } 12632001f49Smrg} 12732001f49Smrg 12832001f49Smrg 12932001f49Smrgstatic void 13032001f49SmrgIdle(void) 13132001f49Smrg{ 13232001f49Smrg yRot += 2.0; 13332001f49Smrg if (yRot > 360.0) 13432001f49Smrg yRot -= 360.0; 13532001f49Smrg glutPostRedisplay(); 13632001f49Smrg} 13732001f49Smrg 13832001f49Smrg 13932001f49Smrg 14032001f49Smrgstatic void 14132001f49SmrgSquareVertex(GLfloat s, GLfloat t, GLfloat size) 14232001f49Smrg{ 14332001f49Smrg GLfloat x = -size + s * 2.0 * size; 14432001f49Smrg GLfloat y = -size + t * 2.0 * size; 14532001f49Smrg GLuint i; 14632001f49Smrg 14732001f49Smrg glMultiTexCoord2f(GL_TEXTURE0, s, t); 14832001f49Smrg glMultiTexCoord2f(GL_TEXTURE1, s, t); 14932001f49Smrg glMultiTexCoord2f(GL_TEXTURE2, s, t); 15032001f49Smrg glMultiTexCoord2f(GL_TEXTURE3, s, t); 15132001f49Smrg 15232001f49Smrg /* assign (s,t) to the generic attributes */ 15332001f49Smrg for (i = 0; i < NumAttribs; i++) { 15432001f49Smrg if (Attribs[i].location >= 0) { 15532001f49Smrg glVertexAttrib2f(Attribs[i].location, s, t); 15632001f49Smrg } 15732001f49Smrg } 15832001f49Smrg 15932001f49Smrg glVertex2f(x, y); 16032001f49Smrg} 16132001f49Smrg 16232001f49Smrg 16332001f49Smrg/* 16432001f49Smrg * Draw a square, specifying normal and tangent vectors. 16532001f49Smrg */ 16632001f49Smrgstatic void 16732001f49SmrgSquare(GLfloat size) 16832001f49Smrg{ 16932001f49Smrg GLint tangentAttrib = 1; 17032001f49Smrg glNormal3f(0, 0, 1); 17132001f49Smrg glVertexAttrib3f(tangentAttrib, 1, 0, 0); 17232001f49Smrg glBegin(GL_POLYGON); 17332001f49Smrg#if 1 17432001f49Smrg SquareVertex(0, 0, size); 17532001f49Smrg SquareVertex(1, 0, size); 17632001f49Smrg SquareVertex(1, 1, size); 17732001f49Smrg SquareVertex(0, 1, size); 17832001f49Smrg#else 17932001f49Smrg glTexCoord2f(0, 0); glVertex2f(-size, -size); 18032001f49Smrg glTexCoord2f(1, 0); glVertex2f( size, -size); 18132001f49Smrg glTexCoord2f(1, 1); glVertex2f( size, size); 18232001f49Smrg glTexCoord2f(0, 1); glVertex2f(-size, size); 18332001f49Smrg#endif 18432001f49Smrg glEnd(); 18532001f49Smrg} 18632001f49Smrg 18732001f49Smrg 18832001f49Smrgstatic void 18932001f49SmrgCube(GLfloat size) 19032001f49Smrg{ 19132001f49Smrg /* +X */ 19232001f49Smrg glPushMatrix(); 19332001f49Smrg glRotatef(90, 0, 1, 0); 19432001f49Smrg glTranslatef(0, 0, size); 19532001f49Smrg Square(size); 19632001f49Smrg glPopMatrix(); 19732001f49Smrg 19832001f49Smrg /* -X */ 19932001f49Smrg glPushMatrix(); 20032001f49Smrg glRotatef(-90, 0, 1, 0); 20132001f49Smrg glTranslatef(0, 0, size); 20232001f49Smrg Square(size); 20332001f49Smrg glPopMatrix(); 20432001f49Smrg 20532001f49Smrg /* +Y */ 20632001f49Smrg glPushMatrix(); 20732001f49Smrg glRotatef(90, 1, 0, 0); 20832001f49Smrg glTranslatef(0, 0, size); 20932001f49Smrg Square(size); 21032001f49Smrg glPopMatrix(); 21132001f49Smrg 21232001f49Smrg /* -Y */ 21332001f49Smrg glPushMatrix(); 21432001f49Smrg glRotatef(-90, 1, 0, 0); 21532001f49Smrg glTranslatef(0, 0, size); 21632001f49Smrg Square(size); 21732001f49Smrg glPopMatrix(); 21832001f49Smrg 21932001f49Smrg 22032001f49Smrg /* +Z */ 22132001f49Smrg glPushMatrix(); 22232001f49Smrg glTranslatef(0, 0, size); 22332001f49Smrg Square(size); 22432001f49Smrg glPopMatrix(); 22532001f49Smrg 22632001f49Smrg /* -Z */ 22732001f49Smrg glPushMatrix(); 22832001f49Smrg glRotatef(180, 0, 1, 0); 22932001f49Smrg glTranslatef(0, 0, size); 23032001f49Smrg Square(size); 23132001f49Smrg glPopMatrix(); 23232001f49Smrg} 23332001f49Smrg 23432001f49Smrg 23532001f49Smrgstatic void 23632001f49SmrgSphere(GLfloat radius, GLint slices, GLint stacks) 23732001f49Smrg{ 23832001f49Smrg static GLUquadricObj *q = NULL; 23932001f49Smrg 24032001f49Smrg if (!q) { 24132001f49Smrg q = gluNewQuadric(); 24232001f49Smrg gluQuadricDrawStyle(q, GLU_FILL); 24332001f49Smrg gluQuadricNormals(q, GLU_SMOOTH); 24432001f49Smrg gluQuadricTexture(q, GL_TRUE); 24532001f49Smrg } 24632001f49Smrg 24732001f49Smrg gluSphere(q, radius, slices, stacks); 24832001f49Smrg} 24932001f49Smrg 25032001f49Smrg 25132001f49Smrgstatic void 25232001f49SmrgRedisplay(void) 25332001f49Smrg{ 25432001f49Smrg glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 25532001f49Smrg 25632001f49Smrg glPushMatrix(); 25732001f49Smrg glRotatef(xRot, 1.0f, 0.0f, 0.0f); 25832001f49Smrg glRotatef(yRot, 0.0f, 1.0f, 0.0f); 25932001f49Smrg glRotatef(zRot, 0.0f, 0.0f, 1.0f); 26032001f49Smrg 26132001f49Smrg glMatrixMode(GL_TEXTURE); 26232001f49Smrg glLoadIdentity(); 26332001f49Smrg glRotatef(TexRot, 0.0f, 1.0f, 0.0f); 26432001f49Smrg glMatrixMode(GL_MODELVIEW); 26532001f49Smrg 26632001f49Smrg if (Object == SPHERE) { 26732001f49Smrg Sphere(2.5, 20, 10); 26832001f49Smrg } 26932001f49Smrg else if (Object == CUBE) { 27032001f49Smrg Cube(2.0); 27132001f49Smrg } 27232001f49Smrg 27332001f49Smrg glPopMatrix(); 27432001f49Smrg 27532001f49Smrg glutSwapBuffers(); 27632001f49Smrg} 27732001f49Smrg 27832001f49Smrg 27932001f49Smrgstatic void 28032001f49SmrgReshape(int width, int height) 28132001f49Smrg{ 28232001f49Smrg glViewport(0, 0, width, height); 28332001f49Smrg glMatrixMode(GL_PROJECTION); 28432001f49Smrg glLoadIdentity(); 28532001f49Smrg glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0); 28632001f49Smrg glMatrixMode(GL_MODELVIEW); 28732001f49Smrg glLoadIdentity(); 28832001f49Smrg glTranslatef(0.0f, 0.0f, -15.0f); 28932001f49Smrg} 29032001f49Smrg 29132001f49Smrg 29232001f49Smrgstatic void 29332001f49SmrgCleanUp(void) 29432001f49Smrg{ 29532001f49Smrg glDeleteShader(fragShader); 29632001f49Smrg glDeleteShader(vertShader); 29732001f49Smrg glDeleteProgram(Program); 29832001f49Smrg glutDestroyWindow(win); 29932001f49Smrg} 30032001f49Smrg 30132001f49Smrg 30232001f49Smrgstatic void 30332001f49SmrgKey(unsigned char key, int x, int y) 30432001f49Smrg{ 30532001f49Smrg const GLfloat step = 2.0; 30632001f49Smrg (void) x; 30732001f49Smrg (void) y; 30832001f49Smrg 30932001f49Smrg switch(key) { 31032001f49Smrg case 'a': 31132001f49Smrg Anim = !Anim; 31232001f49Smrg if (Anim) 31332001f49Smrg glutIdleFunc(Idle); 31432001f49Smrg else 31532001f49Smrg glutIdleFunc(NULL); 31632001f49Smrg break; 31732001f49Smrg case 'z': 31832001f49Smrg zRot += step; 31932001f49Smrg break; 32032001f49Smrg case 'Z': 32132001f49Smrg zRot -= step; 32232001f49Smrg break; 32332001f49Smrg case 'o': 32432001f49Smrg Object = (Object + 1) % NUM_SHAPES; 32532001f49Smrg break; 32632001f49Smrg case 'r': 32732001f49Smrg RandomUniformValues(); 32832001f49Smrg SetUniformValues(Program, Uniforms); 32932001f49Smrg PrintUniforms(Uniforms); 33032001f49Smrg break; 33132001f49Smrg case 27: 33232001f49Smrg CleanUp(); 33332001f49Smrg exit(0); 33432001f49Smrg break; 33532001f49Smrg } 33632001f49Smrg glutPostRedisplay(); 33732001f49Smrg} 33832001f49Smrg 33932001f49Smrg 34032001f49Smrgstatic void 34132001f49SmrgSpecialKey(int key, int x, int y) 34232001f49Smrg{ 34332001f49Smrg const GLfloat step = 2.0; 34432001f49Smrg 34532001f49Smrg (void) x; 34632001f49Smrg (void) y; 34732001f49Smrg 34832001f49Smrg switch(key) { 34932001f49Smrg case GLUT_KEY_UP: 35032001f49Smrg xRot += step; 35132001f49Smrg break; 35232001f49Smrg case GLUT_KEY_DOWN: 35332001f49Smrg xRot -= step; 35432001f49Smrg break; 35532001f49Smrg case GLUT_KEY_LEFT: 35632001f49Smrg yRot -= step; 35732001f49Smrg break; 35832001f49Smrg case GLUT_KEY_RIGHT: 35932001f49Smrg yRot += step; 36032001f49Smrg break; 36132001f49Smrg } 36232001f49Smrg glutPostRedisplay(); 36332001f49Smrg} 36432001f49Smrg 36532001f49Smrg 36632001f49Smrgstatic void 36732001f49SmrgInitUniforms(const struct config_file *conf, 36832001f49Smrg struct uniform_info uniforms[]) 36932001f49Smrg{ 37032001f49Smrg int i; 37132001f49Smrg 37232001f49Smrg for (i = 0; i < conf->num_uniforms; i++) { 37332001f49Smrg int j; 37432001f49Smrg for (j = 0; uniforms[j].name; j++) { 37532001f49Smrg if (strcmp(uniforms[j].name, conf->uniforms[i].name) == 0) { 37632001f49Smrg uniforms[j].type = conf->uniforms[i].type; 37732001f49Smrg uniforms[j].value[0] = conf->uniforms[i].value[0]; 37832001f49Smrg uniforms[j].value[1] = conf->uniforms[i].value[1]; 37932001f49Smrg uniforms[j].value[2] = conf->uniforms[i].value[2]; 38032001f49Smrg uniforms[j].value[3] = conf->uniforms[i].value[3]; 38132001f49Smrg } 38232001f49Smrg } 38332001f49Smrg } 38432001f49Smrg} 38532001f49Smrg 38632001f49Smrg 38732001f49Smrgstatic void 38832001f49SmrgLoadTexture(GLint unit, GLenum target, const char *texFileName) 38932001f49Smrg{ 39032001f49Smrg GLint imgWidth, imgHeight; 39132001f49Smrg GLenum imgFormat; 39232001f49Smrg GLubyte *image = NULL; 39332001f49Smrg GLuint tex; 39432001f49Smrg GLenum filter = GL_LINEAR; 39532001f49Smrg GLenum objTarget; 39632001f49Smrg 39732001f49Smrg image = LoadRGBImage(texFileName, &imgWidth, &imgHeight, &imgFormat); 39832001f49Smrg if (!image) { 39932001f49Smrg printf("Couldn't read %s\n", texFileName); 40032001f49Smrg exit(1); 40132001f49Smrg } 40232001f49Smrg 40332001f49Smrg printf("Load Texture: unit %d, target 0x%x: %s %d x %d\n", 40432001f49Smrg unit, target, texFileName, imgWidth, imgHeight); 40532001f49Smrg 40632001f49Smrg if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && 40732001f49Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) { 40832001f49Smrg objTarget = GL_TEXTURE_CUBE_MAP; 40932001f49Smrg } 41032001f49Smrg else { 41132001f49Smrg objTarget = target; 41232001f49Smrg } 41332001f49Smrg 41432001f49Smrg glActiveTexture(GL_TEXTURE0 + unit); 41532001f49Smrg glGenTextures(1, &tex); 41632001f49Smrg glBindTexture(objTarget, tex); 41732001f49Smrg 41832001f49Smrg if (target == GL_TEXTURE_3D) { 41932001f49Smrg#ifdef GLU_VERSION_1_3 42032001f49Smrg /* depth=1 */ 42132001f49Smrg gluBuild3DMipmaps(target, 4, imgWidth, imgHeight, 1, 42232001f49Smrg imgFormat, GL_UNSIGNED_BYTE, image); 42332001f49Smrg#else 42432001f49Smrg fprintf(stderr, "Error: GLU 1.3 not available\n"); 42532001f49Smrg exit(1); 42632001f49Smrg#endif 42732001f49Smrg } 42832001f49Smrg else if (target == GL_TEXTURE_1D) { 42932001f49Smrg gluBuild1DMipmaps(target, 4, imgWidth, 43032001f49Smrg imgFormat, GL_UNSIGNED_BYTE, image); 43132001f49Smrg } 43232001f49Smrg else { 43332001f49Smrg gluBuild2DMipmaps(target, 4, imgWidth, imgHeight, 43432001f49Smrg imgFormat, GL_UNSIGNED_BYTE, image); 43532001f49Smrg } 43632001f49Smrg 43732001f49Smrg free(image); 43832001f49Smrg 43932001f49Smrg glTexParameteri(objTarget, GL_TEXTURE_WRAP_S, GL_REPEAT); 44032001f49Smrg glTexParameteri(objTarget, GL_TEXTURE_WRAP_T, GL_REPEAT); 44132001f49Smrg glTexParameteri(objTarget, GL_TEXTURE_MIN_FILTER, filter); 44232001f49Smrg glTexParameteri(objTarget, GL_TEXTURE_MAG_FILTER, filter); 44332001f49Smrg} 44432001f49Smrg 44532001f49Smrg 44632001f49Smrgstatic GLenum 44732001f49SmrgTypeFromName(const char *n) 44832001f49Smrg{ 44932001f49Smrg static const struct { 45032001f49Smrg const char *name; 45132001f49Smrg GLenum type; 45232001f49Smrg } types[] = { 45332001f49Smrg { "GL_FLOAT", GL_FLOAT }, 45432001f49Smrg { "GL_FLOAT_VEC2", GL_FLOAT_VEC2 }, 45532001f49Smrg { "GL_FLOAT_VEC3", GL_FLOAT_VEC3 }, 45632001f49Smrg { "GL_FLOAT_VEC4", GL_FLOAT_VEC4 }, 45732001f49Smrg { "GL_INT", GL_INT }, 45832001f49Smrg { "GL_INT_VEC2", GL_INT_VEC2 }, 45932001f49Smrg { "GL_INT_VEC3", GL_INT_VEC3 }, 46032001f49Smrg { "GL_INT_VEC4", GL_INT_VEC4 }, 46132001f49Smrg { "GL_SAMPLER_1D", GL_SAMPLER_1D }, 46232001f49Smrg { "GL_SAMPLER_2D", GL_SAMPLER_2D }, 46332001f49Smrg { "GL_SAMPLER_3D", GL_SAMPLER_3D }, 46432001f49Smrg { "GL_SAMPLER_CUBE", GL_SAMPLER_CUBE }, 46532001f49Smrg { "GL_SAMPLER_2D_RECT", GL_SAMPLER_2D_RECT_ARB }, 46632001f49Smrg { NULL, 0 } 46732001f49Smrg }; 46832001f49Smrg GLuint i; 46932001f49Smrg 47032001f49Smrg for (i = 0; types[i].name; i++) { 47132001f49Smrg if (strcmp(types[i].name, n) == 0) 47232001f49Smrg return types[i].type; 47332001f49Smrg } 47432001f49Smrg abort(); 47532001f49Smrg return GL_NONE; 47632001f49Smrg} 47732001f49Smrg 47832001f49Smrg 47932001f49Smrg 48032001f49Smrg/** 48132001f49Smrg * Read a config file. 48232001f49Smrg */ 48332001f49Smrgstatic void 48432001f49SmrgReadConfigFile(const char *filename, struct config_file *conf) 48532001f49Smrg{ 48632001f49Smrg char line[1000]; 48732001f49Smrg FILE *f; 48832001f49Smrg 48932001f49Smrg f = fopen(filename, "r"); 49032001f49Smrg if (!f) { 49132001f49Smrg fprintf(stderr, "Unable to open config file %s\n", filename); 49232001f49Smrg exit(1); 49332001f49Smrg } 49432001f49Smrg 49532001f49Smrg conf->num_uniforms = 0; 49632001f49Smrg 49732001f49Smrg /* ugly but functional parser */ 49832001f49Smrg while (fgets(line, sizeof(line), f) != NULL) { 49932001f49Smrg if (line[0]) { 50032001f49Smrg if (strncmp(line, "vs ", 3) == 0) { 50132001f49Smrg VertShaderFile = strdup(line + 3); 50232001f49Smrg VertShaderFile[strlen(VertShaderFile) - 1] = 0; 50332001f49Smrg } 50432001f49Smrg else if (strncmp(line, "fs ", 3) == 0) { 50532001f49Smrg FragShaderFile = strdup(line + 3); 50632001f49Smrg FragShaderFile[strlen(FragShaderFile) - 1] = 0; 50732001f49Smrg } 50832001f49Smrg else if (strncmp(line, "texture ", 8) == 0) { 50932001f49Smrg char target[100], texFileName[100]; 51032001f49Smrg int unit, k; 51132001f49Smrg k = sscanf(line + 8, "%d %s %s", &unit, target, texFileName); 51232001f49Smrg assert(k == 3 || k == 8); 51332001f49Smrg if (strcmp(target, "CUBE") == 0) { 51432001f49Smrg char texFileNames[6][100]; 51532001f49Smrg k = sscanf(line + 8, "%d %s %s %s %s %s %s %s", 51632001f49Smrg &unit, target, 51732001f49Smrg texFileNames[0], 51832001f49Smrg texFileNames[1], 51932001f49Smrg texFileNames[2], 52032001f49Smrg texFileNames[3], 52132001f49Smrg texFileNames[4], 52232001f49Smrg texFileNames[5]); 52332001f49Smrg LoadTexture(unit, GL_TEXTURE_CUBE_MAP_POSITIVE_X, texFileNames[0]); 52432001f49Smrg LoadTexture(unit, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, texFileNames[1]); 52532001f49Smrg LoadTexture(unit, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, texFileNames[2]); 52632001f49Smrg LoadTexture(unit, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, texFileNames[3]); 52732001f49Smrg LoadTexture(unit, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, texFileNames[4]); 52832001f49Smrg LoadTexture(unit, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, texFileNames[5]); 52932001f49Smrg } 53032001f49Smrg else if (!strcmp(target, "2D")) { 53132001f49Smrg LoadTexture(unit, GL_TEXTURE_2D, texFileName); 53232001f49Smrg } 53332001f49Smrg else if (!strcmp(target, "3D")) { 53432001f49Smrg LoadTexture(unit, GL_TEXTURE_3D, texFileName); 53532001f49Smrg } 53632001f49Smrg else if (!strcmp(target, "RECT")) { 53732001f49Smrg LoadTexture(unit, GL_TEXTURE_RECTANGLE_ARB, texFileName); 53832001f49Smrg } 53932001f49Smrg else { 54032001f49Smrg printf("Bad texture target: %s\n", target); 54132001f49Smrg exit(1); 54232001f49Smrg } 54332001f49Smrg } 54432001f49Smrg else if (strncmp(line, "uniform ", 8) == 0) { 54532001f49Smrg char name[1000], typeName[100]; 54632001f49Smrg int k; 54732001f49Smrg float v1 = 0.0F, v2 = 0.0F, v3 = 0.0F, v4 = 0.0F; 54832001f49Smrg GLenum type; 54932001f49Smrg 55032001f49Smrg k = sscanf(line + 8, "%s %s %f %f %f %f", typeName, name, 55132001f49Smrg &v1, &v2, &v3, &v4); 55232001f49Smrg 55332001f49Smrg type = TypeFromName(typeName); 55432001f49Smrg 55532001f49Smrg if (strlen(name) + 1 > sizeof(conf->uniforms[conf->num_uniforms].name)) { 55632001f49Smrg fprintf(stderr, "string overflow\n"); 55732001f49Smrg exit(1); 55832001f49Smrg } 55932001f49Smrg strcpy(conf->uniforms[conf->num_uniforms].name, name); 56032001f49Smrg conf->uniforms[conf->num_uniforms].value[0] = v1; 56132001f49Smrg conf->uniforms[conf->num_uniforms].value[1] = v2; 56232001f49Smrg conf->uniforms[conf->num_uniforms].value[2] = v3; 56332001f49Smrg conf->uniforms[conf->num_uniforms].value[3] = v4; 56432001f49Smrg conf->uniforms[conf->num_uniforms].type = type; 56532001f49Smrg conf->num_uniforms++; 56632001f49Smrg } 56732001f49Smrg else { 56832001f49Smrg if (strlen(line) > 1) { 56932001f49Smrg fprintf(stderr, "syntax error in: %s\n", line); 57032001f49Smrg break; 57132001f49Smrg } 57232001f49Smrg } 57332001f49Smrg } 57432001f49Smrg } 57532001f49Smrg 57632001f49Smrg fclose(f); 57732001f49Smrg} 57832001f49Smrg 57932001f49Smrg 58032001f49Smrgstatic void 58132001f49SmrgInit(void) 58232001f49Smrg{ 58332001f49Smrg GLdouble vertTime = 0.0, fragTime = 0.0, linkTime = 0.0; 58432001f49Smrg struct config_file config; 58532001f49Smrg 58632001f49Smrg memset(&config, 0, sizeof(config)); 58732001f49Smrg 58832001f49Smrg if (ConfigFile) 58932001f49Smrg ReadConfigFile(ConfigFile, &config); 59032001f49Smrg 59132001f49Smrg if (!ShadersSupported()) 59232001f49Smrg exit(1); 59332001f49Smrg 59432001f49Smrg if (VertShaderFile) { 59532001f49Smrg printf("Read vert shader %s\n", VertShaderFile); 59632001f49Smrg vertShader = CompileShaderFile(GL_VERTEX_SHADER, VertShaderFile); 59732001f49Smrg vertTime = GetShaderCompileTime(); 59832001f49Smrg } 59932001f49Smrg 60032001f49Smrg if (FragShaderFile) { 60132001f49Smrg printf("Read frag shader %s\n", FragShaderFile); 60232001f49Smrg fragShader = CompileShaderFile(GL_FRAGMENT_SHADER, FragShaderFile); 60332001f49Smrg fragTime = GetShaderCompileTime(); 60432001f49Smrg } 60532001f49Smrg 60632001f49Smrg Program = LinkShaders(vertShader, fragShader); 60732001f49Smrg linkTime = GetShaderLinkTime(); 60832001f49Smrg 60932001f49Smrg printf("Time to compile vertex shader: %fs\n", vertTime); 61032001f49Smrg printf("Time to compile fragment shader: %fs\n", fragTime); 61132001f49Smrg printf("Time to link shaders: %fs\n", linkTime); 61232001f49Smrg 61332001f49Smrg assert(ValidateShaderProgram(Program)); 61432001f49Smrg 61532001f49Smrg glUseProgram(Program); 61632001f49Smrg 61732001f49Smrg NumUniforms = GetUniforms(Program, Uniforms); 61832001f49Smrg if (config.num_uniforms) { 61932001f49Smrg InitUniforms(&config, Uniforms); 62032001f49Smrg } 62132001f49Smrg else { 62232001f49Smrg RandomUniformValues(); 62332001f49Smrg } 62432001f49Smrg SetUniformValues(Program, Uniforms); 62532001f49Smrg PrintUniforms(Uniforms); 62632001f49Smrg 62732001f49Smrg NumAttribs = GetAttribs(Program, Attribs); 62832001f49Smrg PrintAttribs(Attribs); 62932001f49Smrg 63032001f49Smrg /* assert(glGetError() == 0); */ 63132001f49Smrg 63232001f49Smrg glClearColor(0.4f, 0.4f, 0.8f, 0.0f); 63332001f49Smrg 63432001f49Smrg glEnable(GL_DEPTH_TEST); 63532001f49Smrg 63632001f49Smrg glColor3f(1, 0, 0); 63732001f49Smrg} 63832001f49Smrg 63932001f49Smrg 64032001f49Smrgstatic void 64132001f49SmrgKeys(void) 64232001f49Smrg{ 64332001f49Smrg printf("Keyboard:\n"); 64432001f49Smrg printf(" a Animation toggle\n"); 64532001f49Smrg printf(" r Randomize uniform values\n"); 64632001f49Smrg printf(" o Change object\n"); 64732001f49Smrg printf(" arrows Rotate object\n"); 64832001f49Smrg printf(" ESC Exit\n"); 64932001f49Smrg} 65032001f49Smrg 65132001f49Smrg 65232001f49Smrgstatic void 65332001f49SmrgUsage(void) 65432001f49Smrg{ 65532001f49Smrg printf("Usage:\n"); 65632001f49Smrg printf(" shtest config.shtest\n"); 65732001f49Smrg printf(" Run w/ given config file.\n"); 65832001f49Smrg printf(" shtest --vs vertShader --fs fragShader\n"); 65932001f49Smrg printf(" Load/compile given shaders.\n"); 66032001f49Smrg} 66132001f49Smrg 66232001f49Smrg 66332001f49Smrgstatic void 66432001f49SmrgParseOptions(int argc, char *argv[]) 66532001f49Smrg{ 66632001f49Smrg int i; 66732001f49Smrg 66832001f49Smrg if (argc == 1) { 66932001f49Smrg Usage(); 67032001f49Smrg exit(1); 67132001f49Smrg } 67232001f49Smrg 67332001f49Smrg for (i = 1; i < argc; i++) { 67432001f49Smrg if (strcmp(argv[i], "--fs") == 0) { 67532001f49Smrg FragShaderFile = argv[i+1]; 67632001f49Smrg i++; 67732001f49Smrg } 67832001f49Smrg else if (strcmp(argv[i], "--vs") == 0) { 67932001f49Smrg VertShaderFile = argv[i+1]; 68032001f49Smrg i++; 68132001f49Smrg } 68232001f49Smrg else { 68332001f49Smrg /* assume the arg is a config file */ 68432001f49Smrg ConfigFile = argv[i]; 68532001f49Smrg break; 68632001f49Smrg } 68732001f49Smrg } 68832001f49Smrg} 68932001f49Smrg 69032001f49Smrg 69132001f49Smrgint 69232001f49Smrgmain(int argc, char *argv[]) 69332001f49Smrg{ 69432001f49Smrg glutInitWindowSize(400, 400); 69532001f49Smrg glutInit(&argc, argv); 69632001f49Smrg glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); 69732001f49Smrg win = glutCreateWindow(argv[0]); 69832001f49Smrg glewInit(); 69932001f49Smrg glutReshapeFunc(Reshape); 70032001f49Smrg glutKeyboardFunc(Key); 70132001f49Smrg glutSpecialFunc(SpecialKey); 70232001f49Smrg glutDisplayFunc(Redisplay); 70332001f49Smrg ParseOptions(argc, argv); 70432001f49Smrg Init(); 70532001f49Smrg Keys(); 70632001f49Smrg glutMainLoop(); 70732001f49Smrg return 0; 70832001f49Smrg} 70932001f49Smrg 710