summaryrefslogtreecommitdiff
path: root/progs
diff options
context:
space:
mode:
Diffstat (limited to 'progs')
-rw-r--r--progs/demos/Makefile7
-rw-r--r--progs/demos/fslight.c385
-rw-r--r--progs/glsl/CH06-brick.frag.txt36
-rw-r--r--progs/glsl/CH06-brick.vert.txt41
-rw-r--r--progs/glsl/CH11-bumpmap.frag.txt41
-rw-r--r--progs/glsl/CH11-bumpmap.vert.txt38
-rw-r--r--progs/glsl/CH11-toyball.frag.txt75
-rw-r--r--progs/glsl/CH11-toyball.vert.txt24
-rw-r--r--progs/glsl/CH18-mandel.frag.txt55
-rw-r--r--progs/glsl/CH18-mandel.vert.txt35
-rw-r--r--progs/glsl/Makefile74
-rw-r--r--progs/glsl/brick.c311
-rw-r--r--progs/glsl/bump.c411
-rw-r--r--progs/glsl/cubemap.frag.txt18
-rw-r--r--progs/glsl/mandelbrot.c328
-rw-r--r--progs/glsl/noise.c297
-rw-r--r--progs/glsl/reflect.vert.txt19
-rw-r--r--progs/glsl/shadowtex.frag.txt21
-rw-r--r--progs/glsl/simple.vert.txt9
-rw-r--r--progs/glsl/texdemo1.c570
-rw-r--r--progs/glsl/toyball.c339
-rw-r--r--progs/tests/Makefile9
-rw-r--r--progs/tests/drawbuffers.c298
-rw-r--r--progs/util/extfuncs.h118
24 files changed, 3507 insertions, 52 deletions
diff --git a/progs/demos/Makefile b/progs/demos/Makefile
index 4623d6c8d9..6369746f00 100644
--- a/progs/demos/Makefile
+++ b/progs/demos/Makefile
@@ -113,6 +113,10 @@ trackball.o: trackball.c trackball.h
$(CC) -c -I$(INCDIR) $(CFLAGS) trackball.c
+extfuncs.h: $(TOP)/progs/util/extfuncs.h
+ cp $< .
+
+
reflect: reflect.o showbuffer.o readtex.o
$(CC) -I$(INCDIR) $(CFLAGS) reflect.o showbuffer.o readtex.o $(APP_LIB_DEPS) -o $@
@@ -141,6 +145,9 @@ engine.o: engine.c trackball.h
$(CC) -c -I$(INCDIR) $(CFLAGS) engine.c
+fslight.c: extfuncs.h
+
+
clean:
-rm -f $(PROGS)
-rm -f *.o *~
diff --git a/progs/demos/fslight.c b/progs/demos/fslight.c
index 1c016cc75e..b03ba2315a 100644
--- a/progs/demos/fslight.c
+++ b/progs/demos/fslight.c
@@ -20,46 +20,37 @@
#include <GL/gl.h>
#include <GL/glut.h>
#include <GL/glext.h>
+#include "extfuncs.h"
+
+
+static GLint CoordAttrib = 0;
+
+static char *FragProgFile = NULL;
+static char *VertProgFile = NULL;
static GLfloat diffuse[4] = { 0.5f, 0.5f, 1.0f, 1.0f };
static GLfloat specular[4] = { 0.8f, 0.8f, 0.8f, 1.0f };
-static GLfloat lightPos[4] = { 0.0f, 10.0f, 20.0f, 1.0f };
+static GLfloat lightPos[4] = { 0.0f, 10.0f, 20.0f, 0.0f };
static GLfloat delta = 1.0f;
static GLuint fragShader;
static GLuint vertShader;
static GLuint program;
-static GLint uLightPos;
static GLint uDiffuse;
static GLint uSpecular;
+static GLint uTexture;
+static GLuint SphereList, RectList, CurList;
static GLint win = 0;
-static GLboolean anim = GL_TRUE;
+static GLboolean anim = GL_FALSE;
static GLboolean wire = GL_FALSE;
static GLboolean pixelLight = GL_TRUE;
static GLint t0 = 0;
static GLint frames = 0;
-static GLfloat xRot = 0.0f, yRot = 0.0f;
-
-static PFNGLCREATESHADERPROC glCreateShader_func = NULL;
-static PFNGLSHADERSOURCEPROC glShaderSource_func = NULL;
-static PFNGLGETSHADERSOURCEPROC glGetShaderSource_func = NULL;
-static PFNGLCOMPILESHADERPROC glCompileShader_func = NULL;
-static PFNGLCREATEPROGRAMPROC glCreateProgram_func = NULL;
-static PFNGLDELETEPROGRAMPROC glDeleteProgram_func = NULL;
-static PFNGLDELETESHADERPROC glDeleteShader_func = NULL;
-static PFNGLATTACHSHADERPROC glAttachShader_func = NULL;
-static PFNGLLINKPROGRAMPROC glLinkProgram_func = NULL;
-static PFNGLUSEPROGRAMPROC glUseProgram_func = NULL;
-static PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation_func = NULL;
-static PFNGLISPROGRAMPROC glIsProgram_func = NULL;
-static PFNGLISSHADERPROC glIsShader_func = NULL;
-static PFNGLUNIFORM3FVPROC glUniform3fv_func = NULL;
-static PFNGLUNIFORM3FVPROC glUniform4fv_func = NULL;
-
+static GLfloat xRot = 90.0f, yRot = 0.0f;
static void
@@ -69,31 +60,37 @@ normalize(GLfloat *dst, const GLfloat *src)
dst[0] = src[0] / len;
dst[1] = src[1] / len;
dst[2] = src[2] / len;
+ dst[3] = src[3];
}
static void
Redisplay(void)
{
+ GLfloat vec[4];
+
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ /* update light position */
+ normalize(vec, lightPos);
+ glLightfv(GL_LIGHT0, GL_POSITION, vec);
if (pixelLight) {
- GLfloat vec[3];
glUseProgram_func(program);
- normalize(vec, lightPos);
- glUniform3fv_func(uLightPos, 1, vec);
glDisable(GL_LIGHTING);
}
else {
glUseProgram_func(0);
- glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
glEnable(GL_LIGHTING);
}
glPushMatrix();
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
+ /*
glutSolidSphere(2.0, 10, 5);
+ */
+ glCallList(CurList);
glPopMatrix();
glutSwapBuffers();
@@ -174,6 +171,12 @@ Key(unsigned char key, int x, int y)
else
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
break;
+ case 'o':
+ if (CurList == SphereList)
+ CurList = RectList;
+ else
+ CurList = SphereList;
+ break;
case 'p':
pixelLight = !pixelLight;
if (pixelLight)
@@ -217,16 +220,246 @@ SpecialKey(int key, int x, int y)
static void
+TestFunctions(void)
+{
+ printf("Error 0x%x at line %d\n", glGetError(), __LINE__);
+ {
+ GLfloat pos[3];
+ printf("Error 0x%x at line %d\n", glGetError(), __LINE__);
+ printf("Light pos %g %g %g\n", pos[0], pos[1], pos[2]);
+ }
+
+
+ {
+ GLfloat m[16], result[16];
+ GLint mPos;
+ int i;
+
+ for (i = 0; i < 16; i++)
+ m[i] = (float) i;
+
+ mPos = glGetUniformLocation_func(program, "m");
+ printf("Error 0x%x at line %d\n", glGetError(), __LINE__);
+ glUniformMatrix4fv_func(mPos, 1, GL_FALSE, m);
+ printf("Error 0x%x at line %d\n", glGetError(), __LINE__);
+
+ glGetUniformfv_func(program, mPos, result);
+ printf("Error 0x%x at line %d\n", glGetError(), __LINE__);
+
+ for (i = 0; i < 16; i++) {
+ printf("%8g %8g\n", m[i], result[i]);
+ }
+ }
+
+ assert(glIsProgram_func(program));
+ assert(glIsShader_func(fragShader));
+ assert(glIsShader_func(vertShader));
+
+ /* attached shaders */
+ {
+ GLuint shaders[20];
+ GLsizei count;
+ int i;
+ glGetAttachedShaders_func(program, 20, &count, shaders);
+ for (i = 0; i < count; i++) {
+ printf("Attached: %u\n", shaders[i]);
+ assert(shaders[i] == fragShader ||
+ shaders[i] == vertShader);
+ }
+ }
+
+ {
+ GLchar log[1000];
+ GLsizei len;
+ glGetShaderInfoLog_func(vertShader, 1000, &len, log);
+ printf("Vert Shader Info Log: %s\n", log);
+ glGetShaderInfoLog_func(fragShader, 1000, &len, log);
+ printf("Frag Shader Info Log: %s\n", log);
+ glGetProgramInfoLog_func(program, 1000, &len, log);
+ printf("Program Info Log: %s\n", log);
+ }
+}
+
+
+static void
+MakeTexture(void)
+{
+#define SZ0 128
+#define SZ1 64
+ GLubyte image0[SZ0][SZ0][SZ0][4];
+ GLubyte image1[SZ1][SZ1][SZ1][4];
+ GLuint i, j, k;
+
+ /* level 0: two-tone gray checkboard */
+ for (i = 0; i < SZ0; i++) {
+ for (j = 0; j < SZ0; j++) {
+ for (k = 0; k < SZ0; k++) {
+ if ((i/8 + j/8 + k/8) & 1) {
+ image0[i][j][k][0] =
+ image0[i][j][k][1] =
+ image0[i][j][k][2] = 200;
+ }
+ else {
+ image0[i][j][k][0] =
+ image0[i][j][k][1] =
+ image0[i][j][k][2] = 100;
+ }
+ image0[i][j][k][3] = 255;
+ }
+ }
+ }
+
+ /* level 1: two-tone green checkboard */
+ for (i = 0; i < SZ1; i++) {
+ for (j = 0; j < SZ1; j++) {
+ for (k = 0; k < SZ1; k++) {
+ if ((i/8 + j/8 + k/8) & 1) {
+ image1[i][j][k][0] = 0;
+ image1[i][j][k][1] = 250;
+ image1[i][j][k][2] = 0;
+ }
+ else {
+ image1[i][j][k][0] = 0;
+ image1[i][j][k][1] = 200;
+ image1[i][j][k][2] = 0;
+ }
+ image1[i][j][k][3] = 255;
+ }
+ }
+ }
+
+ glActiveTexture(GL_TEXTURE2); /* unit 2 */
+ glBindTexture(GL_TEXTURE_2D, 42);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SZ0, SZ0, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, image0);
+ glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, SZ1, SZ1, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, image1);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ glActiveTexture(GL_TEXTURE4); /* unit 4 */
+ glBindTexture(GL_TEXTURE_3D, 43);
+ glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, SZ0, SZ0, SZ0, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, image0);
+ glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA, SZ1, SZ1, SZ1, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, image1);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+}
+
+
+static void
+MakeSphere(void)
+{
+ GLUquadricObj *obj = gluNewQuadric();
+ SphereList = glGenLists(1);
+ gluQuadricTexture(obj, GL_TRUE);
+ glNewList(SphereList, GL_COMPILE);
+ gluSphere(obj, 2.0f, 10, 5);
+ glEndList();
+}
+
+static void
+VertAttrib(GLint index, float x, float y)
+{
+#if 1
+ glVertexAttrib2f_func(index, x, y);
+#else
+ glTexCoord2f(x, y);
+#endif
+}
+
+static void
+MakeRect(void)
+{
+ RectList = glGenLists(1);
+ glNewList(RectList, GL_COMPILE);
+ glNormal3f(0, 0, 1);
+ glBegin(GL_POLYGON);
+ VertAttrib(CoordAttrib, 0, 0); glVertex2f(-2, -2);
+ VertAttrib(CoordAttrib, 1, 0); glVertex2f( 2, -2);
+ VertAttrib(CoordAttrib, 1, 1); glVertex2f( 2, 2);
+ VertAttrib(CoordAttrib, 0, 1); glVertex2f(-2, 2);
+ glEnd(); /* XXX omit this and crash! */
+ glEndList();
+}
+
+
+
+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, "fslight: problem compiling shader:\n%s\n", log);
+ exit(1);
+ }
+}
+
+
+/**
+ * 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, "fslight: Unable to open shader file %s\n", filename);
+ exit(1);
+ }
+
+ n = fread(buffer, 1, max, f);
+ printf("fslight: 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);
+ }
+}
+
+
+static void
Init(void)
{
static const char *fragShaderText =
- "uniform vec3 lightPos;\n"
"uniform vec4 diffuse;\n"
"uniform vec4 specular;\n"
"varying vec3 normal;\n"
"void main() {\n"
" // Compute dot product of light direction and normal vector\n"
- " float dotProd = max(dot(lightPos, normalize(normal)), 0.0);\n"
+ " float dotProd = max(dot(gl_LightSource[0].position.xyz, \n"
+ " normalize(normal)), 0.0);\n"
" // Compute diffuse and specular contributions\n"
" gl_FragColor = diffuse * dotProd + specular * pow(dotProd, 20.0);\n"
"}\n";
@@ -236,8 +469,6 @@ Init(void)
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
" normal = gl_NormalMatrix * gl_Normal;\n"
"}\n";
-
-
const char *version;
version = (const char *) glGetString(GL_VERSION);
@@ -246,43 +477,55 @@ Init(void)
/*exit(1);*/
}
-
- glCreateShader_func = (PFNGLCREATESHADERPROC) glutGetProcAddress("glCreateShader");
- glDeleteShader_func = (PFNGLDELETESHADERPROC) glutGetProcAddress("glDeleteShader");
- glDeleteProgram_func = (PFNGLDELETEPROGRAMPROC) glutGetProcAddress("glDeleteProgram");
- glShaderSource_func = (PFNGLSHADERSOURCEPROC) glutGetProcAddress("glShaderSource");
- glGetShaderSource_func = (PFNGLGETSHADERSOURCEPROC) glutGetProcAddress("glGetShaderSource");
- glCompileShader_func = (PFNGLCOMPILESHADERPROC) glutGetProcAddress("glCompileShader");
- glCreateProgram_func = (PFNGLCREATEPROGRAMPROC) glutGetProcAddress("glCreateProgram");
- glAttachShader_func = (PFNGLATTACHSHADERPROC) glutGetProcAddress("glAttachShader");
- glLinkProgram_func = (PFNGLLINKPROGRAMPROC) glutGetProcAddress("glLinkProgram");
- glUseProgram_func = (PFNGLUSEPROGRAMPROC) glutGetProcAddress("glUseProgram");
- glGetUniformLocation_func = (PFNGLGETUNIFORMLOCATIONPROC) glutGetProcAddress("glGetUniformLocation");
- glIsProgram_func = (PFNGLISPROGRAMPROC) glutGetProcAddress("glIsProgram");
- glIsShader_func = (PFNGLISSHADERPROC) glutGetProcAddress("glIsShader");
- glUniform3fv_func = (PFNGLUNIFORM3FVPROC) glutGetProcAddress("glUniform3fv");
- glUniform4fv_func = (PFNGLUNIFORM3FVPROC) glutGetProcAddress("glUniform4fv");
+ GetExtensionFuncs();
fragShader = glCreateShader_func(GL_FRAGMENT_SHADER);
- glShaderSource_func(fragShader, 1, &fragShaderText, NULL);
- glCompileShader_func(fragShader);
+ if (FragProgFile)
+ ReadShader(fragShader, FragProgFile);
+ else
+ LoadAndCompileShader(fragShader, fragShaderText);
+
vertShader = glCreateShader_func(GL_VERTEX_SHADER);
- glShaderSource_func(vertShader, 1, &vertShaderText, NULL);
- glCompileShader_func(vertShader);
+ if (VertProgFile)
+ ReadShader(vertShader, VertProgFile);
+ else
+ LoadAndCompileShader(vertShader, vertShaderText);
program = glCreateProgram_func();
glAttachShader_func(program, fragShader);
glAttachShader_func(program, vertShader);
glLinkProgram_func(program);
+ CheckLink(program);
glUseProgram_func(program);
- uLightPos = glGetUniformLocation_func(program, "lightPos");
uDiffuse = glGetUniformLocation_func(program, "diffuse");
uSpecular = glGetUniformLocation_func(program, "specular");
+ uTexture = glGetUniformLocation_func(program, "texture");
+ printf("DiffusePos %d SpecularPos %d TexturePos %d\n",
+ uDiffuse, uSpecular, uTexture);
glUniform4fv_func(uDiffuse, 1, diffuse);
glUniform4fv_func(uSpecular, 1, specular);
+ /* assert(glGetError() == 0);*/
+ glUniform1i_func(uTexture, 2); /* use texture unit 2 */
+ /*assert(glGetError() == 0);*/
+
+ if (CoordAttrib) {
+ int i;
+ glBindAttribLocation_func(program, CoordAttrib, "coord");
+ i = glGetAttribLocation_func(program, "coord");
+ assert(i >= 0);
+ if (i != CoordAttrib) {
+ printf("Hmmm, NVIDIA bug?\n");
+ CoordAttrib = i;
+ }
+ else {
+ printf("Mesa bind attrib: coord = %d\n", i);
+ }
+ }
+
+ /*assert(glGetError() == 0);*/
glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
glEnable(GL_DEPTH_TEST);
@@ -292,11 +535,18 @@ Init(void)
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 20.0f);
+ MakeSphere();
+ MakeRect();
+
+ CurList = SphereList;
+
+ MakeTexture();
+
printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
printf("Press p to toggle between per-pixel and per-vertex lighting\n");
/* test glGetShaderSource() */
- {
+ if (0) {
GLsizei len = strlen(fragShaderText) + 1;
GLsizei lenOut;
GLchar *src =(GLchar *) malloc(len * sizeof(GLchar));
@@ -310,6 +560,35 @@ Init(void)
assert(glIsProgram_func(program));
assert(glIsShader_func(fragShader));
assert(glIsShader_func(vertShader));
+
+ glColor3f(1, 0, 0);
+
+ /* for testing state vars */
+ {
+ static GLfloat fc[4] = { 1, 1, 0, 0 };
+ static GLfloat amb[4] = { 1, 0, 1, 0 };
+ glFogfv(GL_FOG_COLOR, fc);
+ glLightfv(GL_LIGHT1, GL_AMBIENT, amb);
+ }
+
+#if 0
+ TestFunctions();
+#endif
+}
+
+
+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];
+ }
+ }
}
@@ -318,7 +597,7 @@ main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowPosition( 0, 0);
- glutInitWindowSize(200, 200);
+ glutInitWindowSize(100, 100);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
win = glutCreateWindow(argv[0]);
glutReshapeFunc(Reshape);
@@ -327,8 +606,10 @@ main(int argc, char *argv[])
glutDisplayFunc(Redisplay);
if (anim)
glutIdleFunc(Idle);
+ ParseOptions(argc, argv);
Init();
glutMainLoop();
return 0;
}
+
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;
+}
+
diff --git a/progs/tests/Makefile b/progs/tests/Makefile
index 3a22285250..9edef74fb2 100644
--- a/progs/tests/Makefile
+++ b/progs/tests/Makefile
@@ -33,6 +33,7 @@ SOURCES = \
crossbar.c \
cva.c \
dinoshade.c \
+ drawbuffers.c \
floattex.c \
fbotest1.c \
fbotest2.c \
@@ -122,6 +123,12 @@ afsmultiarb: afsmultiarb.o readtex.o
afsmultiarb.o: afsmultiarb.c readtex.h
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
+drawbuffers: drawbuffers.o
+ $(CC) $(CFLAGS) drawbuffers.o $(LIBS) -o $@
+
+drawbuffers.o: drawbuffers.c extfuncs.h
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
+
texrect: texrect.o readtex.o
$(CC) $(CFLAGS) texrect.o readtex.o $(LIBS) -o $@
@@ -150,6 +157,8 @@ readtex.h: $(TOP)/progs/util/readtex.h
readtex.c: $(TOP)/progs/util/readtex.c
ln -s $(TOP)/progs/util/readtex.c .
+extfuncs.h: $(TOP)/progs/util/extfuncs.h
+ ln -s $(TOP)/progs/util/extfuncs.h .
diff --git a/progs/tests/drawbuffers.c b/progs/tests/drawbuffers.c
new file mode 100644
index 0000000000..8583bac0dd
--- /dev/null
+++ b/progs/tests/drawbuffers.c
@@ -0,0 +1,298 @@
+/*
+ * Test GL_ARB_draw_buffers, GL_EXT_framebuffer_object
+ * and GLSL's gl_FragData[].
+ *
+ * Brian Paul
+ * 11 March 2007
+ */
+
+
+#define GL_GLEXT_PROTOTYPES
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <GL/glut.h>
+#include "extfuncs.h"
+
+static int Win;
+static int Width = 400, Height = 400;
+static GLuint FBobject, RBobjects[3];
+static GLfloat Xrot = 0.0, Yrot = 0.0;
+
+
+static void
+CheckError(int line)
+{
+ GLenum err = glGetError();
+ if (err) {
+ printf("GL Error 0x%x at line %d\n", (int) err, line);
+ }
+}
+
+
+static void
+Display(void)
+{
+ GLubyte *buffer = malloc(Width * Height * 4);
+ static const GLenum buffers[2] = {
+ GL_COLOR_ATTACHMENT0_EXT,
+ GL_COLOR_ATTACHMENT1_EXT
+ };
+
+ /* draw to user framebuffer */
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBobject);
+
+ /* Clear color buffer 0 (blue) */
+ glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
+ glClearColor(0.5, 0.5, 1.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* Clear color buffer 1 (1 - blue) */
+ glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
+ glClearColor(0.5, 0.5, 0.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ /* draw to two buffers w/ fragment shader */
+ glDrawBuffersARB(2, buffers);
+
+ glPushMatrix();
+ glRotatef(Xrot, 1, 0, 0);
+ glRotatef(Yrot, 0, 1, 0);
+ glutSolidTorus(0.75, 2.0, 10, 20);
+ glPopMatrix();
+
+ /* read from user framebuffer */
+ /* bottom half = colorbuffer 0 */
+ glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
+ glReadPixels(0, 0, Width, Height / 2, GL_RGBA, GL_UNSIGNED_BYTE,
+ buffer);
+ /* top half = colorbuffer 1 */
+ glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
+ glReadPixels(0, Height/2, Width, Height / 2, GL_RGBA, GL_UNSIGNED_BYTE,
+ buffer + Width * Height / 2 * 4);
+
+ /* draw to window */
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ glWindowPos2iARB(0, 0);
+ glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+
+ free(buffer);
+ glutSwapBuffers();
+ CheckError(__LINE__);
+}
+
+
+static void
+Reshape(int width, int height)
+{
+ float ar = (float) width / (float) height;
+
+ glViewport(0, 0, width, height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-ar, ar, -1.0, 1.0, 5.0, 35.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(0.0, 0.0, -20.0);
+
+ Width = width;
+ Height = height;
+
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[0]);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[1]);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[2]);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
+ Width, Height);
+}
+
+
+static void
+CleanUp(void)
+{
+ glDeleteFramebuffersEXT(1, &FBobject);
+ glDeleteRenderbuffersEXT(3, RBobjects);
+ glutDestroyWindow(Win);
+ exit(0);
+}
+
+
+static void
+Key(unsigned char key, int x, int y)
+{
+ (void) x;
+ (void) y;
+ switch (key) {
+ case 'x':
+ Xrot += 5.0;
+ break;
+ case 'y':
+ Yrot += 5.0;
+ break;
+ case 27:
+ CleanUp();
+ break;
+ }
+ glutPostRedisplay();
+}
+
+
+static void
+CheckExtensions(void)
+{
+ const char *version = (const char *) glGetString(GL_VERSION);
+ GLint numBuf;
+
+ if (!glutExtensionSupported("GL_EXT_framebuffer_object")) {
+ printf("Sorry, GL_EXT_framebuffer_object is required!\n");
+ exit(1);
+ }
+ if (!glutExtensionSupported("GL_ARB_draw_buffers")) {
+ printf("Sorry, GL_ARB_draw_buffers is required!\n");
+ exit(1);
+ }
+ if (version[0] != '2') {
+ printf("Sorry, OpenGL 2.0 is required!\n");
+ exit(1);
+ }
+
+ glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &numBuf);
+ printf("GL_MAX_DRAW_BUFFERS_ARB = %d\n", numBuf);
+ if (numBuf < 2) {
+ printf("Sorry, GL_MAX_DRAW_BUFFERS_ARB needs to be >= 2\n");
+ exit(1);
+ }
+
+ printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
+}
+
+
+static void
+SetupRenderbuffers(void)
+{
+ glGenFramebuffersEXT(1, &FBobject);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBobject);
+
+ glGenRenderbuffersEXT(3, RBobjects);
+
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[0]);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
+
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[1]);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
+
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[2]);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
+ Width, Height);
+
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+ GL_RENDERBUFFER_EXT, RBobjects[0]);
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT,
+ GL_RENDERBUFFER_EXT, RBobjects[1]);
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
+ GL_RENDERBUFFER_EXT, RBobjects[2]);
+
+ CheckError(__LINE__);
+}
+
+
+static GLuint
+LoadAndCompileShader(GLenum target, const char *text)
+{
+ GLint stat;
+ GLuint shader = glCreateShader_func(target);
+ 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, "drawbuffers: problem compiling shader:\n%s\n", log);
+ exit(1);
+ }
+ return shader;
+}
+
+
+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, "drawbuffers: shader link error:\n%s\n", log);
+ }
+}
+
+
+static void
+SetupShaders(void)
+{
+ /* second color output = 1 - first color */
+ static const char *fragShaderText =
+ "void main() {\n"
+ " gl_FragData[0] = gl_Color; \n"
+ " gl_FragData[1] = vec4(1.0) - gl_Color; \n"
+ "}\n";
+
+ GLuint fragShader, program;
+
+ fragShader = LoadAndCompileShader(GL_FRAGMENT_SHADER, fragShaderText);
+ program = glCreateProgram_func();
+
+ glAttachShader_func(program, fragShader);
+ glLinkProgram_func(program);
+ CheckLink(program);
+ glUseProgram_func(program);
+}
+
+
+static void
+SetupLighting(void)
+{
+ static const GLfloat frontMat[4] = { 1.0, 0.5, 0.5, 1.0 };
+ static const GLfloat backMat[4] = { 1.0, 0.5, 0.5, 1.0 };
+
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, frontMat);
+ glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, backMat);
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_LIGHTING);
+}
+
+
+static void
+Init(void)
+{
+ CheckExtensions();
+ GetExtensionFuncs();
+ SetupRenderbuffers();
+ SetupShaders();
+ SetupLighting();
+ glEnable(GL_DEPTH_TEST);
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ glutInit(&argc, argv);
+ glutInitWindowPosition(0, 0);
+ glutInitWindowSize(Width, Height);
+ glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
+ Win = glutCreateWindow(argv[0]);
+ glutReshapeFunc(Reshape);
+ glutKeyboardFunc(Key);
+ glutDisplayFunc(Display);
+ Init();
+ glutMainLoop();
+ return 0;
+}
diff --git a/progs/util/extfuncs.h b/progs/util/extfuncs.h
new file mode 100644
index 0000000000..f5ea5feaa8
--- /dev/null
+++ b/progs/util/extfuncs.h
@@ -0,0 +1,118 @@
+/**
+ * Utility for getting OpenGL extension function pointers
+ * Meant to be #included.
+ */
+
+/* OpenGL 2.0 */
+static PFNGLATTACHSHADERPROC glAttachShader_func = NULL;
+static PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation_func = NULL;
+static PFNGLCOMPILESHADERPROC glCompileShader_func = NULL;
+static PFNGLCREATEPROGRAMPROC glCreateProgram_func = NULL;
+static PFNGLCREATESHADERPROC glCreateShader_func = NULL;
+static PFNGLDELETEPROGRAMPROC glDeleteProgram_func = NULL;
+static PFNGLDELETESHADERPROC glDeleteShader_func = NULL;
+static PFNGLGETATTACHEDSHADERSPROC glGetAttachedShaders_func = NULL;
+static PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation_func = NULL;
+static PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog_func = NULL;
+static PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog_func = NULL;
+static PFNGLGETSHADERIVPROC glGetShaderiv_func = NULL;
+static PFNGLGETPROGRAMIVPROC glGetProgramiv_func = NULL;
+static PFNGLGETSHADERSOURCEPROC glGetShaderSource_func = NULL;
+static PFNGLGETUNIFORMFVPROC glGetUniformfv_func = NULL;
+static PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation_func = NULL;
+static PFNGLISPROGRAMPROC glIsProgram_func = NULL;
+static PFNGLISSHADERPROC glIsShader_func = NULL;
+static PFNGLLINKPROGRAMPROC glLinkProgram_func = NULL;
+static PFNGLSHADERSOURCEPROC glShaderSource_func = NULL;
+static PFNGLUNIFORM1IPROC glUniform1i_func = NULL;
+static PFNGLUNIFORM1FVPROC glUniform1fv_func = NULL;
+static PFNGLUNIFORM2FVPROC glUniform2fv_func = NULL;
+static PFNGLUNIFORM3FVPROC glUniform3fv_func = NULL;
+static PFNGLUNIFORM4FVPROC glUniform4fv_func = NULL;
+static PFNGLUNIFORMMATRIX2FVPROC glUniformMatrix2fv_func = NULL;
+static PFNGLUNIFORMMATRIX3FVPROC glUniformMatrix3fv_func = NULL;
+static PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv_func = NULL;
+static PFNGLUSEPROGRAMPROC glUseProgram_func = NULL;
+static PFNGLVERTEXATTRIB1FPROC glVertexAttrib1f_func = NULL;
+static PFNGLVERTEXATTRIB2FPROC glVertexAttrib2f_func = NULL;
+static PFNGLVERTEXATTRIB3FPROC glVertexAttrib3f_func = NULL;
+static PFNGLVERTEXATTRIB4FPROC glVertexAttrib4f_func = NULL;
+
+
+/* GL_ARB_vertex/fragment_program */
+static PFNGLBINDPROGRAMARBPROC glBindProgramARB_func = NULL;
+static PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB_func = NULL;
+static PFNGLGENPROGRAMSARBPROC glGenProgramsARB_func = NULL;
+static PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC glGetProgramLocalParameterdvARB_func = NULL;
+static PFNGLISPROGRAMARBPROC glIsProgramARB_func = NULL;
+static PFNGLPROGRAMLOCALPARAMETER4DARBPROC glProgramLocalParameter4dARB_func = NULL;
+static PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB_func = NULL;
+static PFNGLPROGRAMSTRINGARBPROC glProgramStringARB_func = NULL;
+static PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB_func = NULL;
+
+/* GL_APPLE_vertex_array_object */
+static PFNGLBINDVERTEXARRAYAPPLEPROC glBindVertexArrayAPPLE_func = NULL;
+static PFNGLDELETEVERTEXARRAYSAPPLEPROC glDeleteVertexArraysAPPLE_func = NULL;
+static PFNGLGENVERTEXARRAYSAPPLEPROC glGenVertexArraysAPPLE_func = NULL;
+static PFNGLISVERTEXARRAYAPPLEPROC glIsVertexArrayAPPLE_func = NULL;
+
+
+
+static void
+GetExtensionFuncs(void)
+{
+ /* OpenGL 2.0 */
+ glAttachShader_func = (PFNGLATTACHSHADERPROC) glutGetProcAddress("glAttachShader");
+ glBindAttribLocation_func = (PFNGLBINDATTRIBLOCATIONPROC) glutGetProcAddress("glBindAttribLocation");
+ glCompileShader_func = (PFNGLCOMPILESHADERPROC) glutGetProcAddress("glCompileShader");
+ glCreateProgram_func = (PFNGLCREATEPROGRAMPROC) glutGetProcAddress("glCreateProgram");
+ glCreateShader_func = (PFNGLCREATESHADERPROC) glutGetProcAddress("glCreateShader");
+ glDeleteProgram_func = (PFNGLDELETEPROGRAMPROC) glutGetProcAddress("glDeleteProgram");
+ glDeleteShader_func = (PFNGLDELETESHADERPROC) glutGetProcAddress("glDeleteShader");
+ glGetAttachedShaders_func = (PFNGLGETATTACHEDSHADERSPROC) glutGetProcAddress("glGetAttachedShaders");
+ glGetAttribLocation_func = (PFNGLGETATTRIBLOCATIONPROC) glutGetProcAddress("glGetAttribLocation");
+ glGetProgramInfoLog_func = (PFNGLGETPROGRAMINFOLOGPROC) glutGetProcAddress("glGetProgramInfoLog");
+ glGetShaderInfoLog_func = (PFNGLGETSHADERINFOLOGPROC) glutGetProcAddress("glGetShaderInfoLog");
+ glGetProgramiv_func = (PFNGLGETPROGRAMIVPROC) glutGetProcAddress("glGetProgramiv");
+ glGetShaderiv_func = (PFNGLGETSHADERIVPROC) glutGetProcAddress("glGetShaderiv");
+ glGetShaderSource_func = (PFNGLGETSHADERSOURCEPROC) glutGetProcAddress("glGetShaderSource");
+ glGetUniformLocation_func = (PFNGLGETUNIFORMLOCATIONPROC) glutGetProcAddress("glGetUniformLocation");
+ glGetUniformfv_func = (PFNGLGETUNIFORMFVPROC) glutGetProcAddress("glGetUniformfv");
+ glIsProgram_func = (PFNGLISPROGRAMPROC) glutGetProcAddress("glIsProgram");
+ glIsShader_func = (PFNGLISSHADERPROC) glutGetProcAddress("glIsShader");
+ glLinkProgram_func = (PFNGLLINKPROGRAMPROC) glutGetProcAddress("glLinkProgram");
+ glShaderSource_func = (PFNGLSHADERSOURCEPROC) glutGetProcAddress("glShaderSource");
+ glUniform1i_func = (PFNGLUNIFORM1IPROC) glutGetProcAddress("glUniform1i");
+ glUniform1fv_func = (PFNGLUNIFORM1FVPROC) glutGetProcAddress("glUniform1fv");
+ glUniform2fv_func = (PFNGLUNIFORM2FVPROC) glutGetProcAddress("glUniform2fv");
+ glUniform3fv_func = (PFNGLUNIFORM3FVPROC) glutGetProcAddress("glUniform3fv");
+ glUniform4fv_func = (PFNGLUNIFORM3FVPROC) glutGetProcAddress("glUniform4fv");
+ glUniformMatrix2fv_func = (PFNGLUNIFORMMATRIX2FVPROC) glutGetProcAddress("glUniformMatrix2fv");
+ glUniformMatrix3fv_func = (PFNGLUNIFORMMATRIX3FVPROC) glutGetProcAddress("glUniformMatrix3fv");
+ glUniformMatrix4fv_func = (PFNGLUNIFORMMATRIX4FVPROC) glutGetProcAddress("glUniformMatrix4fv");
+ glUseProgram_func = (PFNGLUSEPROGRAMPROC) glutGetProcAddress("glUseProgram");
+ glVertexAttrib1f_func = (PFNGLVERTEXATTRIB1FPROC) glutGetProcAddress("glVertexAttrib1f");
+ glVertexAttrib2f_func = (PFNGLVERTEXATTRIB2FPROC) glutGetProcAddress("glVertexAttrib2f");
+ glVertexAttrib3f_func = (PFNGLVERTEXATTRIB3FPROC) glutGetProcAddress("glVertexAttrib3f");
+ glVertexAttrib4f_func = (PFNGLVERTEXATTRIB4FPROC) glutGetProcAddress("glVertexAttrib4f");
+
+
+ /* GL_ARB_vertex/fragment_program */
+ glBindProgramARB_func = (PFNGLBINDPROGRAMARBPROC) glutGetProcAddress("glBindProgramARB");
+ glDeleteProgramsARB_func = (PFNGLDELETEPROGRAMSARBPROC) glutGetProcAddress("glDeleteProgramsARB");
+ glGenProgramsARB_func = (PFNGLGENPROGRAMSARBPROC) glutGetProcAddress("glGenProgramsARB");
+ glGetProgramLocalParameterdvARB_func = (PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) glutGetProcAddress("glGetProgramLocalParameterdvARB");
+ glIsProgramARB_func = (PFNGLISPROGRAMARBPROC) glutGetProcAddress("glIsProgramARB");
+ glProgramLocalParameter4dARB_func = (PFNGLPROGRAMLOCALPARAMETER4DARBPROC) glutGetProcAddress("glProgramLocalParameter4dARB");
+ glProgramLocalParameter4fvARB_func = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) glutGetProcAddress("glProgramLocalParameter4fvARB");
+ glProgramStringARB_func = (PFNGLPROGRAMSTRINGARBPROC) glutGetProcAddress("glProgramStringARB");
+ glVertexAttrib1fARB_func = (PFNGLVERTEXATTRIB1FARBPROC) glutGetProcAddress("glVertexAttrib1fARB");
+
+ /* GL_APPLE_vertex_array_object */
+ glBindVertexArrayAPPLE_func = (PFNGLBINDVERTEXARRAYAPPLEPROC) glutGetProcAddress("glBindVertexArrayAPPLE");
+ glDeleteVertexArraysAPPLE_func = (PFNGLDELETEVERTEXARRAYSAPPLEPROC) glutGetProcAddress("glDeleteVertexArraysAPPLE");
+ glGenVertexArraysAPPLE_func = (PFNGLGENVERTEXARRAYSAPPLEPROC) glutGetProcAddress("glGenVertexArraysAPPLE");
+ glIsVertexArrayAPPLE_func = (PFNGLISVERTEXARRAYAPPLEPROC) glutGetProcAddress("glIsVertexArrayAPPLE");
+
+}
+