From aa71b8869b914157f3d44ec4eff65b517b595a90 Mon Sep 17 00:00:00 2001 From: Brian Date: Sun, 29 Jul 2007 18:04:23 -0600 Subject: Added shader points and shader bitmap demos --- progs/glsl/Makefile | 6 + progs/glsl/bitmap.c | 368 ++++++++++++++++++++++++++++++++++++++++++++++++++++ progs/glsl/points.c | 301 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 675 insertions(+) create mode 100644 progs/glsl/bitmap.c create mode 100644 progs/glsl/points.c diff --git a/progs/glsl/Makefile b/progs/glsl/Makefile index 37fa312c30..9065a6185a 100644 --- a/progs/glsl/Makefile +++ b/progs/glsl/Makefile @@ -8,11 +8,13 @@ INCDIR = $(TOP)/include LIB_DEP = $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) $(TOP)/$(LIB_DIR)/$(GLU_LIB_NAME) $(TOP)/$(LIB_DIR)/$(GLUT_LIB_NAME) PROGS = \ + bitmap \ brick \ bump \ deriv \ mandelbrot \ noise \ + points \ toyball \ texdemo1 @@ -48,12 +50,16 @@ readtex.h: $(TOP)/progs/util/readtex.h readtex.o: readtex.c readtex.h $(CC) -c -I$(INCDIR) $(CFLAGS) readtex.c +bitmap.c: extfuncs.h + brick.c: extfuncs.h bump.c: extfuncs.h mandelbrot.c: extfuncs.h +points.c: extfuncs.h + toyball.c: extfuncs.h texdemo1: texdemo1.o readtex.o diff --git a/progs/glsl/bitmap.c b/progs/glsl/bitmap.c new file mode 100644 index 0000000000..4b62686cbf --- /dev/null +++ b/progs/glsl/bitmap.c @@ -0,0 +1,368 @@ +/** + * Implement glRasterPos + glBitmap with textures + shaders. + * Brian Paul + * 14 May 2007 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "extfuncs.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 +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); + } +} + + +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) +{ + /* 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"; + 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); + exit(1); + } + printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER)); + + GetExtensionFuncs(); + + FragShader = glCreateShader_func(GL_FRAGMENT_SHADER); + LoadAndCompileShader(FragShader, fragShaderText); + + VertShader = glCreateShader_func(GL_VERTEX_SHADER); + LoadAndCompileShader(VertShader, vertShaderText); + + Program = glCreateProgram_func(); + glAttachShader_func(Program, FragShader); + glAttachShader_func(Program, VertShader); + glLinkProgram_func(Program); + CheckLink(Program); + 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/points.c b/progs/glsl/points.c new file mode 100644 index 0000000000..2dc0670c60 --- /dev/null +++ b/progs/glsl/points.c @@ -0,0 +1,301 @@ +/** + * Implement smooth (AA) points with shaders. + * A simple variation could be used for sprite points. + * Brian Paul + * 29 July 2007 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "extfuncs.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 +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); + } +} + + +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) +{ + /* Fragment shader: compute distance of fragment from center of point, + * if dist > 1, discard + * if dist < k, coverage = 1 + * else, coverage = func(dist) + */ + 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 and inverse viewport scale factor. + */ + static const char *vertShaderText = + "uniform vec2 viewportInv; \n" + "void main() {\n" + " vec4 p = gl_ModelViewProjectionMatrix * gl_Vertex;\n" + " vec2 scale2 = viewportInv * gl_Point.size; \n" + " gl_Position.xy = p.xy + gl_MultiTexCoord0.xy * scale2 * p.w; \n" + " gl_Position.zw = p.zw; \n" + " gl_TexCoord[0] = gl_MultiTexCoord0; \n" + " gl_FrontColor = gl_Color; \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); + exit(1); + } + printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER)); + + GetExtensionFuncs(); + + FragShader = glCreateShader_func(GL_FRAGMENT_SHADER); + LoadAndCompileShader(FragShader, fragShaderText); + + VertShader = glCreateShader_func(GL_VERTEX_SHADER); + LoadAndCompileShader(VertShader, vertShaderText); + + Program = glCreateProgram_func(); + glAttachShader_func(Program, FragShader); + glAttachShader_func(Program, VertShader); + glLinkProgram_func(Program); + CheckLink(Program); + 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; +} + + -- cgit v1.2.3