summaryrefslogtreecommitdiff
path: root/progs/glsl
diff options
context:
space:
mode:
Diffstat (limited to 'progs/glsl')
-rw-r--r--progs/glsl/.gitignore7
-rw-r--r--progs/glsl/CH06-brick.frag (renamed from progs/glsl/CH06-brick.frag.txt)0
-rw-r--r--progs/glsl/CH06-brick.vert (renamed from progs/glsl/CH06-brick.vert.txt)0
-rw-r--r--progs/glsl/CH11-bumpmap.frag (renamed from progs/glsl/CH11-bumpmap.frag.txt)0
-rw-r--r--progs/glsl/CH11-bumpmap.vert (renamed from progs/glsl/CH11-bumpmap.vert.txt)0
-rw-r--r--progs/glsl/CH11-toyball.frag (renamed from progs/glsl/CH11-toyball.frag.txt)0
-rw-r--r--progs/glsl/CH11-toyball.vert (renamed from progs/glsl/CH11-toyball.vert.txt)0
-rw-r--r--progs/glsl/CH18-mandel.frag (renamed from progs/glsl/CH18-mandel.frag.txt)0
-rw-r--r--progs/glsl/CH18-mandel.vert (renamed from progs/glsl/CH18-mandel.vert.txt)0
-rw-r--r--progs/glsl/Makefile124
-rw-r--r--progs/glsl/bitmap.c323
-rw-r--r--progs/glsl/brick.c138
-rw-r--r--progs/glsl/bump.c139
-rw-r--r--progs/glsl/convolutions.c16
-rw-r--r--progs/glsl/cubemap.frag (renamed from progs/glsl/cubemap.frag.txt)0
-rw-r--r--progs/glsl/deriv.c90
-rw-r--r--progs/glsl/mandelbrot.c150
-rw-r--r--progs/glsl/multitex.c285
-rw-r--r--progs/glsl/multitex.frag15
-rw-r--r--progs/glsl/multitex.vert10
-rw-r--r--progs/glsl/noise.c102
-rw-r--r--progs/glsl/pointcoord.c205
-rw-r--r--progs/glsl/points.c260
-rw-r--r--progs/glsl/reflect.vert (renamed from progs/glsl/reflect.vert.txt)0
-rw-r--r--progs/glsl/shadowtex.frag (renamed from progs/glsl/shadowtex.frag.txt)0
-rw-r--r--progs/glsl/simple.vert (renamed from progs/glsl/simple.vert.txt)0
-rw-r--r--progs/glsl/texdemo1.c163
-rw-r--r--progs/glsl/toyball.c163
-rw-r--r--progs/glsl/trirast.c259
-rw-r--r--progs/glsl/twoside.c294
30 files changed, 1899 insertions, 844 deletions
diff --git a/progs/glsl/.gitignore b/progs/glsl/.gitignore
index 81ecf5bdd5..09340ff2ad 100644
--- a/progs/glsl/.gitignore
+++ b/progs/glsl/.gitignore
@@ -1,11 +1,18 @@
+bitmap
brick
bump
convolutions
deriv
extfuncs.h
mandelbrot
+multitex
noise
+points
readtex.c
readtex.h
+shaderutil.c
+shaderutil.h
texdemo1
toyball
+trirast
+twoside
diff --git a/progs/glsl/CH06-brick.frag.txt b/progs/glsl/CH06-brick.frag
index 06ef04e3af..06ef04e3af 100644
--- a/progs/glsl/CH06-brick.frag.txt
+++ b/progs/glsl/CH06-brick.frag
diff --git a/progs/glsl/CH06-brick.vert.txt b/progs/glsl/CH06-brick.vert
index e95e6f42f0..e95e6f42f0 100644
--- a/progs/glsl/CH06-brick.vert.txt
+++ b/progs/glsl/CH06-brick.vert
diff --git a/progs/glsl/CH11-bumpmap.frag.txt b/progs/glsl/CH11-bumpmap.frag
index 063576f5a3..063576f5a3 100644
--- a/progs/glsl/CH11-bumpmap.frag.txt
+++ b/progs/glsl/CH11-bumpmap.frag
diff --git a/progs/glsl/CH11-bumpmap.vert.txt b/progs/glsl/CH11-bumpmap.vert
index d3d19f62ac..d3d19f62ac 100644
--- a/progs/glsl/CH11-bumpmap.vert.txt
+++ b/progs/glsl/CH11-bumpmap.vert
diff --git a/progs/glsl/CH11-toyball.frag.txt b/progs/glsl/CH11-toyball.frag
index 90ec1c27fc..90ec1c27fc 100644
--- a/progs/glsl/CH11-toyball.frag.txt
+++ b/progs/glsl/CH11-toyball.frag
diff --git a/progs/glsl/CH11-toyball.vert.txt b/progs/glsl/CH11-toyball.vert
index b7da3ac839..b7da3ac839 100644
--- a/progs/glsl/CH11-toyball.vert.txt
+++ b/progs/glsl/CH11-toyball.vert
diff --git a/progs/glsl/CH18-mandel.frag.txt b/progs/glsl/CH18-mandel.frag
index a472d81252..a472d81252 100644
--- a/progs/glsl/CH18-mandel.frag.txt
+++ b/progs/glsl/CH18-mandel.frag
diff --git a/progs/glsl/CH18-mandel.vert.txt b/progs/glsl/CH18-mandel.vert
index c4ca66405d..c4ca66405d 100644
--- a/progs/glsl/CH18-mandel.vert.txt
+++ b/progs/glsl/CH18-mandel.vert
diff --git a/progs/glsl/Makefile b/progs/glsl/Makefile
index b9cae66815..ba7a4c688f 100644
--- a/progs/glsl/Makefile
+++ b/progs/glsl/Makefile
@@ -7,13 +7,23 @@ INCDIR = $(TOP)/include
LIB_DEP = $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) $(TOP)/$(LIB_DIR)/$(GLU_LIB_NAME) $(TOP)/$(LIB_DIR)/$(GLUT_LIB_NAME)
+LIBS = -L$(TOP)/$(LIB_DIR) -l$(GLUT_LIB) -l$(GLU_LIB) -l$(GL_LIB) $(APP_LIB_DEPS)
+
PROGS = \
+ bitmap \
brick \
bump \
+ convolutions \
deriv \
mandelbrot \
+ multitex \
noise \
+ points \
+ pointcoord \
+ texdemo1 \
toyball \
+ twoside \
+ trirast \
texdemo1 \
convolutions
@@ -26,7 +36,7 @@ PROGS = \
# make executable from .c file:
.c: $(LIB_DEP)
- $(CC) -I$(INCDIR) $(CFLAGS) $< $(APP_LIB_DEPS) -o $@
+ $(CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) $< $(LIBS) -o $@
##### TARGETS #####
@@ -40,6 +50,7 @@ default: $(PROGS)
extfuncs.h: $(TOP)/progs/util/extfuncs.h
cp $< .
+
readtex.c: $(TOP)/progs/util/readtex.c
cp $< .
@@ -49,20 +60,116 @@ readtex.h: $(TOP)/progs/util/readtex.h
readtex.o: readtex.c readtex.h
$(CC) -c -I$(INCDIR) $(CFLAGS) readtex.c
-brick.c: extfuncs.h
-bump.c: extfuncs.h
+shaderutil.c: $(TOP)/progs/util/shaderutil.c
+ cp $< .
+
+shaderutil.h: $(TOP)/progs/util/shaderutil.h
+ cp $< .
+
+shaderutil.o: shaderutil.c shaderutil.h
+ $(CC) -c -I$(INCDIR) $(CFLAGS) shaderutil.c
+
+
+
+bitmap.o: bitmap.c extfuncs.h shaderutil.h
+ $(CC) -c -I$(INCDIR) $(CFLAGS) bitmap.c
+
+bitmap: bitmap.o shaderutil.o
+ $(CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) bitmap.o shaderutil.o $(LIBS) -o $@
+
+
+brick.o: brick.c extfuncs.h shaderutil.h
+ $(CC) -c -I$(INCDIR) $(CFLAGS) brick.c
+
+brick: brick.o shaderutil.o
+ $(CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) brick.o shaderutil.o $(LIBS) -o $@
+
+
+bump.o: bump.c extfuncs.h shaderutil.h
+ $(CC) -c -I$(INCDIR) $(CFLAGS) bump.c
+
+bump: bump.o shaderutil.o
+ $(CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) bump.o shaderutil.o $(LIBS) -o $@
+
+
+convolutions.o: convolutions.c readtex.h
+ $(CC) -c -I$(INCDIR) $(CFLAGS) convolutions.c
+
+convolutions: convolutions.o readtex.o
+ $(CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) convolutions.o readtex.o $(LIBS) -o $@
+
+
+deriv.o: deriv.c extfuncs.h shaderutil.h
+ $(CC) -c -I$(INCDIR) $(CFLAGS) deriv.c
-mandelbrot.c: extfuncs.h
+deriv: deriv.o shaderutil.o
+ $(CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) deriv.o shaderutil.o $(LIBS) -o $@
-toyball.c: extfuncs.h
-texdemo1: texdemo1.o readtex.o
- $(CC) -I$(INCDIR) $(CFLAGS) texdemo1.o readtex.o $(APP_LIB_DEPS) -o $@
+mandelbrot.o: mandelbrot.c extfuncs.h shaderutil.h
+ $(CC) -c -I$(INCDIR) $(CFLAGS) mandelbrot.c
-texdemo1.o: texdemo1.c readtex.h extfuncs.h
+mandelbrot: mandelbrot.o shaderutil.o
+ $(CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) mandelbrot.o shaderutil.o $(LIBS) -o $@
+
+
+multitex.o: multitex.c extfuncs.h readtex.h shaderutil.h
+ $(CC) -c -I$(INCDIR) $(CFLAGS) multitex.c
+
+multitex: multitex.o readtex.o shaderutil.o
+ $(CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) multitex.o readtex.o shaderutil.o $(LIBS) -o $@
+
+
+noise.o: noise.c extfuncs.h shaderutil.h
+ $(CC) -c -I$(INCDIR) $(CFLAGS) noise.c
+
+noise: noise.o shaderutil.o
+ $(CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) noise.o shaderutil.o $(LIBS) -o $@
+
+
+points.o: points.c extfuncs.h shaderutil.h
+ $(CC) -c -I$(INCDIR) $(CFLAGS) points.c
+
+points: points.o shaderutil.o
+ $(CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) points.o shaderutil.o $(LIBS) -o $@
+
+
+pointcoord.o: pointcoord.c readtex.h extfuncs.h shaderutil.h
+ $(CC) -c -I$(INCDIR) $(CFLAGS) pointcoord.c
+
+pointcoord: pointcoord.o readtex.o shaderutil.o
+ $(CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) pointcoord.o readtex.o shaderutil.o $(LIBS) -o $@
+
+
+texdemo1.o: texdemo1.c readtex.h extfuncs.h shaderutil.h
$(CC) -c -I$(INCDIR) $(CFLAGS) texdemo1.c
+texdemo1: texdemo1.o readtex.o shaderutil.o
+ $(CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) texdemo1.o readtex.o shaderutil.o $(LIBS) -o $@
+
+
+toyball.o: toyball.c extfuncs.h shaderutil.h
+ $(CC) -c -I$(INCDIR) $(CFLAGS) toyball.c
+
+toyball: toyball.o shaderutil.o
+ $(CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) toyball.o shaderutil.o $(LIBS) -o $@
+
+
+twoside.o: twoside.c extfuncs.h shaderutil.h
+ $(CC) -c -I$(INCDIR) $(CFLAGS) twoside.c
+
+twoside: twoside.o shaderutil.o
+ $(CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) twoside.o shaderutil.o $(LIBS) -o $@
+
+
+trirast.o: trirast.c extfuncs.h shaderutil.h
+ $(CC) -c -I$(INCDIR) $(CFLAGS) trirast.c
+
+trirast: trirast.o shaderutil.o
+ $(CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) trirast.o shaderutil.o $(LIBS) -o $@
+
+
convolutions: convolutions.o readtex.o
$(CC) -I$(INCDIR) $(CFLAGS) convolutions.o readtex.o $(APP_LIB_DEPS) -o $@
@@ -74,3 +181,4 @@ clean:
-rm -f $(PROGS)
-rm -f *.o *~
-rm -f extfuncs.h
+ -rm -f shaderutil.*
diff --git a/progs/glsl/bitmap.c b/progs/glsl/bitmap.c
new file mode 100644
index 0000000000..d488ec6cb9
--- /dev/null
+++ b/progs/glsl/bitmap.c
@@ -0,0 +1,323 @@
+/**
+ * Implement glRasterPos + glBitmap with textures + shaders.
+ * Brian Paul
+ * 14 May 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"
+#include "shaderutil.h"
+
+
+static GLuint FragShader;
+static GLuint VertShader;
+static GLuint Program;
+
+static GLint Win = 0;
+static GLint WinWidth = 500, WinHeight = 500;
+static GLboolean Anim = GL_TRUE;
+static GLboolean Bitmap = GL_FALSE;
+static GLfloat Xrot = 20.0f, Yrot = 70.0f;
+static GLint uTex, uScale;
+static GLuint Textures[2];
+
+#define TEX_WIDTH 16
+#define TEX_HEIGHT 8
+
+
+static void
+BitmapText(const char *s)
+{
+ while (*s) {
+ glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
+ s++;
+ }
+}
+
+
+static void
+Redisplay(void)
+{
+ static const GLfloat px[3] = { 1.2, 0, 0};
+ static const GLfloat nx[3] = {-1.2, 0, 0};
+
+ 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);
+
+ glEnable(GL_LIGHTING);
+
+ glPushMatrix();
+ glScalef(0.5, 0.5, 0.5);
+ glutSolidDodecahedron();
+ glPopMatrix();
+
+ glDisable(GL_LIGHTING);
+
+ glColor3f(0, 1, 0);
+ glBegin(GL_LINES);
+ glVertex3f(-1, 0, 0);
+ glVertex3f( 1, 0, 0);
+ glEnd();
+
+ glColor3f(1, 1, 0);
+
+ if (Bitmap) {
+ glRasterPos3fv(px);
+ BitmapText("+X");
+ glRasterPos3fv(nx);
+ BitmapText("-X");
+ }
+ else {
+ glUseProgram_func(Program);
+
+ /* vertex positions (deltas) depend on texture size and window size */
+ if (uScale != -1) {
+ glUniform2f_func(uScale,
+ 2.0 * TEX_WIDTH / WinWidth,
+ 2.0 * TEX_HEIGHT / WinHeight);
+ }
+
+ /* draw +X */
+ glBindTexture(GL_TEXTURE_2D, Textures[0]);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0, 0); glVertex3fv(px);
+ glTexCoord2f(1, 0); glVertex3fv(px);
+ glTexCoord2f(1, 1); glVertex3fv(px);
+ glTexCoord2f(0, 1); glVertex3fv(px);
+ glEnd();
+
+ /* draw -X */
+ glBindTexture(GL_TEXTURE_2D, Textures[1]);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0, 0); glVertex3fv(nx);
+ glTexCoord2f(1, 0); glVertex3fv(nx);
+ glTexCoord2f(1, 1); glVertex3fv(nx);
+ glTexCoord2f(0, 1); glVertex3fv(nx);
+ glEnd();
+
+ glUseProgram_func(0);
+ }
+
+ glPopMatrix();
+
+ glutSwapBuffers();
+}
+
+
+static void
+Idle(void)
+{
+ Yrot = glutGet(GLUT_ELAPSED_TIME) * 0.01;
+ glutPostRedisplay();
+}
+
+
+static void
+Reshape(int width, int height)
+{
+ WinWidth = width;
+ WinHeight = 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, -10.0f);
+}
+
+
+static void
+Key(unsigned char key, int x, int y)
+{
+ (void) x;
+ (void) y;
+
+ switch(key) {
+ case ' ':
+ case 'a':
+ Anim = !Anim;
+ if (Anim)
+ glutIdleFunc(Idle);
+ else
+ glutIdleFunc(NULL);
+ break;
+ case 'b':
+ Bitmap = !Bitmap;
+ if (Bitmap)
+ printf("Using glBitmap\n");
+ else
+ printf("Using billboard texture\n");
+ break;
+ case 27:
+ glDeleteShader_func(FragShader);
+ glDeleteShader_func(VertShader);
+ glDeleteProgram_func(Program);
+ glutDestroyWindow(Win);
+ exit(0);
+ }
+ glutPostRedisplay();
+}
+
+
+static void
+SpecialKey(int key, int x, int y)
+{
+ const GLfloat step = 0.125f;
+ 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;
+ }
+ /*printf("Xrot: %f Yrot: %f\n", Xrot, Yrot);*/
+ glutPostRedisplay();
+}
+
+
+static void
+MakeTexImage(const char *p, GLuint texobj)
+{
+ GLubyte image[TEX_HEIGHT][TEX_WIDTH];
+ GLuint i, j, k;
+
+ for (i = 0; i < TEX_HEIGHT; i++) {
+ for (j = 0; j < TEX_WIDTH; j++) {
+ k = i * TEX_WIDTH + j;
+ if (p[k] == ' ') {
+ image[i][j] = 0;
+ }
+ else {
+ image[i][j] = 255;
+ }
+ }
+ }
+
+ glBindTexture(GL_TEXTURE_2D, texobj);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY, TEX_WIDTH, TEX_HEIGHT, 0,
+ GL_RED, GL_UNSIGNED_BYTE, image);
+ 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);
+}
+
+
+static void
+MakeBitmapTextures(void)
+{
+ const char *px =
+ " X X "
+ " X X X "
+ " X X X "
+ " XXXXX X "
+ " X X X "
+ " X X X "
+ " X X "
+ " X X ";
+ const char *nx =
+ " X X "
+ " X X "
+ " X X "
+ " XXXXX X "
+ " X X "
+ " X X "
+ " X X "
+ " X X ";
+ glGenTextures(2, Textures);
+ MakeTexImage(px, Textures[0]);
+ MakeTexImage(nx, Textures[1]);
+}
+
+
+static void
+Init(void)
+{
+ /* Fragment shader: modulate raster color by texture, discard fragments
+ * with alpha < 1.0
+ */
+ static const char *fragShaderText =
+ "uniform sampler2D tex2d; \n"
+ "void main() {\n"
+ " vec4 c = texture2D(tex2d, gl_TexCoord[0].xy); \n"
+ " if (c.w < 1.0) \n"
+ " discard; \n"
+ " gl_FragColor = c * gl_Color; \n"
+ "}\n";
+ /* Vertex shader: compute new vertex position based on incoming vertex pos,
+ * texcoords and special scale factor.
+ */
+ static const char *vertShaderText =
+ "uniform vec2 scale; \n"
+ "void main() {\n"
+ " vec4 p = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
+ " gl_Position.xy = p.xy + gl_MultiTexCoord0.xy * scale * p.w; \n"
+ " gl_Position.zw = p.zw; \n"
+ " gl_TexCoord[0] = gl_MultiTexCoord0; \n"
+ " gl_FrontColor = gl_Color; \n"
+ "}\n";
+
+ if (!ShadersSupported())
+ exit(1);
+
+ GetExtensionFuncs();
+
+ VertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText);
+ FragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText);
+ Program = LinkShaders(VertShader, FragShader);
+
+ glUseProgram_func(Program);
+
+ uScale = glGetUniformLocation_func(Program, "scale");
+ uTex = glGetUniformLocation_func(Program, "tex2d");
+ if (uTex != -1) {
+ glUniform1i_func(uTex, 0); /* tex unit 0 */
+ }
+
+ glUseProgram_func(0);
+
+ glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_NORMALIZE);
+ glEnable(GL_LIGHT0);
+
+ MakeBitmapTextures();
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ glutInit(&argc, argv);
+ glutInitWindowSize(WinWidth, WinHeight);
+ glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
+ Win = glutCreateWindow(argv[0]);
+ glutReshapeFunc(Reshape);
+ glutKeyboardFunc(Key);
+ glutSpecialFunc(SpecialKey);
+ glutDisplayFunc(Redisplay);
+ if (Anim)
+ glutIdleFunc(Idle);
+ Init();
+ glutMainLoop();
+ return 0;
+}
+
+
diff --git a/progs/glsl/brick.c b/progs/glsl/brick.c
index 522698b5d4..526ef0e2e3 100644
--- a/progs/glsl/brick.c
+++ b/progs/glsl/brick.c
@@ -13,33 +13,26 @@
#include <GL/glut.h>
#include <GL/glext.h>
#include "extfuncs.h"
+#include "shaderutil.h"
-static char *FragProgFile = "CH06-brick.frag.txt";
-static char *VertProgFile = "CH06-brick.vert.txt";
+static char *FragProgFile = "CH06-brick.frag";
+static char *VertProgFile = "CH06-brick.vert";
/* 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} },
+ { "LightPosition", 3, GL_FLOAT, { 0.1, 0.1, 9.0, 0}, -1 },
/* 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 } }
+ { "BrickColor", 3, GL_FLOAT, { 0.8, 0.2, 0.2, 0 }, -1 },
+ { "MortarColor", 3, GL_FLOAT, { 0.6, 0.6, 0.6, 0 }, -1 },
+ { "BrickSize", 2, GL_FLOAT, { 1.0, 0.3, 0, 0 }, -1 },
+ { "BrickPct", 2, GL_FLOAT, { 0.9, 0.8, 0, 0 }, -1 },
+ END_OF_UNIFORMS
};
static GLint win = 0;
@@ -146,121 +139,20 @@ SpecialKey(int key, int x, int y)
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);*/
- }
+ if (!ShadersSupported())
+ exit(1);
GetExtensionFuncs();
- vertShader = glCreateShader_func(GL_VERTEX_SHADER);
- ReadShader(vertShader, VertProgFile);
-
- fragShader = glCreateShader_func(GL_FRAGMENT_SHADER);
- ReadShader(fragShader, FragProgFile);
+ vertShader = CompileShaderFile(GL_VERTEX_SHADER, VertProgFile);
+ fragShader = CompileShaderFile(GL_FRAGMENT_SHADER, FragProgFile);
+ program = LinkShaders(vertShader, fragShader);
- 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();
- }
- }
+ InitUniforms(program, Uniforms);
assert(glGetError() == 0);
diff --git a/progs/glsl/bump.c b/progs/glsl/bump.c
index a6846acf7e..a2e0916861 100644
--- a/progs/glsl/bump.c
+++ b/progs/glsl/bump.c
@@ -13,10 +13,11 @@
#include <GL/glu.h>
#include <GL/glext.h>
#include "extfuncs.h"
+#include "shaderutil.h"
-static char *FragProgFile = "CH11-bumpmap.frag.txt";
-static char *VertProgFile = "CH11-bumpmap.vert.txt";
+static char *FragProgFile = "CH11-bumpmap.frag";
+static char *VertProgFile = "CH11-bumpmap.vert";
/* program/shader objects */
static GLuint fragShader;
@@ -24,20 +25,13 @@ 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 } }
+ { "LightPosition", 3, GL_FLOAT, { 0.57737, 0.57735, 0.57735, 0.0 }, -1 },
+ { "SurfaceColor", 3, GL_FLOAT, { 0.8, 0.8, 0.2, 0 }, -1 },
+ { "BumpDensity", 1, GL_FLOAT, { 10.0, 0, 0, 0 }, -1 },
+ { "BumpSize", 1, GL_FLOAT, { 0.125, 0, 0, 0 }, -1 },
+ { "SpecularFactor", 1, GL_FLOAT, { 0.5, 0, 0, 0 }, -1 },
+ END_OF_UNIFORMS
};
static GLint win = 0;
@@ -232,100 +226,18 @@ SpecialKey(int key, int x, int y)
}
-
-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));
+ if (!ShadersSupported())
+ exit(1);
GetExtensionFuncs();
- vertShader = glCreateShader_func(GL_VERTEX_SHADER);
- ReadShader(vertShader, VertProgFile);
-
- fragShader = glCreateShader_func(GL_FRAGMENT_SHADER);
- ReadShader(fragShader, FragProgFile);
+ vertShader = CompileShaderFile(GL_VERTEX_SHADER, VertProgFile);
+ fragShader = CompileShaderFile(GL_FRAGMENT_SHADER, FragProgFile);
+ program = LinkShaders(vertShader, fragShader);
- program = glCreateProgram_func();
- glAttachShader_func(program, fragShader);
- glAttachShader_func(program, vertShader);
- glLinkProgram_func(program);
- CheckLink(program);
glUseProgram_func(program);
assert(glIsProgram_func(program));
@@ -336,28 +248,7 @@ Init(void)
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();
- }
- }
+ InitUniforms(program, Uniforms);
CheckError(__LINE__);
diff --git a/progs/glsl/convolutions.c b/progs/glsl/convolutions.c
index 9b9ee53245..a25dad5ba9 100644
--- a/progs/glsl/convolutions.c
+++ b/progs/glsl/convolutions.c
@@ -1,3 +1,10 @@
+/**
+ * Convolution with GLSL.
+ * Note: uses GL_ARB_shader_objects, GL_ARB_vertex_shader, GL_ARB_fragment_shader,
+ * not the OpenGL 2.0 shader API.
+ * Author: Zack Rusin
+ */
+
#define GL_GLEXT_PROTOTYPES
#include "readtex.h"
@@ -227,9 +234,11 @@ static void createProgram(const char *vertProgFile,
glUseProgram(program);
+ /*
assert(glIsProgram(program));
assert(glIsShader(fragShader));
assert(glIsShader(vertShader));
+ */
checkError(__LINE__);
{/*texture*/
@@ -316,6 +325,13 @@ static void menuInit()
static void init()
{
+ if (!glutExtensionSupported("GL_ARB_shader_objects") ||
+ !glutExtensionSupported("GL_ARB_vertex_shader") ||
+ !glutExtensionSupported("GL_ARB_fragment_shader")) {
+ fprintf(stderr, "Sorry, this program requires GL_ARB_shader_objects, GL_ARB_vertex_shader, and GL_ARB_fragment_shader\n");
+ exit(1);
+ }
+
fprintf(stderr, "GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
fprintf(stderr, "GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
fprintf(stderr, "GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
diff --git a/progs/glsl/cubemap.frag.txt b/progs/glsl/cubemap.frag
index 9c27648aaf..9c27648aaf 100644
--- a/progs/glsl/cubemap.frag.txt
+++ b/progs/glsl/cubemap.frag
diff --git a/progs/glsl/deriv.c b/progs/glsl/deriv.c
index 8b652bc1e4..e69f0b82c4 100644
--- a/progs/glsl/deriv.c
+++ b/progs/glsl/deriv.c
@@ -17,6 +17,7 @@
#include <GL/glut.h>
#include <GL/glext.h>
#include "extfuncs.h"
+#include "shaderutil.h"
static char *FragProgFile = NULL;
@@ -159,68 +160,6 @@ MakeRect(void)
}
-
-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)
{
@@ -234,33 +173,16 @@ Init(void)
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
" gl_TexCoord[0] = gl_MultiTexCoord0;\n"
"}\n";
- const char *version;
- version = (const char *) glGetString(GL_VERSION);
- if (version[0] != '2' || version[1] != '.') {
- printf("This program requires OpenGL 2.x, found %s\n", version);
+ if (!ShadersSupported())
exit(1);
- }
GetExtensionFuncs();
- fragShader = glCreateShader_func(GL_FRAGMENT_SHADER);
- if (FragProgFile)
- ReadShader(fragShader, FragProgFile);
- else
- LoadAndCompileShader(fragShader, fragShaderText);
-
- vertShader = glCreateShader_func(GL_VERTEX_SHADER);
- 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);
+ vertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText);
+ fragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText);
+ program = LinkShaders(vertShader, fragShader);
+
glUseProgram_func(program);
/*assert(glGetError() == 0);*/
diff --git a/progs/glsl/mandelbrot.c b/progs/glsl/mandelbrot.c
index 7a2bad6dde..e6361b429b 100644
--- a/progs/glsl/mandelbrot.c
+++ b/progs/glsl/mandelbrot.c
@@ -13,10 +13,11 @@
#include <GL/glut.h>
#include <GL/glext.h>
#include "extfuncs.h"
+#include "shaderutil.h"
-static char *FragProgFile = "CH18-mandel.frag.txt";
-static char *VertProgFile = "CH18-mandel.vert.txt";
+static char *FragProgFile = "CH18-mandel.frag";
+static char *VertProgFile = "CH18-mandel.vert";
/* program/shader objects */
static GLuint fragShader;
@@ -24,28 +25,21 @@ 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 } },
+ { "LightPosition", 3, GL_FLOAT, { 0.1, 0.1, 9.0, 0}, -1 },
+ { "SpecularContribution", 1, GL_FLOAT, { 0.5, 0, 0, 0 }, -1 },
+ { "DiffuseContribution", 1, GL_FLOAT, { 0.5, 0, 0, 0 }, -1 },
+ { "Shininess", 1, GL_FLOAT, { 20.0, 0, 0, 0 }, -1 },
/* 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 } }
+ { "MaxIterations", 1, GL_FLOAT, { 12, 0, 0, 0 }, -1 },
+ { "Zoom", 1, GL_FLOAT, { 0.125, 0, 0, 0 }, -1 },
+ { "Xcenter", 1, GL_FLOAT, { -1.5, 0, 0, 0 }, -1 },
+ { "Ycenter", 1, GL_FLOAT, { .005, 0, 0, 0 }, -1 },
+ { "InnerColor", 3, GL_FLOAT, { 1, 0, 0, 0 }, -1 },
+ { "OuterColor1", 3, GL_FLOAT, { 0, 1, 0, 0 }, -1 },
+ { "OuterColor2", 3, GL_FLOAT, { 0, 0, 1, 0 }, -1 },
+ END_OF_UNIFORMS
};
static GLint win = 0;
@@ -157,123 +151,21 @@ SpecialKey(int key, int x, int y)
}
-
-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);*/
- }
+ if (!ShadersSupported())
+ exit(1);
GetExtensionFuncs();
- vertShader = glCreateShader_func(GL_VERTEX_SHADER);
- ReadShader(vertShader, VertProgFile);
-
- fragShader = glCreateShader_func(GL_FRAGMENT_SHADER);
- ReadShader(fragShader, FragProgFile);
+ vertShader = CompileShaderFile(GL_VERTEX_SHADER, VertProgFile);
+ fragShader = CompileShaderFile(GL_FRAGMENT_SHADER, FragProgFile);
+ program = LinkShaders(vertShader, fragShader);
- 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();
- }
- }
+ InitUniforms(program, Uniforms);
uZoom = glGetUniformLocation_func(program, "Zoom");
uXcenter = glGetUniformLocation_func(program, "Xcenter");
diff --git a/progs/glsl/multitex.c b/progs/glsl/multitex.c
new file mode 100644
index 0000000000..096d40f64d
--- /dev/null
+++ b/progs/glsl/multitex.c
@@ -0,0 +1,285 @@
+/**
+ * Test multi-texturing with GL shading language.
+ *
+ * Copyright (C) 2008 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"
+#include "shaderutil.h"
+
+static const char *Demo = "multitex";
+
+static const char *VertFile = "multitex.vert";
+static const char *FragFile = "multitex.frag";
+
+static const char *TexFiles[2] =
+ {
+ "../images/tile.rgb",
+ "../images/tree2.rgba"
+ };
+
+
+static GLuint Program;
+
+static GLfloat Xrot = -90.0, Yrot = .0, Zrot = 0.0;
+static GLfloat EyeDist = 10;
+static GLboolean Anim = GL_TRUE;
+
+
+/* value[0] = tex unit */
+static struct uniform_info Uniforms[] = {
+ { "tex1", 1, GL_INT, { 0, 0, 0, 0 }, -1 },
+ { "tex2", 1, GL_INT, { 1, 0, 0, 0 }, -1 },
+ END_OF_UNIFORMS
+};
+
+
+static void
+DrawPolygon(GLfloat size)
+{
+ glPushMatrix();
+ glRotatef(90, 1, 0, 0);
+ glNormal3f(0, 0, 1);
+ glBegin(GL_POLYGON);
+
+ glMultiTexCoord2f(GL_TEXTURE0, 0, 0);
+ glMultiTexCoord2f(GL_TEXTURE1, 0, 0);
+ glVertex2f(-size, -size);
+
+ glMultiTexCoord2f(GL_TEXTURE0, 2, 0);
+ glMultiTexCoord2f(GL_TEXTURE1, 1, 0);
+ glVertex2f( size, -size);
+
+ glMultiTexCoord2f(GL_TEXTURE0, 2, 2);
+ glMultiTexCoord2f(GL_TEXTURE1, 1, 1);
+ glVertex2f( size, size);
+
+ glMultiTexCoord2f(GL_TEXTURE0, 0, 2);
+ glMultiTexCoord2f(GL_TEXTURE1, 0, 1);
+ glVertex2f(-size, size);
+
+ glEnd();
+ glPopMatrix();
+}
+
+
+static void
+draw(void)
+{
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glPushMatrix(); /* modelview matrix */
+ glTranslatef(0.0, 0.0, -EyeDist);
+ glRotatef(Zrot, 0, 0, 1);
+ glRotatef(Yrot, 0, 1, 0);
+ glRotatef(Xrot, 1, 0, 0);
+
+ DrawPolygon(3.0);
+
+ glPopMatrix();
+
+ glutSwapBuffers();
+}
+
+
+static void
+idle(void)
+{
+ GLfloat t = 0.05 * glutGet(GLUT_ELAPSED_TIME);
+ Yrot = 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 < 3.0)
+ EyeDist = 3.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
+InitTextures(void)
+{
+ GLenum filter = GL_LINEAR;
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ GLint imgWidth, imgHeight;
+ GLenum imgFormat;
+ GLubyte *image = NULL;
+
+ image = LoadRGBImage(TexFiles[i], &imgWidth, &imgHeight, &imgFormat);
+ if (!image) {
+ printf("Couldn't read %s\n", TexFiles[i]);
+ exit(0);
+ }
+
+ glActiveTexture(GL_TEXTURE0 + i);
+ glBindTexture(GL_TEXTURE_2D, 42 + i);
+ gluBuild2DMipmaps(GL_TEXTURE_2D, 4, 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, filter);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
+ }
+}
+
+
+static GLuint
+CreateProgram(const char *vertProgFile, const char *fragProgFile,
+ struct uniform_info *uniforms)
+{
+ GLuint fragShader, vertShader, program;
+
+ vertShader = CompileShaderFile(GL_VERTEX_SHADER, vertProgFile);
+ fragShader = CompileShaderFile(GL_FRAGMENT_SHADER, fragProgFile);
+ assert(vertShader);
+ program = LinkShaders(vertShader, fragShader);
+
+ glUseProgram_func(program);
+
+ InitUniforms(program, uniforms);
+
+ return program;
+}
+
+
+static void
+InitPrograms(void)
+{
+ Program = CreateProgram(VertFile, FragFile, Uniforms);
+}
+
+
+static void
+InitGL(void)
+{
+ 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();
+ 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);
+ InitGL();
+ glutMainLoop();
+ return 0;
+}
diff --git a/progs/glsl/multitex.frag b/progs/glsl/multitex.frag
new file mode 100644
index 0000000000..a2633ceba7
--- /dev/null
+++ b/progs/glsl/multitex.frag
@@ -0,0 +1,15 @@
+// Multi-texture fragment shader
+// Brian Paul
+
+// Composite second texture over first.
+// We're assuming the 2nd texture has a meaningful alpha channel.
+
+uniform sampler2D tex1;
+uniform sampler2D tex2;
+
+void main()
+{
+ vec4 t1 = texture2D(tex1, gl_TexCoord[0].xy);
+ vec4 t2 = texture2D(tex2, gl_TexCoord[1].xy);
+ gl_FragColor = mix(t1, t2, t2.w);
+}
diff --git a/progs/glsl/multitex.vert b/progs/glsl/multitex.vert
new file mode 100644
index 0000000000..5518ca1ddd
--- /dev/null
+++ b/progs/glsl/multitex.vert
@@ -0,0 +1,10 @@
+// Multi-texture vertex shader
+// Brian Paul
+
+
+void main()
+{
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+ gl_TexCoord[1] = gl_MultiTexCoord1;
+ gl_Position = ftransform();
+}
diff --git a/progs/glsl/noise.c b/progs/glsl/noise.c
index a26a805944..9da71ac775 100644
--- a/progs/glsl/noise.c
+++ b/progs/glsl/noise.c
@@ -12,6 +12,7 @@
#include <GL/glut.h>
#include <GL/glext.h>
#include "extfuncs.h"
+#include "shaderutil.h"
static const char *VertShaderText =
@@ -34,18 +35,11 @@ static const char *FragShaderText =
"}\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 } }
+ { "Scale", 4, GL_FLOAT, { 0.5, 0.4, 0.0, 0}, -1 },
+ { "Bias", 4, GL_FLOAT, { 0.5, 0.3, 0.0, 0}, -1 },
+ { "Slice", 1, GL_FLOAT, { 0.5, 0, 0, 0}, -1 },
+ END_OF_UNIFORMS
};
/* program/shader objects */
@@ -175,94 +169,20 @@ SpecialKey(int key, int x, int y)
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);*/
- }
+ if (!ShadersSupported())
+ exit(1);
GetExtensionFuncs();
- vertShader = glCreateShader_func(GL_VERTEX_SHADER);
- LoadAndCompileShader(vertShader, VertShaderText);
-
- fragShader = glCreateShader_func(GL_FRAGMENT_SHADER);
- LoadAndCompileShader(fragShader, FragShaderText);
+ vertShader = CompileShaderText(GL_VERTEX_SHADER, VertShaderText);
+ fragShader = CompileShaderText(GL_FRAGMENT_SHADER, FragShaderText);
+ program = LinkShaders(vertShader, fragShader);
- 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();
- }
- }
+ InitUniforms(program, Uniforms);
assert(glGetError() == 0);
diff --git a/progs/glsl/pointcoord.c b/progs/glsl/pointcoord.c
new file mode 100644
index 0000000000..b240077c25
--- /dev/null
+++ b/progs/glsl/pointcoord.c
@@ -0,0 +1,205 @@
+/**
+ * Test GLSL 1.20 gl_PointCoord fragment program attribute.
+ * Brian Paul
+ * 11 Aug 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"
+#include "shaderutil.h"
+
+
+static GLint WinWidth = 300, WinHeight = 300;
+static char *FragProgFile = NULL;
+static char *VertProgFile = NULL;
+static GLuint fragShader;
+static GLuint vertShader;
+static GLuint program;
+static GLint win = 0;
+static GLint tex0;
+static GLenum Filter = GL_NEAREST;
+
+
+static void
+Redisplay(void)
+{
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* draw one point/sprite */
+ glPushMatrix();
+ glPointSize(60);
+ glBegin(GL_POINTS);
+ glVertex2f(WinWidth / 2.0f, WinHeight / 2.0f);
+ glEnd();
+ glPopMatrix();
+
+ glutSwapBuffers();
+}
+
+
+static void
+Reshape(int width, int height)
+{
+ glViewport(0, 0, width, height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, width, 0, height, -1, 1);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ WinWidth = width;
+ WinHeight = height;
+}
+
+
+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 27:
+ CleanUp();
+ exit(0);
+ break;
+ }
+ glutPostRedisplay();
+}
+
+
+
+static void
+MakeTexture(void)
+{
+#define SZ 16
+ GLubyte image[SZ][SZ][4];
+ GLuint i, j;
+
+ for (i = 0; i < SZ; i++) {
+ for (j = 0; j < SZ; j++) {
+ if ((i + j) & 1) {
+ image[i][j][0] = 0;
+ image[i][j][1] = 0;
+ image[i][j][2] = 0;
+ image[i][j][3] = 255;
+ }
+ else {
+ image[i][j][0] = j * 255 / (SZ-1);
+ image[i][j][1] = i * 255 / (SZ-1);
+ image[i][j][2] = 0;
+ image[i][j][3] = 255;
+ }
+ }
+ }
+
+ glActiveTexture(GL_TEXTURE0); /* unit 0 */
+ glBindTexture(GL_TEXTURE_2D, 42);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SZ, SZ, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, image);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filter);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Filter);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+#undef SZ
+}
+
+
+static void
+Init(void)
+{
+ static const char *fragShaderText =
+ "#version 120 \n"
+ "uniform sampler2D tex0; \n"
+ "void main() { \n"
+ " gl_FragColor = texture2D(tex0, gl_PointCoord.xy, 0.0); \n"
+ "}\n";
+ static const char *vertShaderText =
+ "void main() {\n"
+ " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
+ "}\n";
+
+ if (!ShadersSupported())
+ exit(1);
+
+ GetExtensionFuncs();
+
+ vertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText);
+ fragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText);
+ program = LinkShaders(vertShader, fragShader);
+
+ glUseProgram_func(program);
+
+ tex0 = glGetUniformLocation_func(program, "tex0");
+ printf("Uniforms: tex0: %d\n", tex0);
+
+ glUniform1i_func(tex0, 0); /* tex unit 0 */
+
+ /*assert(glGetError() == 0);*/
+
+ glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
+
+ printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
+
+ assert(glIsProgram_func(program));
+ assert(glIsShader_func(fragShader));
+ assert(glIsShader_func(vertShader));
+
+ MakeTexture();
+
+ glEnable(GL_POINT_SPRITE);
+
+ 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(WinWidth, WinHeight);
+ glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
+ win = glutCreateWindow(argv[0]);
+ glutReshapeFunc(Reshape);
+ glutKeyboardFunc(Key);
+ glutDisplayFunc(Redisplay);
+ ParseOptions(argc, argv);
+ Init();
+ glutMainLoop();
+ return 0;
+}
diff --git a/progs/glsl/points.c b/progs/glsl/points.c
new file mode 100644
index 0000000000..392dc4db85
--- /dev/null
+++ b/progs/glsl/points.c
@@ -0,0 +1,260 @@
+/**
+ * Implement smooth (AA) points with shaders.
+ * A simple variation could be used for sprite points.
+ * Brian Paul
+ * 29 July 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"
+#include "shaderutil.h"
+
+
+static GLuint FragShader;
+static GLuint VertShader;
+static GLuint Program;
+
+static GLint Win = 0;
+static GLint WinWidth = 500, WinHeight = 200;
+static GLfloat Xpos = 0.0f, Ypos = 0.0f;
+static GLint uViewportInv;
+static GLboolean Smooth = GL_TRUE, Blend = GL_TRUE;
+
+
+/**
+ * Issue vertices for a "shader point".
+ * The position is duplicated, only texcoords (or other vertex attrib) change.
+ * The vertex program will compute the "real" quad corners.
+ */
+static void
+PointVertex3f(GLfloat x, GLfloat y, GLfloat z)
+{
+ glTexCoord2f(-1, -1);
+ glVertex3f(x, y, z);
+
+ glTexCoord2f( 1, -1);
+ glVertex3f(x, y, z);
+
+ glTexCoord2f( 1, 1);
+ glVertex3f(x, y, z);
+
+ glTexCoord2f(-1, 1);
+ glVertex3f(x, y, z);
+}
+
+
+static void
+DrawPoints(GLboolean shaderPoints)
+{
+ int i;
+ for (i = 0; i < 9; i++) {
+ GLfloat x = i - 4, y = 0, z = 0;
+ /* note: can't call glPointSize inside Begin/End :( */
+ glPointSize( 2 + i * 5 );
+ if (shaderPoints) {
+ glBegin(GL_QUADS);
+ PointVertex3f(x, y, z);
+ glEnd();
+ }
+ else {
+ glBegin(GL_POINTS);
+ glVertex3f(x, y, z);
+ glEnd();
+ }
+ }
+}
+
+
+/**
+ * Top row of points rendered convetionally,
+ * bottom row rendered with shaders.
+ */
+static void
+Redisplay(void)
+{
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ if (Smooth)
+ glEnable(GL_POINT_SMOOTH);
+ else
+ glDisable(GL_POINT_SMOOTH);
+
+ if (Blend)
+ glEnable(GL_BLEND);
+ else
+ glDisable(GL_BLEND);
+
+ glPushMatrix();
+ glTranslatef(Xpos, Ypos, 0);
+
+ /*
+ * regular points
+ */
+ glPushMatrix();
+ glTranslatef(0, 1.2, 0);
+ glUseProgram_func(0);
+ DrawPoints(GL_FALSE);
+ glPopMatrix();
+
+ /*
+ * shader points
+ */
+ glPushMatrix();
+ glTranslatef(0, -1.2, 0);
+ glUseProgram_func(Program);
+ if (uViewportInv != -1) {
+ glUniform2f_func(uViewportInv, 1.0 / WinWidth, 1.0 / WinHeight);
+ }
+ DrawPoints(GL_TRUE);
+ glPopMatrix();
+
+ glPopMatrix();
+
+ glutSwapBuffers();
+}
+
+
+static void
+Reshape(int width, int height)
+{
+ WinWidth = width;
+ WinHeight = height;
+ glViewport(0, 0, width, height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-1.0, 1.0, -1.0, 1.0, 4.0, 30.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(0.0f, 0.0f, -20.0f);
+}
+
+
+static void
+Key(unsigned char key, int x, int y)
+{
+ (void) x;
+ (void) y;
+
+ switch(key) {
+ case 'b':
+ Blend = !Blend;
+ break;
+ case 's':
+ Smooth = !Smooth;
+ break;
+ case 27:
+ glDeleteShader_func(FragShader);
+ glDeleteShader_func(VertShader);
+ glDeleteProgram_func(Program);
+ glutDestroyWindow(Win);
+ exit(0);
+ }
+ glutPostRedisplay();
+}
+
+
+static void
+SpecialKey(int key, int x, int y)
+{
+ const GLfloat step = 1/100.0;
+ switch(key) {
+ case GLUT_KEY_UP:
+ Ypos += step;
+ break;
+ case GLUT_KEY_DOWN:
+ Ypos -= step;
+ break;
+ case GLUT_KEY_LEFT:
+ Xpos -= step;
+ break;
+ case GLUT_KEY_RIGHT:
+ Xpos += step;
+ break;
+ }
+ glutPostRedisplay();
+}
+
+
+static void
+Init(void)
+{
+ /* Fragment shader: compute distance of fragment from center of point
+ * (we're using texcoords but another varying could be used).
+ * if dist > 1, discard (coverage==0)
+ * if dist < k, coverage = 1
+ * else, coverage = func(dist)
+ * Note: length() uses sqrt() and may be expensive. The distance could
+ * be squared instead (with adjustments to the threshold (k) test)
+ */
+ static const char *fragShaderText =
+ "void main() {\n"
+ " float cover; \n"
+ " float k = 2.0 / gl_Point.size; \n"
+ " float d = length(gl_TexCoord[0].xy); \n"
+ " if (d >= 1.0) \n"
+ " discard; \n"
+ " if (d < 1.0 - k) \n"
+ " cover = 1.0; \n"
+ " else \n"
+ " cover = (1.0 - d) * 0.5 * gl_Point.size; \n"
+ " gl_FragColor.rgb = gl_Color.rgb; \n"
+ " gl_FragColor.a = cover; \n"
+ "}\n";
+ /* Vertex shader: compute new vertex position based on incoming vertex pos,
+ * texcoords, point size, and inverse viewport scale factor.
+ * Note: should compute point size attenuation here too.
+ */
+ static const char *vertShaderText =
+ "uniform vec2 viewportInv; \n"
+ "void main() {\n"
+ " vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
+ " gl_Position.xy = pos.xy + gl_MultiTexCoord0.xy * viewportInv \n"
+ " * gl_Point.size * pos.w; \n"
+ " gl_Position.zw = pos.zw; \n"
+ " gl_TexCoord[0] = gl_MultiTexCoord0; \n"
+ " gl_FrontColor = gl_Color; \n"
+ "}\n";
+
+ if (!ShadersSupported())
+ exit(1);
+
+ GetExtensionFuncs();
+
+ VertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText);
+ FragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText);
+ Program = LinkShaders(VertShader, FragShader);
+
+ glUseProgram_func(Program);
+
+ uViewportInv = glGetUniformLocation_func(Program, "viewportInv");
+
+ glUseProgram_func(0);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ glutInit(&argc, argv);
+ glutInitWindowSize(WinWidth, WinHeight);
+ 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
index 402be38bf7..402be38bf7 100644
--- a/progs/glsl/reflect.vert.txt
+++ b/progs/glsl/reflect.vert
diff --git a/progs/glsl/shadowtex.frag.txt b/progs/glsl/shadowtex.frag
index a6a80da47f..a6a80da47f 100644
--- a/progs/glsl/shadowtex.frag.txt
+++ b/progs/glsl/shadowtex.frag
diff --git a/progs/glsl/simple.vert.txt b/progs/glsl/simple.vert
index a0abe0dc0b..a0abe0dc0b 100644
--- a/progs/glsl/simple.vert.txt
+++ b/progs/glsl/simple.vert
diff --git a/progs/glsl/texdemo1.c b/progs/glsl/texdemo1.c
index 3ceae14b96..96ddca1f32 100644
--- a/progs/glsl/texdemo1.c
+++ b/progs/glsl/texdemo1.c
@@ -31,14 +31,15 @@
#include "GL/glut.h"
#include "readtex.h"
#include "extfuncs.h"
+#include "shaderutil.h"
static const char *Demo = "texdemo1";
-static const char *ReflectVertFile = "reflect.vert.txt";
-static const char *CubeFragFile = "cubemap.frag.txt";
+static const char *ReflectVertFile = "reflect.vert";
+static const char *CubeFragFile = "cubemap.frag";
-static const char *SimpleVertFile = "simple.vert.txt";
-static const char *SimpleTexFragFile = "shadowtex.frag.txt";
+static const char *SimpleVertFile = "simple.vert";
+static const char *SimpleTexFragFile = "shadowtex.frag";
static const char *GroundImage = "../images/tile.rgb";
@@ -51,39 +52,20 @@ static GLboolean Anim = GL_TRUE;
static int win = 0;
-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 } }
+ { "cubeTex", 1, GL_INT, { 0, 0, 0, 0 }, -1 },
+ { "lightPos", 3, GL_FLOAT, { 10, 10, 20, 0 }, -1 },
+ END_OF_UNIFORMS
};
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 } }
+ { "tex2d", 1, GL_INT, { 1, 0, 0, 0 }, -1 },
+ { "lightPos", 3, GL_FLOAT, { 10, 10, 20, 0 }, -1 },
+ END_OF_UNIFORMS
};
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();
@@ -388,132 +370,19 @@ InitTextures(GLboolean useImageFiles)
}
-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);
- }
+ GLuint fragShader, vertShader, program;
- if (fragProgFile) {
- fragShader = glCreateShader_func(GL_FRAGMENT_SHADER);
- ReadShader(fragShader, fragProgFile);
- glAttachShader_func(program, fragShader);
- }
-
- glLinkProgram_func(program);
- CheckLink(program);
+ vertShader = CompileShaderFile(GL_VERTEX_SHADER, vertProgFile);
+ fragShader = CompileShaderFile(GL_FRAGMENT_SHADER, fragProgFile);
+ program = LinkShaders(vertShader, fragShader);
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__);
+ InitUniforms(program, uniforms);
return program;
}
diff --git a/progs/glsl/toyball.c b/progs/glsl/toyball.c
index cef52c04a6..2daaedd6df 100644
--- a/progs/glsl/toyball.c
+++ b/progs/glsl/toyball.c
@@ -13,10 +13,11 @@
#include <GL/glut.h>
#include <GL/glext.h>
#include "extfuncs.h"
+#include "shaderutil.h"
-static char *FragProgFile = "CH11-toyball.frag.txt";
-static char *VertProgFile = "CH11-toyball.vert.txt";
+static char *FragProgFile = "CH11-toyball.frag";
+static char *VertProgFile = "CH11-toyball.vert";
/* program/shader objects */
static GLuint fragShader;
@@ -24,30 +25,23 @@ 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 } }
+ { "LightDir", 4, GL_FLOAT, { 0.57737, 0.57735, 0.57735, 0.0 }, -1 },
+ { "HVector", 4, GL_FLOAT, { 0.32506, 0.32506, 0.88808, 0.0 }, -1 },
+ { "BallCenter", 4, GL_FLOAT, { 0.0, 0.0, 0.0, 1.0 }, -1 },
+ { "SpecularColor", 4, GL_FLOAT, { 0.4, 0.4, 0.4, 60.0 }, -1 },
+ { "Red", 4, GL_FLOAT, { 0.6, 0.0, 0.0, 1.0 }, -1 },
+ { "Blue", 4, GL_FLOAT, { 0.0, 0.3, 0.6, 1.0 }, -1 },
+ { "Yellow", 4, GL_FLOAT, { 0.6, 0.5, 0.0, 1.0 }, -1 },
+ { "HalfSpace0", 4, GL_FLOAT, { 1.0, 0.0, 0.0, 0.2 }, -1 },
+ { "HalfSpace1", 4, GL_FLOAT, { 0.309016994, 0.951056516, 0.0, 0.2 }, -1 },
+ { "HalfSpace2", 4, GL_FLOAT, { -0.809016994, 0.587785252, 0.0, 0.2 }, -1 },
+ { "HalfSpace3", 4, GL_FLOAT, { -0.809016994, -0.587785252, 0.0, 0.2 }, -1 },
+ { "HalfSpace4", 4, GL_FLOAT, { 0.309116994, -0.951056516, 0.0, 0.2 }, -1 },
+ { "InOrOutInit", 1, GL_FLOAT, { -3.0, 0, 0, 0 }, -1 },
+ { "StripeWidth", 1, GL_FLOAT, { 0.3, 0, 0, 0 }, -1 },
+ { "FWidth", 1, GL_FLOAT, { 0.005, 0, 0, 0 }, -1 },
+ END_OF_UNIFORMS
};
static GLint win = 0;
@@ -172,127 +166,20 @@ SpecialKey(int key, int x, int y)
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));
+ if (!ShadersSupported())
+ exit(1);
GetExtensionFuncs();
- vertShader = glCreateShader_func(GL_VERTEX_SHADER);
- ReadShader(vertShader, VertProgFile);
-
- fragShader = glCreateShader_func(GL_FRAGMENT_SHADER);
- ReadShader(fragShader, FragProgFile);
+ vertShader = CompileShaderFile(GL_VERTEX_SHADER, VertProgFile);
+ fragShader = CompileShaderFile(GL_FRAGMENT_SHADER, FragProgFile);
+ program = LinkShaders(vertShader, fragShader);
- 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();
- }
- }
+ InitUniforms(program, Uniforms);
assert(glGetError() == 0);
diff --git a/progs/glsl/trirast.c b/progs/glsl/trirast.c
new file mode 100644
index 0000000000..89df64fc71
--- /dev/null
+++ b/progs/glsl/trirast.c
@@ -0,0 +1,259 @@
+/**
+ * Demonstration of doing triangle rasterization with a fragment program.
+ * Basic idea:
+ * 1. Draw screen-aligned quad / bounding box around the triangle verts.
+ * 2. For each pixel in the quad, determine if pixel is inside/outside
+ * the triangle edges.
+ *
+ * Brian Paul
+ * 1 Aug 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"
+#include "shaderutil.h"
+
+
+static GLint WinWidth = 300, WinHeight = 300;
+static char *FragProgFile = NULL;
+static char *VertProgFile = NULL;
+static GLuint fragShader;
+static GLuint vertShader;
+static GLuint program;
+static GLint win = 0;
+static GLboolean anim = GL_TRUE;
+static GLfloat Zrot = 0.0f;
+static GLint uv0, uv1, uv2;
+
+
+static const GLfloat TriVerts[3][2] = {
+ { 50, 50 },
+ { 250, 50 },
+ { 150, 250 }
+};
+
+
+static void
+RotateVerts(GLfloat a,
+ GLuint n, const GLfloat vertsIn[][2], GLfloat vertsOut[][2])
+{
+ GLuint i;
+ GLfloat cx = WinWidth / 2, cy = WinHeight / 2;
+ for (i = 0; i < n; i++) {
+ float x = vertsIn[i][0] - cx;
+ float y = vertsIn[i][1] - cy;
+
+ vertsOut[i][0] = x * cos(a) + y * sin(a) + cx;
+ vertsOut[i][1] = -x * sin(a) + y * cos(a) + cy;
+ }
+}
+
+static void
+ComputeBounds(GLuint n, GLfloat vertsIn[][2],
+ GLfloat *xmin, GLfloat *ymin,
+ GLfloat *xmax, GLfloat *ymax)
+{
+ GLuint i;
+ *xmin = *xmax = vertsIn[0][0];
+ *ymin = *ymax = vertsIn[0][1];
+ for (i = 1; i < n; i++) {
+ if (vertsIn[i][0] < *xmin)
+ *xmin = vertsIn[i][0];
+ else if (vertsIn[i][0] > *xmax)
+ *xmax = vertsIn[i][0];
+ if (vertsIn[i][1] < *ymin)
+ *ymin = vertsIn[i][1];
+ else if (vertsIn[i][1] > *ymax)
+ *ymax = vertsIn[i][1];
+ }
+}
+
+
+static void
+Redisplay(void)
+{
+ GLfloat v[3][2], xmin, ymin, xmax, ymax;
+
+ RotateVerts(Zrot, 3, TriVerts, v);
+ ComputeBounds(3, v, &xmin, &ymin, &xmax, &ymax);
+
+ glUniform2fv_func(uv0, 1, v[0]);
+ glUniform2fv_func(uv1, 1, v[1]);
+ glUniform2fv_func(uv2, 1, v[2]);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glPushMatrix();
+ glBegin(GL_POLYGON);
+ glVertex2f(xmin, ymin);
+ glVertex2f(xmax, ymin);
+ glVertex2f(xmax, ymax);
+ glVertex2f(xmin, ymax);
+ glEnd();
+ glPopMatrix();
+
+ glutSwapBuffers();
+}
+
+
+static void
+Idle(void)
+{
+ if (anim) {
+ Zrot = glutGet(GLUT_ELAPSED_TIME) * 0.0005;
+ glutPostRedisplay();
+ }
+ else
+ abort();
+}
+
+
+static void
+Reshape(int width, int height)
+{
+ glViewport(0, 0, width, height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, width, 0, height, -1, 1);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+}
+
+
+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 ' ':
+ case 'a':
+ anim = !anim;
+ if (anim)
+ glutIdleFunc(Idle);
+ else
+ glutIdleFunc(NULL);
+ break;
+ case 'z':
+ Zrot = 0;
+ break;
+ case 's':
+ Zrot += 0.05;
+ break;
+ case 27:
+ CleanUp();
+ exit(0);
+ break;
+ }
+ glutPostRedisplay();
+}
+
+
+static void
+Init(void)
+{
+ static const char *fragShaderText =
+ "uniform vec2 v0, v1, v2; \n"
+ "float crs(const vec2 u, const vec2 v) \n"
+ "{ \n"
+ " return u.x * v.y - u.y * v.x; \n"
+ "} \n"
+ "\n"
+ "void main() {\n"
+ " vec2 p = gl_FragCoord.xy; \n"
+ " if (crs(v1 - v0, p - v0) >= 0 && \n"
+ " crs(v2 - v1, p - v1) >= 0 && \n"
+ " crs(v0 - v2, p - v2) >= 0) \n"
+ " gl_FragColor = vec4(1.0); \n"
+ " else \n"
+ " gl_FragColor = vec4(0.5); \n"
+ "}\n";
+ static const char *vertShaderText =
+ "void main() {\n"
+ " gl_Position = ftransform(); \n"
+ "}\n";
+
+ if (!ShadersSupported())
+ exit(1);
+
+ GetExtensionFuncs();
+
+ vertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText);
+ fragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText);
+ program = LinkShaders(vertShader, fragShader);
+
+ glUseProgram_func(program);
+
+ uv0 = glGetUniformLocation_func(program, "v0");
+ uv1 = glGetUniformLocation_func(program, "v1");
+ uv2 = glGetUniformLocation_func(program, "v2");
+ printf("Uniforms: %d %d %d\n", uv0, uv1, uv2);
+
+ /*assert(glGetError() == 0);*/
+
+ glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
+ glEnable(GL_DEPTH_TEST);
+
+ 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(WinWidth, WinHeight);
+ glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
+ win = glutCreateWindow(argv[0]);
+ glutReshapeFunc(Reshape);
+ glutKeyboardFunc(Key);
+ glutDisplayFunc(Redisplay);
+ if (anim)
+ glutIdleFunc(Idle);
+ ParseOptions(argc, argv);
+ Init();
+ glutMainLoop();
+ return 0;
+}
diff --git a/progs/glsl/twoside.c b/progs/glsl/twoside.c
new file mode 100644
index 0000000000..672a00491e
--- /dev/null
+++ b/progs/glsl/twoside.c
@@ -0,0 +1,294 @@
+/**
+ * Test two-sided lighting with shaders.
+ * Both GL_VERTEX_PROGRAM_TWO_SIDE and gl_FrontFacing can be tested
+ * (see keys below).
+ *
+ * Brian Paul
+ * 18 Dec 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"
+#include "shaderutil.h"
+
+
+static GLint WinWidth = 300, WinHeight = 300;
+static char *FragProgFile = NULL;
+static char *VertProgFile = NULL;
+static GLuint fragShader;
+static GLuint vertShader;
+static GLuint program;
+static GLint win = 0;
+static GLboolean anim = 0*GL_TRUE;
+static GLboolean DetermineInFragProg = GL_TRUE;
+static GLfloat Xrot = 30.0f;
+static GLint u_fragface;
+static GLenum FrontWinding = GL_CCW;
+static int prevTime = 0;
+
+
+static const GLfloat Red[4] = {1, 0, 0, 0};
+static const GLfloat Green[4] = {0, 1, 0, 0};
+
+
+static void
+Redisplay(void)
+{
+ int i;
+ float radius = 2;
+
+ glFrontFace(FrontWinding);
+
+ if (DetermineInFragProg) {
+ glUniform1i_func(u_fragface, 1);
+ glDisable(GL_VERTEX_PROGRAM_TWO_SIDE);
+ }
+ else {
+ glUniform1i_func(u_fragface, 0);
+ glEnable(GL_VERTEX_PROGRAM_TWO_SIDE);
+ }
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
+ glPushMatrix();
+ glRotatef(Xrot, 1, 0, 0);
+
+ /* Draw a tristrip ring */
+ glBegin(GL_TRIANGLE_STRIP);
+ glColor4fv(Red);
+ glSecondaryColor3fv_func(Green);
+ for (i = 0; i < 20; i++) {
+ float a = i / 19.0 * M_PI * 2.0;
+ float x = radius * cos(a);
+ float y = radius * sin(a);
+ glVertex3f(x, -1, y);
+ glVertex3f(x, +1, y);
+ }
+ glEnd();
+
+ glPopMatrix();
+
+ glutSwapBuffers();
+}
+
+
+static void
+Idle(void)
+{
+ int curTime = glutGet(GLUT_ELAPSED_TIME);
+ int dt = curTime - prevTime;
+
+ if (prevTime == 0) {
+ prevTime = curTime;
+ return;
+ }
+ prevTime = curTime;
+
+ Xrot += dt * 0.1;
+ glutPostRedisplay();
+}
+
+
+static void
+Reshape(int width, int height)
+{
+ float ar = (float) width / height;
+ glViewport(0, 0, width, height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-ar, ar, -1, 1, 3, 25);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(0, 0, -10);
+}
+
+
+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 ' ':
+ case 'a':
+ anim = !anim;
+ if (anim) {
+ prevTime = glutGet(GLUT_ELAPSED_TIME);
+ glutIdleFunc(Idle);
+ }
+ else
+ glutIdleFunc(NULL);
+ break;
+ case 'f':
+ printf("Using frag shader gl_FrontFacing\n");
+ DetermineInFragProg = GL_TRUE;
+ break;
+ case 'v':
+ printf("Using vert shader Two-sided lighting\n");
+ DetermineInFragProg = GL_FALSE;
+ break;
+ case 'r':
+ /* reset */
+ Xrot = 30;
+ anim = 0;
+ glutIdleFunc(NULL);
+ break;
+ case 's':
+ Xrot += 5;
+ break;
+ case 'S':
+ Xrot -= 5;
+ break;
+ case 'w':
+ if (FrontWinding == GL_CCW) {
+ FrontWinding = GL_CW;
+ printf("FrontFace = GL_CW\n");
+ }
+ else {
+ FrontWinding = GL_CCW;
+ printf("FrontFace = GL_CCW\n");
+ }
+ break;
+ case 27:
+ CleanUp();
+ exit(0);
+ break;
+ }
+ glutPostRedisplay();
+}
+
+
+static void
+Init(void)
+{
+ static const char *fragShaderText =
+ "uniform bool fragface; \n"
+ "void main() { \n"
+#if 0
+ " if (!fragface || gl_FrontFacing) { \n"
+ " gl_FragColor = gl_Color; \n"
+ " } \n"
+ " else { \n"
+ " gl_FragColor = 0.8 * gl_SecondaryColor; \n"
+ " } \n"
+#else
+ " bool f = gl_FrontFacing; \n"
+ " if (f) { \n"
+ " gl_FragColor = vec4(1.0, 0.0, 0.0, 0.0); \n"
+ " } \n"
+ " else { \n"
+ " gl_FragColor = vec4(0.0, 1.0, 0.0, 0.0); \n"
+ " } \n"
+ " //float g = float(gl_FrontFacing) * 0.5 + 0.5; \n"
+ " //gl_FragColor = vec4(g); \n"
+#endif
+ "} \n";
+ static const char *vertShaderText =
+ "uniform bool fragface; \n"
+ "void main() { \n"
+ " gl_FrontColor = gl_Color; \n"
+ " if (fragface) { \n"
+ " // front/back chosen in frag prog \n"
+ " gl_FrontSecondaryColor = gl_SecondaryColor; \n"
+ " } \n"
+ " else { \n"
+ " // front/back chosen in prim setup \n"
+ " gl_BackColor = gl_SecondaryColor; \n"
+ " } \n"
+ " gl_Position = ftransform(); \n"
+ "} \n";
+
+ if (!ShadersSupported())
+ exit(1);
+
+ GetExtensionFuncs();
+
+ vertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText);
+ fragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText);
+ program = LinkShaders(vertShader, fragShader);
+
+ glUseProgram_func(program);
+
+ u_fragface = glGetUniformLocation_func(program, "fragface");
+ printf("Uniforms: %d\n", u_fragface);
+
+ /*assert(glGetError() == 0);*/
+
+ glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
+
+ printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
+
+ assert(glIsProgram_func(program));
+ assert(glIsShader_func(fragShader));
+ assert(glIsShader_func(vertShader));
+
+ glEnable(GL_DEPTH_TEST);
+}
+
+
+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];
+ }
+ }
+}
+
+
+static void
+Usage(void)
+{
+ printf("Keys:\n");
+ printf(" f - do front/back determination in fragment shader\n");
+ printf(" v - do front/back determination in vertex shader\n");
+ printf(" r - reset, show front\n");
+ printf(" a - toggle animation\n");
+ printf(" s - step rotation\n");
+ printf(" w - toggle CW, CCW front-face winding\n");
+ printf("NOTE: red = front face, green = back face.\n");
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ glutInit(&argc, argv);
+ glutInitWindowPosition( 0, 0);
+ glutInitWindowSize(WinWidth, WinHeight);
+ glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
+ win = glutCreateWindow(argv[0]);
+ glutReshapeFunc(Reshape);
+ glutKeyboardFunc(Key);
+ glutDisplayFunc(Redisplay);
+ if (anim)
+ glutIdleFunc(Idle);
+ ParseOptions(argc, argv);
+ Init();
+ Usage();
+ glutMainLoop();
+ return 0;
+}