diff options
Diffstat (limited to 'progs/glsl')
-rw-r--r-- | progs/glsl/CH06-brick.frag.txt | 36 | ||||
-rw-r--r-- | progs/glsl/CH06-brick.vert.txt | 41 | ||||
-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 | 75 | ||||
-rw-r--r-- | progs/glsl/CH11-toyball.vert.txt | 24 | ||||
-rw-r--r-- | progs/glsl/CH18-mandel.frag.txt | 55 | ||||
-rw-r--r-- | progs/glsl/CH18-mandel.vert.txt | 35 | ||||
-rw-r--r-- | progs/glsl/Makefile | 74 | ||||
-rw-r--r-- | progs/glsl/brick.c | 311 | ||||
-rw-r--r-- | progs/glsl/bump.c | 411 | ||||
-rw-r--r-- | progs/glsl/cubemap.frag.txt | 18 | ||||
-rw-r--r-- | progs/glsl/mandelbrot.c | 328 | ||||
-rw-r--r-- | progs/glsl/noise.c | 297 | ||||
-rw-r--r-- | progs/glsl/reflect.vert.txt | 19 | ||||
-rw-r--r-- | progs/glsl/shadowtex.frag.txt | 21 | ||||
-rw-r--r-- | progs/glsl/simple.vert.txt | 9 | ||||
-rw-r--r-- | progs/glsl/texdemo1.c | 570 | ||||
-rw-r--r-- | progs/glsl/toyball.c | 339 |
19 files changed, 2742 insertions, 0 deletions
diff --git a/progs/glsl/CH06-brick.frag.txt b/progs/glsl/CH06-brick.frag.txt new file mode 100644 index 0000000000..06ef04e3af --- /dev/null +++ b/progs/glsl/CH06-brick.frag.txt @@ -0,0 +1,36 @@ +// +// Fragment shader for procedural bricks +// +// Authors: Dave Baldwin, Steve Koren, Randi Rost +// based on a shader by Darwyn Peachey +// +// Copyright (c) 2002-2006 3Dlabs Inc. Ltd. +// +// See 3Dlabs-License.txt for license information +// + +uniform vec3 BrickColor, MortarColor; +uniform vec2 BrickSize; +uniform vec2 BrickPct; + +varying vec2 MCposition; +varying float LightIntensity; + +void main() +{ + vec3 color; + vec2 position, useBrick; + + position = MCposition / BrickSize; + + if (fract(position.y * 0.5) > 0.5) + position.x += 0.5; + + position = fract(position); + + useBrick = step(position, BrickPct); + + color = mix(MortarColor, BrickColor, useBrick.x * useBrick.y); + color *= LightIntensity; + gl_FragColor = vec4(color, 1.0); +} diff --git a/progs/glsl/CH06-brick.vert.txt b/progs/glsl/CH06-brick.vert.txt new file mode 100644 index 0000000000..e95e6f42f0 --- /dev/null +++ b/progs/glsl/CH06-brick.vert.txt @@ -0,0 +1,41 @@ +// +// Vertex shader for procedural bricks +// +// Authors: Dave Baldwin, Steve Koren, Randi Rost +// based on a shader by Darwyn Peachey +// +// Copyright (c) 2002-2006 3Dlabs Inc. Ltd. +// +// See 3Dlabs-License.txt for license information +// + +uniform vec3 LightPosition; + +const float SpecularContribution = 0.3; +const float DiffuseContribution = 1.0 - SpecularContribution; + +varying float LightIntensity; +varying vec2 MCposition; + +void main() +{ + vec3 ecPosition = vec3(gl_ModelViewMatrix * gl_Vertex); + vec3 tnorm = normalize(gl_NormalMatrix * gl_Normal); + vec3 lightVec = normalize(LightPosition - ecPosition); + vec3 reflectVec = reflect(-lightVec, tnorm); + vec3 viewVec = normalize(-ecPosition); + float diffuse = max(dot(lightVec, tnorm), 0.0); + float spec = 0.0; + + if (diffuse > 0.0) + { + spec = max(dot(reflectVec, viewVec), 0.0); + spec = pow(spec, 16.0); + } + + LightIntensity = DiffuseContribution * diffuse + + SpecularContribution * spec; + + MCposition = gl_Vertex.xy; + gl_Position = ftransform(); +} 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..90ec1c27fc --- /dev/null +++ b/progs/glsl/CH11-toyball.frag.txt @@ -0,0 +1,75 @@ +// +// 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); + + 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; +} diff --git a/progs/glsl/CH11-toyball.vert.txt b/progs/glsl/CH11-toyball.vert.txt new file mode 100644 index 0000000000..b7da3ac839 --- /dev/null +++ b/progs/glsl/CH11-toyball.vert.txt @@ -0,0 +1,24 @@ +// +// 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() +{ +//orig: ECposition = gl_ModelViewMatrix * gl_Vertex; + + ECposition = gl_TextureMatrix[0] * gl_Vertex; + ECposition = gl_ModelViewMatrix * ECposition; + + ECballCenter = gl_ModelViewMatrix * BallCenter; + gl_Position = ftransform(); +} diff --git a/progs/glsl/CH18-mandel.frag.txt b/progs/glsl/CH18-mandel.frag.txt new file mode 100644 index 0000000000..a472d81252 --- /dev/null +++ b/progs/glsl/CH18-mandel.frag.txt @@ -0,0 +1,55 @@ +// +// Fragment shader for drawing the Mandelbrot set +// +// Authors: Dave Baldwin, Steve Koren, Randi Rost +// based on a shader by Michael Rivero +// +// Copyright (c) 2002-2005: 3Dlabs, Inc. +// +// See 3Dlabs-License.txt for license information +// + +varying vec3 Position; +varying float LightIntensity; + +uniform float MaxIterations; +uniform float Zoom; +uniform float Xcenter; +uniform float Ycenter; +uniform vec3 InnerColor; +uniform vec3 OuterColor1; +uniform vec3 OuterColor2; + +void main() +{ + float real = Position.x * Zoom + Xcenter; + float imag = Position.y * Zoom + Ycenter; + float Creal = real; // Change this line... + float Cimag = imag; // ...and this one to get a Julia set + + float r2 = 0.0; + float iter; + +// for (iter = 0.0; iter < MaxIterations && r2 < 4.0; ++iter) + for (iter = 0.0; iter < 12 && r2 < 4.0; ++iter) + { + float tempreal = real; + + real = (tempreal * tempreal) - (imag * imag) + Creal; + imag = 2.0 * tempreal * imag + Cimag; + r2 = (real * real) + (imag * imag); + } + + // Base the color on the number of iterations + + vec3 color; + + if (r2 < 4.0) + color = InnerColor; + else + color = mix(OuterColor1, OuterColor2, fract(iter * 0.05)); + + color *= LightIntensity; + + gl_FragColor = vec4(color, 1.0); +} diff --git a/progs/glsl/CH18-mandel.vert.txt b/progs/glsl/CH18-mandel.vert.txt new file mode 100644 index 0000000000..c4ca66405d --- /dev/null +++ b/progs/glsl/CH18-mandel.vert.txt @@ -0,0 +1,35 @@ +// +// Vertex shader for drawing the Mandelbrot set +// +// Authors: Dave Baldwin, Steve Koren, Randi Rost +// based on a shader by Michael Rivero +// +// Copyright (c) 2002-2005: 3Dlabs, Inc. +// +// See 3Dlabs-License.txt for license information +// + +uniform vec3 LightPosition; +uniform float SpecularContribution; +uniform float DiffuseContribution; +uniform float Shininess; + +varying float LightIntensity; +varying vec3 Position; + +void main() +{ + vec3 ecPosition = vec3(gl_ModelViewMatrix * gl_Vertex); + vec3 tnorm = normalize(gl_NormalMatrix * gl_Normal); + vec3 lightVec = normalize(LightPosition - ecPosition); + vec3 reflectVec = reflect(-lightVec, tnorm); + vec3 viewVec = normalize(-ecPosition); + float spec = max(dot(reflectVec, viewVec), 0.0); + spec = pow(spec, Shininess); + LightIntensity = DiffuseContribution * + max(dot(lightVec, tnorm), 0.0) + + SpecularContribution * spec; + Position = vec3(gl_MultiTexCoord0 - 0.5) * 5.0; + gl_Position = ftransform(); + +}
\ No newline at end of file diff --git a/progs/glsl/Makefile b/progs/glsl/Makefile new file mode 100644 index 0000000000..e08d4102c8 --- /dev/null +++ b/progs/glsl/Makefile @@ -0,0 +1,74 @@ +# progs/demos/Makefile + +TOP = ../.. +include $(TOP)/configs/current + +INCDIR = $(TOP)/include + +OSMESA_LIBS = -L$(TOP)/$(LIB_DIR) -lglut -lOSMesa -lGLU -lGL $(APP_LIB_DEPS) + +OSMESA16_LIBS = -L$(TOP)/$(LIB_DIR) -lglut -lOSMesa16 -lGLU -lGL $(APP_LIB_DEPS) + +OSMESA32_LIBS = -L$(TOP)/$(LIB_DIR) -lglut -lOSMesa32 -lGLU -lGL $(APP_LIB_DEPS) + +LIB_DEP = $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) $(TOP)/$(LIB_DIR)/$(GLU_LIB_NAME) $(TOP)/$(LIB_DIR)/$(GLUT_LIB_NAME) + +PROGS = \ + brick \ + bump \ + mandelbrot \ + noise \ + toyball \ + texdemo1 + + +##### RULES ##### + +.SUFFIXES: +.SUFFIXES: .c + + +# make executable from .c file: +.c: $(LIB_DEP) + $(CC) -I$(INCDIR) $(CFLAGS) $< $(APP_LIB_DEPS) -o $@ + + +##### TARGETS ##### + +default: $(PROGS) + + + +##### Extra dependencies + +extfuncs.h: $(TOP)/progs/util/extfuncs.h + cp $< . + +readtex.c: $(TOP)/progs/util/readtex.c + cp $< . + +readtex.h: $(TOP)/progs/util/readtex.h + cp $< . + +readtex.o: readtex.c readtex.h + $(CC) -c -I$(INCDIR) $(CFLAGS) readtex.c + +brick.c: extfuncs.h + +bump.c: extfuncs.h + +mandelbrot.c: extfuncs.h + +toyball.c: extfuncs.h + +texdemo1: texdemo1.o readtex.o + $(CC) -I$(INCDIR) $(CFLAGS) texdemo1.o readtex.o $(APP_LIB_DEPS) -o $@ + +texdemo1.o: texdemo1.c readtex.h extfuncs.h + $(CC) -c -I$(INCDIR) $(CFLAGS) texdemo1.c + + +clean: + -rm -f $(PROGS) + -rm -f *.o *~ + -rm -f extfuncs.h diff --git a/progs/glsl/brick.c b/progs/glsl/brick.c new file mode 100644 index 0000000000..522698b5d4 --- /dev/null +++ b/progs/glsl/brick.c @@ -0,0 +1,311 @@ +/** + * "Brick" shader demo. Uses the example shaders from chapter 6 of + * the OpenGL Shading Language "orange" book. + * 10 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 = "CH06-brick.frag.txt"; +static char *VertProgFile = "CH06-brick.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[] = { + /* vert */ + { "LightPosition", 3, -1, { 0.1, 0.1, 9.0, 0} }, + /* frag */ + { "BrickColor", 3, -1, { 0.8, 0.2, 0.2, 0 } }, + { "MortarColor", 3, -1, { 0.6, 0.6, 0.6, 0 } }, + { "BrickSize", 2, -1, { 1.0, 0.3, 0, 0 } }, + { "BrickPct", 2, -1, { 0.9, 0.8, 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); + + glBegin(GL_POLYGON); + glTexCoord2f(0, 0); glVertex2f(-2, -2); + glTexCoord2f(1, 0); glVertex2f( 2, -2); + glTexCoord2f(1, 1); glVertex2f( 2, 2); + glTexCoord2f(0, 1); glVertex2f(-2, 2); + glEnd(); + + glPopMatrix(); + + 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) +{ + (void) x; + (void) y; + + switch(key) { + case 'z': + zRot -= 1.0; + break; + case 'Z': + zRot += 1.0; + break; + case 27: + CleanUp(); + exit(0); + break; + } + glutPostRedisplay(); +} + + +static void +SpecialKey(int key, int x, int y) +{ + const GLfloat step = 3.0f; + + (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);*/ + } + + 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); + + 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); + + printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER)); + + assert(glIsProgram_func(program)); + assert(glIsShader_func(fragShader)); + assert(glIsShader_func(vertShader)); + + 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/bump.c b/progs/glsl/bump.c new file mode 100644 index 0000000000..a6846acf7e --- /dev/null +++ b/progs/glsl/bump.c @@ -0,0 +1,411 @@ +/** + * 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, { 10.0, 0, 0, 0 } }, + { "BumpSize", 1, -1, { 0.125, 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 = 20.0f, yRot = 0.0f, zRot = 0.0f; + +static GLuint tangentAttrib; + +static GLboolean Anim = GL_FALSE; + + +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 +Cube(GLfloat size) +{ + /* +X */ + glPushMatrix(); + glRotatef(90, 0, 1, 0); + glTranslatef(0, 0, size); + Square(size); + glPopMatrix(); + + /* -X */ + glPushMatrix(); + glRotatef(-90, 0, 1, 0); + glTranslatef(0, 0, size); + Square(size); + glPopMatrix(); + + /* +Y */ + glPushMatrix(); + glRotatef(90, 1, 0, 0); + glTranslatef(0, 0, size); + Square(size); + glPopMatrix(); + + /* -Y */ + glPushMatrix(); + glRotatef(-90, 1, 0, 0); + glTranslatef(0, 0, size); + Square(size); + glPopMatrix(); + + + /* +Z */ + glPushMatrix(); + glTranslatef(0, 0, size); + Square(size); + glPopMatrix(); + + /* -Z */ + glPushMatrix(); + glRotatef(180, 0, 1, 0); + glTranslatef(0, 0, size); + Square(size); + glPopMatrix(); + +} + + +static void +Idle(void) +{ + GLint t = glutGet(GLUT_ELAPSED_TIME); + yRot = t * 0.05; + glutPostRedisplay(); +} + + +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); + + Cube(1.5); + + 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 'a': + Anim = !Anim; + glutIdleFunc(Anim ? Idle : NULL); + break; + 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/cubemap.frag.txt b/progs/glsl/cubemap.frag.txt new file mode 100644 index 0000000000..9c27648aaf --- /dev/null +++ b/progs/glsl/cubemap.frag.txt @@ -0,0 +1,18 @@ +// Fragment shader for cube-texture reflection mapping +// Brian Paul + + +uniform samplerCube cubeTex; +varying vec3 normal; +uniform vec3 lightPos; + +void main() +{ + // simple diffuse, specular lighting: + vec3 lp = normalize(lightPos); + float dp = dot(lp, normalize(normal)); + float spec = pow(dp, 5.0); + + // final color: + gl_FragColor = dp * textureCube(cubeTex, gl_TexCoord[0].xyz, 0.0) + spec; +} diff --git a/progs/glsl/mandelbrot.c b/progs/glsl/mandelbrot.c new file mode 100644 index 0000000000..7a2bad6dde --- /dev/null +++ b/progs/glsl/mandelbrot.c @@ -0,0 +1,328 @@ +/** + * "Mandelbrot" shader demo. Uses the example shaders from + * chapter 15 (or 18) of the OpenGL Shading Language "orange" book. + * 15 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 = "CH18-mandel.frag.txt"; +static char *VertProgFile = "CH18-mandel.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[] = { + /* vert */ + { "LightPosition", 3, -1, { 0.1, 0.1, 9.0, 0} }, + { "SpecularContribution", 1, -1, { 0.5, 0, 0, 0 } }, + { "DiffuseContribution", 1, -1, { 0.5, 0, 0, 0 } }, + { "Shininess", 1, -1, { 20.0, 0, 0, 0 } }, + /* frag */ + { "MaxIterations", 1, -1, { 12, 0, 0, 0 } }, + { "Zoom", 1, -1, { 0.125, 0, 0, 0 } }, + { "Xcenter", 1, -1, { -1.5, 0, 0, 0 } }, + { "Ycenter", 1, -1, { .005, 0, 0, 0 } }, + { "InnerColor", 3, -1, { 1, 0, 0, 0 } }, + { "OuterColor1", 3, -1, { 0, 1, 0, 0 } }, + { "OuterColor2", 3, -1, { 0, 0, 1, 0 } }, + { NULL, 0, 0, { 0, 0, 0, 0 } } +}; + +static GLint win = 0; + +static GLfloat xRot = 0.0f, yRot = 0.0f, zRot = 0.0f; + +static GLint uZoom, uXcenter, uYcenter; +static GLfloat zoom = 1.0, xCenter = -1.5, yCenter = 0.0; + + +static void +Redisplay(void) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + /* set interactive uniform parameters */ + glUniform1fv_func(uZoom, 1, &zoom); + glUniform1fv_func(uXcenter, 1, &xCenter); + glUniform1fv_func(uYcenter, 1, &yCenter); + + 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); + + glBegin(GL_POLYGON); + glTexCoord2f(0, 0); glVertex2f(-1, -1); + glTexCoord2f(1, 0); glVertex2f( 1, -1); + glTexCoord2f(1, 1); glVertex2f( 1, 1); + glTexCoord2f(0, 1); glVertex2f(-1, 1); + glEnd(); + + 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, -6.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) +{ + (void) x; + (void) y; + + switch(key) { + case 'z': + zoom *= 0.9; + break; + case 'Z': + zoom /= 0.9; + break; + case 27: + CleanUp(); + exit(0); + break; + } + glutPostRedisplay(); +} + + +static void +SpecialKey(int key, int x, int y) +{ + const GLfloat step = 0.1 * zoom; + + (void) x; + (void) y; + + switch(key) { + case GLUT_KEY_UP: + yCenter += step; + break; + case GLUT_KEY_DOWN: + yCenter -= step; + break; + case GLUT_KEY_LEFT: + xCenter -= step; + break; + case GLUT_KEY_RIGHT: + xCenter += 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);*/ + } + + 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); + + 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(); + } + } + + uZoom = glGetUniformLocation_func(program, "Zoom"); + uXcenter = glGetUniformLocation_func(program, "Xcenter"); + uYcenter = glGetUniformLocation_func(program, "Ycenter"); + + assert(glGetError() == 0); + + glClearColor(0.4f, 0.4f, 0.8f, 0.0f); + + printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER)); + + assert(glIsProgram_func(program)); + assert(glIsShader_func(fragShader)); + assert(glIsShader_func(vertShader)); + + 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/noise.c b/progs/glsl/noise.c new file mode 100644 index 0000000000..a26a805944 --- /dev/null +++ b/progs/glsl/noise.c @@ -0,0 +1,297 @@ +/** + * Test noise() functions. + * 28 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 const char *VertShaderText = + "void main() {\n" + " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" + " gl_TexCoord[0] = gl_MultiTexCoord0;\n" + "}\n"; + +static const char *FragShaderText = + "uniform vec4 Scale, Bias;\n" + "uniform float Slice;\n" + "void main()\n" + "{\n" + " vec4 scale = vec4(5.0);\n" + " vec4 p;\n" + " p.xy = gl_TexCoord[0].xy;\n" + " p.z = Slice;\n" + " vec4 n = noise4(p * scale);\n" + " gl_FragColor = n * Scale + Bias;\n" + "}\n"; + + +struct uniform_info { + const char *name; + GLuint size; + GLint location; + GLfloat value[4]; +}; + +static struct uniform_info Uniforms[] = { + { "Scale", 4, -1, { 0.5, 0.4, 0.0, 0} }, + { "Bias", 4, -1, { 0.5, 0.3, 0.0, 0} }, + { "Slice", 1, -1, { 0.5, 0, 0, 0} }, + { NULL, 0, 0, { 0, 0, 0, 0 } } +}; + +/* program/shader objects */ +static GLuint fragShader; +static GLuint vertShader; +static GLuint program; + +static GLint win = 0; +static GLfloat xRot = 0.0f, yRot = 0.0f, zRot = 0.0f; +static GLfloat Slice = 0.0; +static GLboolean Anim = GL_FALSE; + + +static void +Idle(void) +{ + Slice += 0.01; + glutPostRedisplay(); +} + + +static void +Redisplay(void) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glUniform1fv_func(Uniforms[2].location, 1, &Slice); + + 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); + + glBegin(GL_POLYGON); + glTexCoord2f(0, 0); glVertex2f(-2, -2); + glTexCoord2f(1, 0); glVertex2f( 2, -2); + glTexCoord2f(1, 1); glVertex2f( 2, 2); + glTexCoord2f(0, 1); glVertex2f(-2, 2); + glEnd(); + + glPopMatrix(); + + 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 = 0.01; + (void) x; + (void) y; + + switch(key) { + case 'a': + Anim = !Anim; + glutIdleFunc(Anim ? Idle : NULL); + case 's': + Slice -= step; + break; + case 'S': + Slice += step; + break; + case 'z': + zRot -= 1.0; + break; + case 'Z': + zRot += 1.0; + break; + case 27: + CleanUp(); + exit(0); + break; + } + glutPostRedisplay(); +} + + +static void +SpecialKey(int key, int x, int y) +{ + const GLfloat step = 3.0f; + + (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"); + } +} + + +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);*/ + } + + GetExtensionFuncs(); + + vertShader = glCreateShader_func(GL_VERTEX_SHADER); + LoadAndCompileShader(vertShader, VertShaderText); + + fragShader = glCreateShader_func(GL_FRAGMENT_SHADER); + LoadAndCompileShader(fragShader, FragShaderText); + + program = glCreateProgram_func(); + glAttachShader_func(program, fragShader); + glAttachShader_func(program, vertShader); + glLinkProgram_func(program); + CheckLink(program); + glUseProgram_func(program); + + 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); + + printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER)); + + assert(glIsProgram_func(program)); + assert(glIsShader_func(fragShader)); + assert(glIsShader_func(vertShader)); + + glColor3f(1, 0, 0); +} + + +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); + Init(); + glutMainLoop(); + return 0; +} + diff --git a/progs/glsl/reflect.vert.txt b/progs/glsl/reflect.vert.txt new file mode 100644 index 0000000000..402be38bf7 --- /dev/null +++ b/progs/glsl/reflect.vert.txt @@ -0,0 +1,19 @@ +// Vertex shader for cube-texture reflection mapping +// Brian Paul + + +varying vec3 normal; + +void main() +{ + vec3 n = gl_NormalMatrix * gl_Normal; + vec3 u = normalize(vec3(gl_ModelViewMatrix * gl_Vertex)); + float two_n_dot_u = 2.0 * dot(n, u); + vec4 f; + f.xyz = u - n * two_n_dot_u; + + // outputs + normal = n; + gl_TexCoord[0] = gl_TextureMatrix[0] * f; + gl_Position = ftransform(); +} diff --git a/progs/glsl/shadowtex.frag.txt b/progs/glsl/shadowtex.frag.txt new file mode 100644 index 0000000000..a6a80da47f --- /dev/null +++ b/progs/glsl/shadowtex.frag.txt @@ -0,0 +1,21 @@ +// Fragment shader for 2D texture with shadow attenuation +// Brian Paul + + +uniform sampler2D tex2d; +uniform vec3 lightPos; + +void main() +{ + // XXX should compute this from lightPos + vec2 shadowCenter = vec2(-0.25, -0.25); + + // d = distance from center + float d = distance(gl_TexCoord[0].xy, shadowCenter); + + // attenuate and clamp + d = clamp(d * d * d, 0.0, 2.0); + + // modulate texture by d for shadow effect + gl_FragColor = d * texture2D(tex2d, gl_TexCoord[0].xy, 0.0); +} diff --git a/progs/glsl/simple.vert.txt b/progs/glsl/simple.vert.txt new file mode 100644 index 0000000000..a0abe0dc0b --- /dev/null +++ b/progs/glsl/simple.vert.txt @@ -0,0 +1,9 @@ +// Simple vertex shader +// Brian Paul + + +void main() +{ + gl_TexCoord[0] = gl_MultiTexCoord0; + gl_Position = ftransform(); +} diff --git a/progs/glsl/texdemo1.c b/progs/glsl/texdemo1.c new file mode 100644 index 0000000000..d29ecf452b --- /dev/null +++ b/progs/glsl/texdemo1.c @@ -0,0 +1,570 @@ +/** + * Test texturing with GL shading language. + * + * Copyright (C) 2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#include <assert.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "GL/glut.h" +#include "readtex.h" +#include "extfuncs.h" + +static const char *Demo = "texdemo1"; + +static const char *ReflectVertFile = "reflect.vert.txt"; +static const char *CubeFragFile = "cubemap.frag.txt"; + +static const char *SimpleVertFile = "simple.vert.txt"; +static const char *SimpleTexFragFile = "shadowtex.frag.txt"; + +static const char *GroundImage = "../images/tile.rgb"; + +static GLuint Program1, Program2; + +static GLfloat TexXrot = 0, TexYrot = 0; +static GLfloat Xrot = 20.0, Yrot = 20.0, Zrot = 0.0; +static GLfloat EyeDist = 10; +static GLboolean Anim = GL_TRUE; + + +struct uniform_info { + const char *name; + GLuint size; + GLint location; + GLenum type; /**< GL_FLOAT or GL_INT */ + GLfloat value[4]; +}; + +static struct uniform_info ReflectUniforms[] = { + { "cubeTex", 1, -1, GL_INT, { 0, 0, 0, 0 } }, + { "lightPos", 3, -1, GL_FLOAT, { 10, 10, 20, 0 } }, + { NULL, 0, 0, 0, { 0, 0, 0, 0 } } +}; + +static struct uniform_info SimpleUniforms[] = { + { "tex2d", 1, -1, GL_INT, { 1, 0, 0, 0 } }, + { "lightPos", 3, -1, GL_FLOAT, { 10, 10, 20, 0 } }, + { NULL, 0, 0, 0, { 0, 0, 0, 0 } } +}; + + +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); + } +} + + +static void +DrawGround(GLfloat size) +{ + glPushMatrix(); + glRotatef(90, 1, 0, 0); + glNormal3f(0, 0, 1); + glBegin(GL_POLYGON); + glTexCoord2f(-2, -2); glVertex2f(-size, -size); + glTexCoord2f( 2, -2); glVertex2f( size, -size); + glTexCoord2f( 2, 2); glVertex2f( size, size); + glTexCoord2f(-2, 2); glVertex2f(-size, size); + glEnd(); + glPopMatrix(); +} + + +static void +draw(void) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glEnable(GL_TEXTURE_2D); + + glPushMatrix(); /* modelview matrix */ + glTranslatef(0.0, 0.0, -EyeDist); + glRotatef(Xrot, 1, 0, 0); + glRotatef(Yrot, 0, 1, 0); + glRotatef(Zrot, 0, 0, 1); + + /* sphere w/ reflection map */ + glPushMatrix(); + glTranslatef(0, 1, 0); + glUseProgram_func(Program1); + + /* setup texture matrix */ + glActiveTexture(GL_TEXTURE0); + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glRotatef(-TexYrot, 0, 1, 0); + glRotatef(-TexXrot, 1, 0, 0); + + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); + glutSolidSphere(2.0, 20, 20); + + glLoadIdentity(); /* texture matrix */ + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + /* ground */ + glUseProgram_func(Program2); + glTranslatef(0, -1.0, 0); + DrawGround(5); + + glPopMatrix(); + + glutSwapBuffers(); +} + + +static void +idle(void) +{ + GLfloat t = 0.05 * glutGet(GLUT_ELAPSED_TIME); + TexYrot = t; + glutPostRedisplay(); +} + + +static void +key(unsigned char k, int x, int y) +{ + (void) x; + (void) y; + switch (k) { + case ' ': + case 'a': + Anim = !Anim; + if (Anim) + glutIdleFunc(idle); + else + glutIdleFunc(NULL); + break; + case 'z': + EyeDist -= 0.5; + if (EyeDist < 6.0) + EyeDist = 6.0; + break; + case 'Z': + EyeDist += 0.5; + if (EyeDist > 90.0) + EyeDist = 90; + break; + case 27: + exit(0); + } + glutPostRedisplay(); +} + + +static void +specialkey(int key, int x, int y) +{ + 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(); +} + + +/* new window size or exposure */ +static void +Reshape(int width, int height) +{ + GLfloat ar = (float) width / (float) height; + glViewport(0, 0, (GLint)width, (GLint)height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-2.0*ar, 2.0*ar, -2.0, 2.0, 4.0, 100.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + + +static void +InitCheckers(void) +{ +#define CUBE_TEX_SIZE 64 + GLubyte image[CUBE_TEX_SIZE][CUBE_TEX_SIZE][3]; + static const GLubyte colors[6][3] = { + { 255, 0, 0 }, /* face 0 - red */ + { 0, 255, 255 }, /* face 1 - cyan */ + { 0, 255, 0 }, /* face 2 - green */ + { 255, 0, 255 }, /* face 3 - purple */ + { 0, 0, 255 }, /* face 4 - blue */ + { 255, 255, 0 } /* face 5 - yellow */ + }; + static const GLenum targets[6] = { + GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, + GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB + }; + + GLint i, j, f; + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + /* make colored checkerboard cube faces */ + for (f = 0; f < 6; f++) { + for (i = 0; i < CUBE_TEX_SIZE; i++) { + for (j = 0; j < CUBE_TEX_SIZE; j++) { + if ((i/4 + j/4) & 1) { + image[i][j][0] = colors[f][0]; + image[i][j][1] = colors[f][1]; + image[i][j][2] = colors[f][2]; + } + else { + image[i][j][0] = 255; + image[i][j][1] = 255; + image[i][j][2] = 255; + } + } + } + + glTexImage2D(targets[f], 0, GL_RGB, CUBE_TEX_SIZE, CUBE_TEX_SIZE, 0, + GL_RGB, GL_UNSIGNED_BYTE, image); + } +} + + +static void +LoadFace(GLenum target, const char *filename, + GLboolean flipTB, GLboolean flipLR) +{ + GLint w, h; + GLenum format; + GLubyte *img = LoadRGBImage(filename, &w, &h, &format); + if (!img) { + printf("Error: couldn't load texture image %s\n", filename); + exit(1); + } + assert(format == GL_RGB); + + /* <sigh> the way the texture cube mapping works, we have to flip + * images to make things look right. + */ + if (flipTB) { + const int stride = 3 * w; + GLubyte temp[3*1024]; + int i; + for (i = 0; i < h / 2; i++) { + memcpy(temp, img + i * stride, stride); + memcpy(img + i * stride, img + (h - i - 1) * stride, stride); + memcpy(img + (h - i - 1) * stride, temp, stride); + } + } + if (flipLR) { + const int stride = 3 * w; + GLubyte temp[3]; + GLubyte *row; + int i, j; + for (i = 0; i < h; i++) { + row = img + i * stride; + for (j = 0; j < w / 2; j++) { + int k = w - j - 1; + temp[0] = row[j*3+0]; + temp[1] = row[j*3+1]; + temp[2] = row[j*3+2]; + row[j*3+0] = row[k*3+0]; + row[j*3+1] = row[k*3+1]; + row[j*3+2] = row[k*3+2]; + row[k*3+0] = temp[0]; + row[k*3+1] = temp[1]; + row[k*3+2] = temp[2]; + } + } + } + + gluBuild2DMipmaps(target, GL_RGB, w, h, format, GL_UNSIGNED_BYTE, img); + free(img); +} + + +static void +LoadEnvmaps(void) +{ + LoadFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, "right.rgb", GL_TRUE, GL_FALSE); + LoadFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, "left.rgb", GL_TRUE, GL_FALSE); + LoadFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, "top.rgb", GL_FALSE, GL_TRUE); + LoadFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, "bottom.rgb", GL_FALSE, GL_TRUE); + LoadFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, "front.rgb", GL_TRUE, GL_FALSE); + LoadFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, "back.rgb", GL_TRUE, GL_FALSE); +} + + +static void +InitTextures(GLboolean useImageFiles) +{ + GLenum filter; + + /* + * Env map + */ + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP, 1); + if (useImageFiles) { + LoadEnvmaps(); + filter = GL_LINEAR; + } + else { + InitCheckers(); + filter = GL_NEAREST; + } + glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, filter); + glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + /* + * Ground texture + */ + { + GLint imgWidth, imgHeight; + GLenum imgFormat; + GLubyte *image = NULL; + + image = LoadRGBImage(GroundImage, &imgWidth, &imgHeight, &imgFormat); + if (!image) { + printf("Couldn't read %s\n", GroundImage); + exit(0); + } + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, 2); + gluBuild2DMipmaps(GL_TEXTURE_2D, 3, imgWidth, imgHeight, + imgFormat, GL_UNSIGNED_BYTE, image); + free(image); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } +} + + +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, "%s: problem compiling shader: %s\n", Demo, 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, "%s: Unable to open shader file %s\n", Demo, filename); + exit(1); + } + + n = fread(buffer, 1, max, f); + printf("%s: read %d bytes from shader file %s\n", Demo, 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 GLuint +CreateProgram(const char *vertProgFile, const char *fragProgFile, + struct uniform_info *uniforms) +{ + GLuint fragShader = 0, vertShader = 0, program = 0; + GLint i; + + program = glCreateProgram_func(); + if (vertProgFile) { + vertShader = glCreateShader_func(GL_VERTEX_SHADER); + ReadShader(vertShader, vertProgFile); + glAttachShader_func(program, vertShader); + } + + if (fragProgFile) { + fragShader = glCreateShader_func(GL_FRAGMENT_SHADER); + ReadShader(fragShader, fragProgFile); + glAttachShader_func(program, fragShader); + } + + glLinkProgram_func(program); + CheckLink(program); + + glUseProgram_func(program); + + assert(glIsProgram_func(program)); + assert(glIsShader_func(fragShader)); + assert(glIsShader_func(vertShader)); + + 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: + if (uniforms[i].type == GL_INT) + glUniform1i_func(uniforms[i].location, + (GLint) uniforms[i].value[0]); + else + 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__); + + return program; +} + + +static void +InitPrograms(void) +{ + Program1 = CreateProgram(ReflectVertFile, CubeFragFile, ReflectUniforms); + Program2 = CreateProgram(SimpleVertFile, SimpleTexFragFile, SimpleUniforms); +} + + +static void +Init(GLboolean useImageFiles) +{ + const char *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(); + + InitTextures(useImageFiles); + InitPrograms(); + + glEnable(GL_DEPTH_TEST); + + glClearColor(.6, .6, .9, 0); + glColor3f(1.0, 1.0, 1.0); +} + + +int +main(int argc, char *argv[]) +{ + glutInit(&argc, argv); + glutInitWindowSize(500, 400); + glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); + glutCreateWindow(Demo); + glutReshapeFunc(Reshape); + glutKeyboardFunc(key); + glutSpecialFunc(specialkey); + glutDisplayFunc(draw); + if (Anim) + glutIdleFunc(idle); + if (argc > 1 && strcmp(argv[1] , "-i") == 0) + Init(1); + else + Init(0); + glutMainLoop(); + return 0; +} diff --git a/progs/glsl/toyball.c b/progs/glsl/toyball.c new file mode 100644 index 0000000000..cef52c04a6 --- /dev/null +++ b/progs/glsl/toyball.c @@ -0,0 +1,339 @@ +/** + * "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 GLboolean Anim = GL_FALSE; +static GLfloat TexRot = 0.0; +static GLfloat xRot = 0.0f, yRot = 0.0f, zRot = 0.0f; + + +static void +Idle(void) +{ + TexRot += 2.0; + if (TexRot > 360.0) + TexRot -= 360.0; + glutPostRedisplay(); +} + + +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); + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glRotatef(TexRot, 0.0f, 1.0f, 0.0f); + glMatrixMode(GL_MODELVIEW); + + 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 'a': + Anim = !Anim; + if (Anim) + glutIdleFunc(Idle); + else + glutIdleFunc(NULL); + break; + 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; +} + |