/* Simple Demo for GLSL www.lighthouse3d.com tweaked a bit by andy */ #include "GL/glew.h" #ifdef __linux__ #include #endif #ifdef __APPLE__ #include #endif #ifdef _WIN32 #include "glut.h" #endif #include #include #include #include //////////////////////////////////////////////////////////////////////////////// char *textFileRead(char *fn) { FILE *fp; char *content = NULL; int count=0; if (fn != NULL) { fp = fopen(fn,"rt"); if (fp != NULL) { fseek(fp, 0, SEEK_END); count = ftell(fp); rewind(fp); if (count > 0) { content = (char *)malloc(sizeof(char) * (count+1)); count = fread(content,sizeof(char),count,fp); content[count] = '\0'; } fclose(fp); } } if (content == NULL) { fprintf(stderr, "ERROR: could not load in file %s\n", fn); exit(1); } return content; } //////////////////////////////////////////////////////////////////////////////// GLuint ptbrick, pttoon; float lpos[4] = {1.0, 0.5, 1.0, 0.0}; void changeSize(int w, int h) { // Prevent a divide by zero, when window is too short // (you cant make a window of zero width). if(h == 0) h = 1; float ratio = 1.0* w / h; // Reset the coordinate system before modifying glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Set the viewport to be the entire window glViewport(0, 0, w, h); // Set the correct perspective. gluPerspective(45, ratio, 1, 1000); glMatrixMode(GL_MODELVIEW); } //////////////////////////////////////////////////////////////////////////////// void printShaderLog(GLuint obj) { GLint infoLogLength = 0; GLsizei charsWritten = 0; GLchar *infoLog; glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &infoLogLength); if (infoLogLength > 0) { infoLog = (char *) malloc(infoLogLength); glGetShaderInfoLog(obj, infoLogLength, &charsWritten, infoLog); printf("%s\n",infoLog); free(infoLog); } } void printProgramLog(GLuint obj) { GLint infoLogLength = 0; GLsizei charsWritten = 0; GLchar *infoLog; glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &infoLogLength); if (infoLogLength > 0) { infoLog = (char *) malloc(infoLogLength); glGetProgramInfoLog(obj, infoLogLength, &charsWritten, infoLog); printf("%s\n",infoLog); free(infoLog); } } //////////////////////////////////////////////////////////////////////////////// void setBrickParams(GLuint p) { GLint loc; float bColor[3] = {1.0, 0.3, 0.2}; float mColor[3] = {0.85, 0.86, 0.84}; float bSize[2] = {0.30, 0.15}; float bPct[2] = {0.90, 0.85}; float mPct[2]; mPct[0] = 1.0 - bPct[0]; mPct[1] = 1.0 - bPct[1]; float lPos[3] = {0.0, 0.0, 4.0}; //maybe make this more generic later on loc = glGetUniformLocation(p,"BrickColor"); glUniform3fv(loc, 1, bColor); loc = glGetUniformLocation(p,"MortarColor"); glUniform3fv(loc, 1, mColor); loc = glGetUniformLocation(p,"BrickSize"); glUniform2fv(loc, 1, bSize); loc = glGetUniformLocation(p,"BrickPct"); glUniform2fv(loc, 1, bPct); loc = glGetUniformLocation(p,"MortarPct"); glUniform2fv(loc, 1, mPct); loc = glGetUniformLocation(p,"LightPosition"); glUniform3fv(loc, 1, lPos); } //////////////////////////////////////////////////////////////////////////////// void setToonParams(GLuint p) { GLint loc1,loc2,loc3,loc4; float specIntensity = 0.98; float sc[4] = {0.8,0.8,0.8,1.0}; float threshold[2] = {0.5,0.25}; float colors[12] = {0.4,0.4,0.8,1.0, 0.2,0.2,0.4,1.0, 0.1,0.1,0.1,1.0}; loc1 = glGetUniformLocation(p,"specIntensity"); glUniform1f(loc1,specIntensity); loc2 = glGetUniformLocation(p,"specColor"); //glUniform4f(loc2,sc[0],sc[1],sc[2],sc[3]); glUniform4fv(loc2,1,sc); loc3 = glGetUniformLocation(p,"t"); glUniform1fv(loc3,2,threshold); loc4 = glGetUniformLocation(p,"colors"); glUniform4fv(loc4,3,colors); } //////////////////////////////////////////////////////////////////////////////// float rotAmount = 0; void renderScene(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); gluLookAt(0.0,3.0,6.0, 0.0,0.0,-1.0, 0.0f,1.0f,0.0f); glLightfv(GL_LIGHT0, GL_POSITION, lpos); glRotatef(rotAmount,0,1,0); // draw the brick platform glUseProgram(ptbrick); setBrickParams(ptbrick); glutSolidCube(2); // draw the toon-shaded teapot glTranslatef(0,1.5,0); glUseProgram(pttoon); setToonParams(pttoon); glutSolidTeapot(1); rotAmount+= 0.1; glutSwapBuffers(); } //////////////////////////////////////////////////////////////////////////////// void processNormalKeys(unsigned char key, int x, int y) { if (key == 27) exit(0); } //////////////////////////////////////////////////////////////////////////////// GLuint setShaders(char * vert, char * frag) { GLuint v,f, pro; char *vs,*fs; v = glCreateShader(GL_VERTEX_SHADER); f = glCreateShader(GL_FRAGMENT_SHADER); vs = textFileRead(vert); fs = textFileRead(frag); const char * vv = vs; const char * ff = fs; glShaderSource(v, 1, &vv,NULL); glShaderSource(f, 1, &ff,NULL); free(vs);free(fs); glCompileShader(v); glCompileShader(f); printShaderLog(v); printShaderLog(f); pro = glCreateProgram(); glAttachShader(pro,v); glAttachShader(pro,f); glLinkProgram(pro); printProgramLog(pro); return(pro); } //////////////////////////////////////////////////////////////////////////////// int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); glutInitWindowPosition(100,100); glutInitWindowSize(320,320); glutCreateWindow("GLSL"); glutDisplayFunc(renderScene); glutIdleFunc(renderScene); glutReshapeFunc(changeSize); glutKeyboardFunc(processNormalKeys); glEnable(GL_DEPTH_TEST); glClearColor(0.0,0.0,0.0,1.0); glewInit(); if (GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader) printf("Ready for GLSL\n"); else { printf("No GLSL support\n"); exit(1); } ptbrick = setShaders("./brick.vert", "./brick.frag"); pttoon = setShaders("./toon.vert", "./toon3.frag"); glutMainLoop(); return 0; }