1/** 2 * Test linking of multiple compilation units. 3 * Brian Paul 4 * 28 March 2009 5 */ 6 7#include <assert.h> 8#include <string.h> 9#include <stdio.h> 10#include <stdlib.h> 11#include <math.h> 12#include <GL/glew.h> 13#include "glut_wrap.h" 14#include "shaderutil.h" 15 16 17static GLfloat diffuse[4] = { 0.5f, 1.0f, 0.5f, 1.0f }; 18static GLfloat specular[4] = { 0.8f, 0.8f, 0.8f, 1.0f }; 19static GLfloat lightPos[4] = { 0.0f, 10.0f, 20.0f, 0.0f }; 20static GLfloat delta = 1.0f; 21 22static GLuint VertShader1; 23static GLuint VertShader2; 24static GLuint FragShader1; 25static GLuint FragShader2; 26static GLuint Program; 27 28static GLint uDiffuse; 29static GLint uSpecular; 30static GLint uTexture; 31 32static GLint Win = 0; 33static GLboolean anim = GL_TRUE; 34 35 36 37static const char *FragShaderSource1 = 38 "float compute_dotprod(const vec3 normal) \n" 39 "{ \n" 40 " float dotProd = max(dot(gl_LightSource[0].position.xyz, \n" 41 " normalize(normal)), 0.0); \n" 42 " return dotProd; \n" 43 "} \n"; 44 45static const char *FragShaderSource2 = 46 "uniform vec4 diffuse;\n" 47 "uniform vec4 specular;\n" 48 "varying vec3 normal;\n" 49 "\n" 50 "// external function \n" 51 "float compute_dotprod(const vec3 normal); \n" 52 "\n" 53 "void main() \n" 54 "{ \n" 55 " float dotProd = compute_dotprod(normal); \n" 56 " gl_FragColor = diffuse * dotProd + specular * pow(dotProd, 20.0); \n" 57 "} \n"; 58 59 60static const char *VertShaderSource1 = 61 "vec3 compute_normal() \n" 62 "{ \n" 63 " return gl_NormalMatrix * gl_Normal; \n" 64 "} \n"; 65 66static const char *VertShaderSource2 = 67 "varying vec3 normal;\n" 68 "\n" 69 "// external function \n" 70 "vec3 compute_normal(); \n" 71 "\n" 72 "void main() \n" 73 "{ \n" 74 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; \n" 75 " normal = compute_normal(); \n" 76 "} \n"; 77 78 79static void 80normalize(GLfloat *dst, const GLfloat *src) 81{ 82 GLfloat len = sqrt(src[0] * src[0] + src[1] * src[1] + src[2] * src[2]); 83 dst[0] = src[0] / len; 84 dst[1] = src[1] / len; 85 dst[2] = src[2] / len; 86 dst[3] = src[3]; 87} 88 89 90static void 91Redisplay(void) 92{ 93 GLfloat vec[4]; 94 95 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 96 97 /* update light position */ 98 normalize(vec, lightPos); 99 glLightfv(GL_LIGHT0, GL_POSITION, vec); 100 101 glutSolidSphere(2.0, 10, 5); 102 103 glutSwapBuffers(); 104} 105 106 107static void 108Idle(void) 109{ 110 lightPos[0] += delta; 111 if (lightPos[0] > 25.0f || lightPos[0] < -25.0f) 112 delta = -delta; 113 glutPostRedisplay(); 114} 115 116 117static void 118Reshape(int width, int height) 119{ 120 glViewport(0, 0, width, height); 121 glMatrixMode(GL_PROJECTION); 122 glLoadIdentity(); 123 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0); 124 glMatrixMode(GL_MODELVIEW); 125 glLoadIdentity(); 126 glTranslatef(0.0f, 0.0f, -15.0f); 127} 128 129 130static void 131CleanUp(void) 132{ 133 glDeleteShader(VertShader1); 134 glDeleteShader(VertShader2); 135 glDeleteShader(FragShader1); 136 glDeleteShader(FragShader2); 137 glDeleteProgram(Program); 138 glutDestroyWindow(Win); 139} 140 141 142static void 143Key(unsigned char key, int x, int y) 144{ 145 (void) x; 146 (void) y; 147 148 switch(key) { 149 case ' ': 150 case 'a': 151 anim = !anim; 152 if (anim) 153 glutIdleFunc(Idle); 154 else 155 glutIdleFunc(NULL); 156 break; 157 case 'x': 158 lightPos[0] -= 1.0f; 159 break; 160 case 'X': 161 lightPos[0] += 1.0f; 162 break; 163 case 27: 164 CleanUp(); 165 exit(0); 166 break; 167 } 168 glutPostRedisplay(); 169} 170 171 172static void 173CheckLink(GLuint prog) 174{ 175 GLint stat; 176 glGetProgramiv(prog, GL_LINK_STATUS, &stat); 177 if (!stat) { 178 GLchar log[1000]; 179 GLsizei len; 180 glGetProgramInfoLog(prog, 1000, &len, log); 181 fprintf(stderr, "Linker error:\n%s\n", log); 182 } 183} 184 185 186static void 187Init(void) 188{ 189 if (!ShadersSupported()) 190 exit(1); 191 192 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER)); 193 194 VertShader1 = CompileShaderText(GL_VERTEX_SHADER, VertShaderSource1); 195 VertShader2 = CompileShaderText(GL_VERTEX_SHADER, VertShaderSource2); 196 FragShader1 = CompileShaderText(GL_FRAGMENT_SHADER, FragShaderSource1); 197 FragShader2 = CompileShaderText(GL_FRAGMENT_SHADER, FragShaderSource2); 198 199 Program = glCreateProgram(); 200 glAttachShader(Program, VertShader1); 201 glAttachShader(Program, VertShader2); 202 glAttachShader(Program, FragShader1); 203 glAttachShader(Program, FragShader2); 204 205 glLinkProgram(Program); 206 207 CheckLink(Program); 208 209 glUseProgram(Program); 210 211 uDiffuse = glGetUniformLocation(Program, "diffuse"); 212 uSpecular = glGetUniformLocation(Program, "specular"); 213 uTexture = glGetUniformLocation(Program, "texture"); 214 printf("DiffusePos %d SpecularPos %d TexturePos %d\n", 215 uDiffuse, uSpecular, uTexture); 216 217 glUniform4fv(uDiffuse, 1, diffuse); 218 glUniform4fv(uSpecular, 1, specular); 219 220 glClearColor(0.3f, 0.3f, 0.3f, 0.0f); 221 glEnable(GL_DEPTH_TEST); 222 223 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse); 224 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); 225 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 10.0f); 226 227 assert(glIsProgram(Program)); 228 assert(glIsShader(VertShader1)); 229 assert(glIsShader(VertShader2)); 230 assert(glIsShader(FragShader1)); 231 assert(glIsShader(FragShader2)); 232 233 glColor3f(1, 0, 0); 234} 235 236 237int 238main(int argc, char *argv[]) 239{ 240 glutInit(&argc, argv); 241 glutInitWindowSize(300, 300); 242 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); 243 Win = glutCreateWindow(argv[0]); 244 glewInit(); 245 glutReshapeFunc(Reshape); 246 glutKeyboardFunc(Key); 247 glutDisplayFunc(Redisplay); 248 if (anim) 249 glutIdleFunc(Idle); 250 Init(); 251 glutMainLoop(); 252 return 0; 253} 254 255 256