diff options
Diffstat (limited to 'progs/glsl')
| -rw-r--r-- | progs/glsl/CH11-bumpmap.frag.txt | 41 | ||||
| -rw-r--r-- | progs/glsl/CH11-bumpmap.vert.txt | 38 | ||||
| -rw-r--r-- | progs/glsl/CH11-toyball.frag.txt | 79 | ||||
| -rw-r--r-- | progs/glsl/CH11-toyball.vert.txt | 20 | ||||
| -rw-r--r-- | progs/glsl/CH18-mandel.frag.txt | 4 | ||||
| -rw-r--r-- | progs/glsl/Makefile | 12 | ||||
| -rw-r--r-- | progs/glsl/bump.c | 348 | ||||
| -rw-r--r-- | progs/glsl/toyball.c | 316 | 
8 files changed, 854 insertions, 4 deletions
diff --git a/progs/glsl/CH11-bumpmap.frag.txt b/progs/glsl/CH11-bumpmap.frag.txt new file mode 100644 index 0000000000..063576f5a3 --- /dev/null +++ b/progs/glsl/CH11-bumpmap.frag.txt @@ -0,0 +1,41 @@ +// +// Fragment shader for procedural bumps +// +// Authors: John Kessenich, Randi Rost +// +// Copyright (c) 2002-2006 3Dlabs Inc. Ltd.  +// +// See 3Dlabs-License.txt for license information +// + +varying vec3 LightDir; +varying vec3 EyeDir; + +uniform vec3  SurfaceColor;    // = (0.7, 0.6, 0.18) +uniform float BumpDensity;     // = 16.0 +uniform float BumpSize;        // = 0.15 +uniform float SpecularFactor;  // = 0.5 + +void main() +{ +    vec3 litColor; +    vec2 c = BumpDensity * gl_TexCoord[0].st; +    vec2 p = fract(c) - vec2(0.5); + +    float d, f; +    d = p.x * p.x + p.y * p.y; +    f = 1.0 / sqrt(d + 1.0); + +    if (d >= BumpSize) +        { p = vec2(0.0); f = 1.0; } + +    vec3 normDelta = vec3(p.x, p.y, 1.0) * f; +    litColor = SurfaceColor * max(dot(normDelta, LightDir), 0.0); +    vec3 reflectDir = reflect(LightDir, normDelta); +     +    float spec = max(dot(EyeDir, reflectDir), 0.0); +    spec *= SpecularFactor; +    litColor = min(litColor + spec, vec3(1.0)); + +    gl_FragColor = vec4(litColor, 1.0); +} diff --git a/progs/glsl/CH11-bumpmap.vert.txt b/progs/glsl/CH11-bumpmap.vert.txt new file mode 100644 index 0000000000..d3d19f62ac --- /dev/null +++ b/progs/glsl/CH11-bumpmap.vert.txt @@ -0,0 +1,38 @@ +// +// Vertex shader for procedural bumps +// +// Authors: Randi Rost, John Kessenich +// +// Copyright (c) 2002-2006 3Dlabs Inc. Ltd.  +// +// See 3Dlabs-License.txt for license information +// + +varying vec3 LightDir; +varying vec3 EyeDir; + +uniform vec3 LightPosition; + +attribute vec3 Tangent; + +void main()  +{ +    EyeDir         = vec3(gl_ModelViewMatrix * gl_Vertex); +    gl_Position    = ftransform(); +    gl_TexCoord[0] = gl_MultiTexCoord0; + +    vec3 n = normalize(gl_NormalMatrix * gl_Normal); +    vec3 t = normalize(gl_NormalMatrix * Tangent); +    vec3 b = cross(n, t); + +    vec3 v; +    v.x = dot(LightPosition, t); +    v.y = dot(LightPosition, b); +    v.z = dot(LightPosition, n); +    LightDir = normalize(v); + +    v.x = dot(EyeDir, t); +    v.y = dot(EyeDir, b); +    v.z = dot(EyeDir, n); +    EyeDir = normalize(v); +} diff --git a/progs/glsl/CH11-toyball.frag.txt b/progs/glsl/CH11-toyball.frag.txt new file mode 100644 index 0000000000..cf9129ee1d --- /dev/null +++ b/progs/glsl/CH11-toyball.frag.txt @@ -0,0 +1,79 @@ +// +// Fragment shader for procedurally generated toy ball +// +// Author: Bill Licea-Kane +// +// Copyright (c) 2002-2003 ATI Research  +// +// See ATI-License.txt for license information +// + +varying vec4 ECposition;   // surface position in eye coordinates +varying vec4 ECballCenter; // ball center in eye coordinates + +uniform vec4  LightDir;     // light direction, should be normalized +uniform vec4  HVector;      // reflection vector for infinite light source +uniform vec4  SpecularColor; +uniform vec4  Red, Yellow, Blue; + +uniform vec4  HalfSpace0;   // half-spaces used to define star pattern +uniform vec4  HalfSpace1; +uniform vec4  HalfSpace2; +uniform vec4  HalfSpace3; +uniform vec4  HalfSpace4; + +uniform float InOrOutInit;  // = -3 +uniform float StripeWidth;  // = 0.3 +uniform float FWidth;       // = 0.005 + +void main() +{ +    vec4  normal;              // Analytically computed normal +    vec4  p;                   // Point in shader space +    vec4  surfColor;           // Computed color of the surface +    float intensity;           // Computed light intensity +    vec4  distance;            // Computed distance values +    float inorout;             // Counter for computing star pattern + +    p.xyz = normalize(ECposition.xyz - ECballCenter.xyz);    // Calculate p +    p.w   = 1.0; + +    inorout = InOrOutInit;     // initialize inorout to -3 + +    distance[0] = dot(p, HalfSpace0); +    distance[1] = dot(p, HalfSpace1); +    distance[2] = dot(p, HalfSpace2); +    distance[3] = dot(p, HalfSpace3); + +#if 1 +    distance = smoothstep(-FWidth, FWidth, distance); +    inorout += dot(distance, vec4(1.0)); + +    distance.x = dot(p, HalfSpace4); +    distance.y = StripeWidth - abs(p.z); +    distance = smoothstep(-FWidth, FWidth, distance); +    inorout += distance.x; + +    inorout = clamp(inorout, 0.0, 1.0); + +    surfColor = mix(Yellow, Red, inorout); +    surfColor = mix(surfColor, Blue, distance.y); + +    // normal = point on surface for sphere at (0,0,0) +    normal = p; + +    // Per fragment diffuse lighting +    intensity  = 0.2; // ambient +    intensity += 0.8 * clamp(dot(LightDir, normal), 0.0, 1.0); +    surfColor *= intensity; + +    // Per fragment specular lighting +    intensity  = clamp(dot(HVector, normal), 0.0, 1.0); +    intensity  = pow(intensity, SpecularColor.a); +    surfColor += SpecularColor * intensity; + +    gl_FragColor = surfColor; +#else +    gl_FragColor = distance; +#endif +} diff --git a/progs/glsl/CH11-toyball.vert.txt b/progs/glsl/CH11-toyball.vert.txt new file mode 100644 index 0000000000..21795c17cd --- /dev/null +++ b/progs/glsl/CH11-toyball.vert.txt @@ -0,0 +1,20 @@ +// +// Fragment shader for procedurally generated toy ball +// +// Author: Bill Licea-Kane +// +// Copyright (c) 2002-2003 ATI Research  +// +// See ATI-License.txt for license information +// + +varying vec4 ECposition;   // surface position in eye coordinates +varying vec4 ECballCenter; // ball center in eye coordinates +uniform vec4 BallCenter;   // ball center in modelling coordinates + +void main() +{  +    ECposition   = gl_ModelViewMatrix * gl_Vertex; +    ECballCenter = gl_ModelViewMatrix * BallCenter; +    gl_Position  = ftransform(); +}
\ No newline at end of file diff --git a/progs/glsl/CH18-mandel.frag.txt b/progs/glsl/CH18-mandel.frag.txt index 3769cffdc8..a472d81252 100644 --- a/progs/glsl/CH18-mandel.frag.txt +++ b/progs/glsl/CH18-mandel.frag.txt @@ -30,8 +30,8 @@ void main()      float r2 = 0.0;      float iter; -    for (iter = 0.0; iter < MaxIterations && r2 < 4.0; ++iter) -//nv:    for (iter = 0.0; iter < 12 && r2 < 4.0; ++iter) +//    for (iter = 0.0; iter < MaxIterations && r2 < 4.0; ++iter) +    for (iter = 0.0; iter < 12 && r2 < 4.0; ++iter)      {          float tempreal = real; diff --git a/progs/glsl/Makefile b/progs/glsl/Makefile index 174f5bebe4..fa7f191986 100644 --- a/progs/glsl/Makefile +++ b/progs/glsl/Makefile @@ -15,7 +15,9 @@ LIB_DEP = $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) $(TOP)/$(LIB_DIR)/$(GLU_LIB_NAME) $(T  PROGS = \  	brick \ -	mandelbrot +	bump \ +	mandelbrot \ +	toyball  ##### RULES ##### @@ -33,7 +35,9 @@ PROGS = \  default: $(PROGS) -$(PROGS): + + +##### Extra dependencies  extfuncs.h:  $(TOP)/progs/util/extfuncs.h  	cp $< . @@ -41,8 +45,12 @@ extfuncs.h:  $(TOP)/progs/util/extfuncs.h  brick.c: extfuncs.h +bump.c: extfuncs.h +  mandelbrot.c: extfuncs.h +toyball.c: extfuncs.h +  clean:  	-rm -f $(PROGS) diff --git a/progs/glsl/bump.c b/progs/glsl/bump.c new file mode 100644 index 0000000000..b71c3af970 --- /dev/null +++ b/progs/glsl/bump.c @@ -0,0 +1,348 @@ +/** + * Procedural Bump Mapping demo.  Uses the example shaders from + * chapter 11 of the OpenGL Shading Language "orange" book. + * 16 Jan 2007 + */ + +#include <assert.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <GL/glut.h> +#include <GL/glu.h> +#include <GL/glext.h> +#include "extfuncs.h" + + +static char *FragProgFile = "CH11-bumpmap.frag.txt"; +static char *VertProgFile = "CH11-bumpmap.vert.txt"; + +/* program/shader objects */ +static GLuint fragShader; +static GLuint vertShader; +static GLuint program; + + +struct uniform_info { +   const char *name; +   GLuint size; +   GLint location; +   GLfloat value[4]; +}; + +static struct uniform_info Uniforms[] = { +   { "LightPosition",       3, -1, { 0.57737, 0.57735, 0.57735, 0.0 } }, +   { "SurfaceColor",        3, -1, { 0.8, 0.8, 0.2, 0 } }, +   { "BumpDensity",         1, -1, { 16.0, 0, 0, 0 } }, +   { "BumpSize",            1, -1, { 0.15, 0, 0, 0 } }, +   { "SpecularFactor",      1, -1, { 0.5, 0, 0, 0 } }, +   { NULL, 0, 0, { 0, 0, 0, 0 } } +}; + +static GLint win = 0; + +static GLfloat xRot = 0.0f, yRot = 0.0f, zRot = 0.0f; + +static GLuint tangentAttrib; + + +static void +CheckError(int line) +{ +   GLenum err = glGetError(); +   if (err) { +      printf("GL Error %s (0x%x) at line %d\n", +             gluErrorString(err), (int) err, line); +   } +} + +/* + * Draw a square, specifying normal and tangent vectors. + */ +static void +Square(GLfloat size) +{ +   glNormal3f(0, 0, 1); +   glVertexAttrib3f_func(tangentAttrib, 1, 0, 0); +   glBegin(GL_POLYGON); +   glTexCoord2f(0, 0);  glVertex2f(-size, -size); +   glTexCoord2f(1, 0);  glVertex2f( size, -size); +   glTexCoord2f(1, 1);  glVertex2f( size,  size); +   glTexCoord2f(0, 1);  glVertex2f(-size,  size); +   glEnd(); +} + + +static void +Redisplay(void) +{ +   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +    +   glPushMatrix(); +   glRotatef(xRot, 1.0f, 0.0f, 0.0f); +   glRotatef(yRot, 0.0f, 1.0f, 0.0f); +   glRotatef(zRot, 0.0f, 0.0f, 1.0f); + +   Square(2.0); + +   glPopMatrix(); + +   glFinish(); +   glFlush(); + +   CheckError(__LINE__); + +   glutSwapBuffers(); +} + + +static void +Reshape(int width, int height) +{ +   glViewport(0, 0, width, height); +   glMatrixMode(GL_PROJECTION); +   glLoadIdentity(); +   glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0); +   glMatrixMode(GL_MODELVIEW); +   glLoadIdentity(); +   glTranslatef(0.0f, 0.0f, -15.0f); +} + + +static void +CleanUp(void) +{ +   glDeleteShader_func(fragShader); +   glDeleteShader_func(vertShader); +   glDeleteProgram_func(program); +   glutDestroyWindow(win); +} + + +static void +Key(unsigned char key, int x, int y) +{ +   const GLfloat step = 2.0; +  (void) x; +  (void) y; + +   switch(key) { +   case 'z': +      zRot += step; +      break; +   case 'Z': +      zRot -= step; +      break; +   case 27: +      CleanUp(); +      exit(0); +      break; +   } +   glutPostRedisplay(); +} + + +static void +SpecialKey(int key, int x, int y) +{ +   const GLfloat step = 2.0; + +  (void) x; +  (void) y; + +   switch(key) { +   case GLUT_KEY_UP: +      xRot += step; +      break; +   case GLUT_KEY_DOWN: +      xRot -= step; +      break; +   case GLUT_KEY_LEFT: +      yRot -= step; +      break; +   case GLUT_KEY_RIGHT: +      yRot += step; +      break; +   } +   glutPostRedisplay(); +} + + + +static void +LoadAndCompileShader(GLuint shader, const char *text) +{ +   GLint stat; + +   glShaderSource_func(shader, 1, (const GLchar **) &text, NULL); + +   glCompileShader_func(shader); + +   glGetShaderiv_func(shader, GL_COMPILE_STATUS, &stat); +   if (!stat) { +      GLchar log[1000]; +      GLsizei len; +      glGetShaderInfoLog_func(shader, 1000, &len, log); +      fprintf(stderr, "brick: problem compiling shader: %s\n", log); +      exit(1); +   } +   else { +      printf("Shader compiled OK\n"); +   } +} + + +/** + * Read a shader from a file. + */ +static void +ReadShader(GLuint shader, const char *filename) +{ +   const int max = 100*1000; +   int n; +   char *buffer = (char*) malloc(max); +   FILE *f = fopen(filename, "r"); +   if (!f) { +      fprintf(stderr, "brick: Unable to open shader file %s\n", filename); +      exit(1); +   } + +   n = fread(buffer, 1, max, f); +   printf("brick: read %d bytes from shader file %s\n", n, filename); +   if (n > 0) { +      buffer[n] = 0; +      LoadAndCompileShader(shader, buffer); +   } + +   fclose(f); +   free(buffer); +} + + +static void +CheckLink(GLuint prog) +{ +   GLint stat; +   glGetProgramiv_func(prog, GL_LINK_STATUS, &stat); +   if (!stat) { +      GLchar log[1000]; +      GLsizei len; +      glGetProgramInfoLog_func(prog, 1000, &len, log); +      fprintf(stderr, "Linker error:\n%s\n", log); +   } +   else { +      fprintf(stderr, "Link success!\n"); +   } +} + + +static void +Init(void) +{ +   const char *version; +   GLint i; + +   version = (const char *) glGetString(GL_VERSION); +   if (version[0] != '2' || version[1] != '.') { +      printf("Warning: this program expects OpenGL 2.0\n"); +      /*exit(1);*/ +   } +   printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER)); + +   GetExtensionFuncs(); + +   vertShader = glCreateShader_func(GL_VERTEX_SHADER); +   ReadShader(vertShader, VertProgFile); + +   fragShader = glCreateShader_func(GL_FRAGMENT_SHADER); +   ReadShader(fragShader, FragProgFile); + +   program = glCreateProgram_func(); +   glAttachShader_func(program, fragShader); +   glAttachShader_func(program, vertShader); +   glLinkProgram_func(program); +   CheckLink(program); +   glUseProgram_func(program); + +   assert(glIsProgram_func(program)); +   assert(glIsShader_func(fragShader)); +   assert(glIsShader_func(vertShader)); + +   assert(glGetError() == 0); + +   CheckError(__LINE__); + +   for (i = 0; Uniforms[i].name; i++) { +      Uniforms[i].location +         = glGetUniformLocation_func(program, Uniforms[i].name); +      printf("Uniform %s location: %d\n", Uniforms[i].name, +             Uniforms[i].location); +      switch (Uniforms[i].size) { +      case 1: +         glUniform1fv_func(Uniforms[i].location, 1, Uniforms[i].value); +         break; +      case 2: +         glUniform2fv_func(Uniforms[i].location, 1, Uniforms[i].value); +         break; +      case 3: +         glUniform3fv_func(Uniforms[i].location, 1, Uniforms[i].value); +         break; +      case 4: +         glUniform4fv_func(Uniforms[i].location, 1, Uniforms[i].value); +         break; +      default: +         abort(); +      } +   } + +   CheckError(__LINE__); + +   tangentAttrib = glGetAttribLocation_func(program, "Tangent"); +   printf("Tangent Attrib: %d\n", tangentAttrib); + +   assert(tangentAttrib >= 0); + +   CheckError(__LINE__); + +   glClearColor(0.4f, 0.4f, 0.8f, 0.0f); + +   glEnable(GL_DEPTH_TEST); + +   glColor3f(1, 0, 0); +} + + +static void +ParseOptions(int argc, char *argv[]) +{ +   int i; +   for (i = 1; i < argc; i++) { +      if (strcmp(argv[i], "-fs") == 0) { +         FragProgFile = argv[i+1]; +      } +      else if (strcmp(argv[i], "-vs") == 0) { +         VertProgFile = argv[i+1]; +      } +   } +} + + +int +main(int argc, char *argv[]) +{ +   glutInit(&argc, argv); +   glutInitWindowPosition( 0, 0); +   glutInitWindowSize(400, 400); +   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); +   win = glutCreateWindow(argv[0]); +   glutReshapeFunc(Reshape); +   glutKeyboardFunc(Key); +   glutSpecialFunc(SpecialKey); +   glutDisplayFunc(Redisplay); +   ParseOptions(argc, argv); +   Init(); +   glutMainLoop(); +   return 0; +} + diff --git a/progs/glsl/toyball.c b/progs/glsl/toyball.c new file mode 100644 index 0000000000..2d3462fc61 --- /dev/null +++ b/progs/glsl/toyball.c @@ -0,0 +1,316 @@ +/** + * "Toy Ball" shader demo.  Uses the example shaders from + * chapter 11 of the OpenGL Shading Language "orange" book. + * 16 Jan 2007 + */ + +#include <assert.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <GL/gl.h> +#include <GL/glut.h> +#include <GL/glext.h> +#include "extfuncs.h" + + +static char *FragProgFile = "CH11-toyball.frag.txt"; +static char *VertProgFile = "CH11-toyball.vert.txt"; + +/* program/shader objects */ +static GLuint fragShader; +static GLuint vertShader; +static GLuint program; + + +struct uniform_info { +   const char *name; +   GLuint size; +   GLint location; +   GLfloat value[4]; +}; + +static struct uniform_info Uniforms[] = { +   { "LightDir",       4, -1, { 0.57737, 0.57735, 0.57735, 0.0 } }, +   { "HVector",        4, -1, { 0.32506, 0.32506, 0.88808, 0.0 } }, +   { "BallCenter",     4, -1, { 0.0, 0.0, 0.0, 1.0 } }, +   { "SpecularColor",  4, -1, { 0.4, 0.4, 0.4, 60.0 } }, +   { "Red",            4, -1, { 0.6, 0.0, 0.0, 1.0 } }, +   { "Blue",           4, -1, { 0.0, 0.3, 0.6, 1.0 } }, +   { "Yellow",         4, -1, { 0.6, 0.5, 0.0, 1.0 } }, +   { "HalfSpace0",     4, -1, { 1.0, 0.0, 0.0, 0.2 } }, +   { "HalfSpace1",     4, -1, { 0.309016994, 0.951056516, 0.0, 0.2 } }, +   { "HalfSpace2",     4, -1, { -0.809016994, 0.587785252, 0.0, 0.2 } }, +   { "HalfSpace3",     4, -1, { -0.809016994, -0.587785252, 0.0, 0.2 } }, +   { "HalfSpace4",     4, -1, { 0.309116994, -0.951056516, 0.0, 0.2 } }, +   { "InOrOutInit",    1, -1, { -3.0, 0, 0, 0 } }, +   { "StripeWidth",    1, -1, {  0.3, 0, 0, 0 } }, +   { "FWidth",         1, -1, { 0.005, 0, 0, 0 } }, +   { NULL, 0, 0, { 0, 0, 0, 0 } } +}; + +static GLint win = 0; + +static GLfloat xRot = 0.0f, yRot = 0.0f, zRot = 0.0f; + + +static void +Redisplay(void) +{ +   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +    +   glPushMatrix(); +   glRotatef(xRot, 1.0f, 0.0f, 0.0f); +   glRotatef(yRot, 0.0f, 1.0f, 0.0f); +   glRotatef(zRot, 0.0f, 0.0f, 1.0f); + +   glutSolidSphere(2.0, 20, 10); + +   glPopMatrix(); + +   glFinish(); +   glFlush(); +   glutSwapBuffers(); +} + + +static void +Reshape(int width, int height) +{ +   glViewport(0, 0, width, height); +   glMatrixMode(GL_PROJECTION); +   glLoadIdentity(); +   glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0); +   glMatrixMode(GL_MODELVIEW); +   glLoadIdentity(); +   glTranslatef(0.0f, 0.0f, -15.0f); +} + + +static void +CleanUp(void) +{ +   glDeleteShader_func(fragShader); +   glDeleteShader_func(vertShader); +   glDeleteProgram_func(program); +   glutDestroyWindow(win); +} + + +static void +Key(unsigned char key, int x, int y) +{ +   const GLfloat step = 2.0; +  (void) x; +  (void) y; + +   switch(key) { +   case 'z': +      zRot += step; +      break; +   case 'Z': +      zRot -= step; +      break; +   case 27: +      CleanUp(); +      exit(0); +      break; +   } +   glutPostRedisplay(); +} + + +static void +SpecialKey(int key, int x, int y) +{ +   const GLfloat step = 2.0; + +  (void) x; +  (void) y; + +   switch(key) { +   case GLUT_KEY_UP: +      xRot += step; +      break; +   case GLUT_KEY_DOWN: +      xRot -= step; +      break; +   case GLUT_KEY_LEFT: +      yRot -= step; +      break; +   case GLUT_KEY_RIGHT: +      yRot += step; +      break; +   } +   glutPostRedisplay(); +} + + + +static void +LoadAndCompileShader(GLuint shader, const char *text) +{ +   GLint stat; + +   glShaderSource_func(shader, 1, (const GLchar **) &text, NULL); + +   glCompileShader_func(shader); + +   glGetShaderiv_func(shader, GL_COMPILE_STATUS, &stat); +   if (!stat) { +      GLchar log[1000]; +      GLsizei len; +      glGetShaderInfoLog_func(shader, 1000, &len, log); +      fprintf(stderr, "brick: problem compiling shader: %s\n", log); +      exit(1); +   } +   else { +      printf("Shader compiled OK\n"); +   } +} + + +/** + * Read a shader from a file. + */ +static void +ReadShader(GLuint shader, const char *filename) +{ +   const int max = 100*1000; +   int n; +   char *buffer = (char*) malloc(max); +   FILE *f = fopen(filename, "r"); +   if (!f) { +      fprintf(stderr, "brick: Unable to open shader file %s\n", filename); +      exit(1); +   } + +   n = fread(buffer, 1, max, f); +   printf("brick: read %d bytes from shader file %s\n", n, filename); +   if (n > 0) { +      buffer[n] = 0; +      LoadAndCompileShader(shader, buffer); +   } + +   fclose(f); +   free(buffer); +} + + +static void +CheckLink(GLuint prog) +{ +   GLint stat; +   glGetProgramiv_func(prog, GL_LINK_STATUS, &stat); +   if (!stat) { +      GLchar log[1000]; +      GLsizei len; +      glGetProgramInfoLog_func(prog, 1000, &len, log); +      fprintf(stderr, "Linker error:\n%s\n", log); +   } +   else { +      fprintf(stderr, "Link success!\n"); +   } +} + + +static void +Init(void) +{ +   const char *version; +   GLint i; + +   version = (const char *) glGetString(GL_VERSION); +   if (version[0] != '2' || version[1] != '.') { +      printf("Warning: this program expects OpenGL 2.0\n"); +      /*exit(1);*/ +   } +   printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER)); + +   GetExtensionFuncs(); + +   vertShader = glCreateShader_func(GL_VERTEX_SHADER); +   ReadShader(vertShader, VertProgFile); + +   fragShader = glCreateShader_func(GL_FRAGMENT_SHADER); +   ReadShader(fragShader, FragProgFile); + +   program = glCreateProgram_func(); +   glAttachShader_func(program, fragShader); +   glAttachShader_func(program, vertShader); +   glLinkProgram_func(program); +   CheckLink(program); +   glUseProgram_func(program); + +   assert(glIsProgram_func(program)); +   assert(glIsShader_func(fragShader)); +   assert(glIsShader_func(vertShader)); + + +   for (i = 0; Uniforms[i].name; i++) { +      Uniforms[i].location +         = glGetUniformLocation_func(program, Uniforms[i].name); +      printf("Uniform %s location: %d\n", Uniforms[i].name, +             Uniforms[i].location); +      switch (Uniforms[i].size) { +      case 1: +         glUniform1fv_func(Uniforms[i].location, 1, Uniforms[i].value); +         break; +      case 2: +         glUniform2fv_func(Uniforms[i].location, 1, Uniforms[i].value); +         break; +      case 3: +         glUniform3fv_func(Uniforms[i].location, 1, Uniforms[i].value); +         break; +      case 4: +         glUniform4fv_func(Uniforms[i].location, 1, Uniforms[i].value); +         break; +      default: +         abort(); +      } +   } + +   assert(glGetError() == 0); + +   glClearColor(0.4f, 0.4f, 0.8f, 0.0f); + +   glEnable(GL_DEPTH_TEST); + +   glColor3f(1, 0, 0); +} + + +static void +ParseOptions(int argc, char *argv[]) +{ +   int i; +   for (i = 1; i < argc; i++) { +      if (strcmp(argv[i], "-fs") == 0) { +         FragProgFile = argv[i+1]; +      } +      else if (strcmp(argv[i], "-vs") == 0) { +         VertProgFile = argv[i+1]; +      } +   } +} + + +int +main(int argc, char *argv[]) +{ +   glutInit(&argc, argv); +   glutInitWindowPosition( 0, 0); +   glutInitWindowSize(400, 400); +   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); +   win = glutCreateWindow(argv[0]); +   glutReshapeFunc(Reshape); +   glutKeyboardFunc(Key); +   glutSpecialFunc(SpecialKey); +   glutDisplayFunc(Redisplay); +   ParseOptions(argc, argv); +   Init(); +   glutMainLoop(); +   return 0; +} +  | 
