summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZack Rusin <zack@kde.org>2010-07-09 22:52:06 -0400
committerZack Rusin <zack@kde.org>2010-07-09 22:52:27 -0400
commit9e0209567ced09e4541fd7b2e5ee84d442d0b711 (patch)
tree06ae4197c5b1a5a20d975ecddd0aac559049aa53
parent7834dc7261091f9c94eb3a9563afc9fe1173a22c (diff)
Add a geometry shader example
-rw-r--r--configure.ac1
-rw-r--r--src/Makefile.am1
-rw-r--r--src/gs/Makefile.am15
-rw-r--r--src/gs/SConscript13
-rw-r--r--src/gs/basic.glsl16
-rw-r--r--src/gs/gs-tri.c292
6 files changed, 338 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index 55fe9418..c04f81ea 100644
--- a/configure.ac
+++ b/configure.ac
@@ -224,6 +224,7 @@ AC_OUTPUT([
src/fp/Makefile
src/fpglsl/Makefile
src/glsl/Makefile
+ src/gs/Makefile
src/images/Makefile
src/objviewer/Makefile
src/osdemos/Makefile
diff --git a/src/Makefile.am b/src/Makefile.am
index d45b95ae..a9f04522 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -29,6 +29,7 @@ SUBDIRS = \
fp \
fpglsl \
glsl \
+ gs \
images \
objviewer \
osdemos \
diff --git a/src/gs/Makefile.am b/src/gs/Makefile.am
new file mode 100644
index 00000000..f5151f26
--- /dev/null
+++ b/src/gs/Makefile.am
@@ -0,0 +1,15 @@
+AM_CFLAGS = \
+ $(DEMO_CFLAGS) \
+ $(GLUT_CFLAGS) \
+ -I$(top_srcdir)/src/util
+AM_LDFLAGS = \
+ $(DEMO_LIBS) \
+ $(GLUT_LIBS)
+
+if HAVE_GLUT
+noinst_PROGRAMS = \
+ gs-tri
+endif
+
+EXTRA_DIST = \
+ basic.glsl
diff --git a/src/gs/SConscript b/src/gs/SConscript
new file mode 100644
index 00000000..321e619e
--- /dev/null
+++ b/src/gs/SConscript
@@ -0,0 +1,13 @@
+Import('env')
+
+if not env['GLUT']:
+ Return()
+
+env = env.Clone()
+
+env.Prepend(LIBS = ['$GLUT_LIB'])
+
+env.Program(
+ target = 'gs-tri',
+ source = ['gs-tri.c'],
+ )
diff --git a/src/gs/basic.glsl b/src/gs/basic.glsl
new file mode 100644
index 00000000..256a1e6f
--- /dev/null
+++ b/src/gs/basic.glsl
@@ -0,0 +1,16 @@
+#version 120
+#extension GL_ARB_geometry_shader4 : enable
+
+const int KernelSize = 9;
+
+void main()
+{
+ for(int i = 0; i < gl_VerticesIn; ++i)
+ {
+ gl_FrontColor = gl_FrontColorIn[i];
+ gl_BackColor = gl_BackColorIn[i];
+ gl_Position = gl_PositionIn[i];
+ EmitVertex();
+ }
+ EndPrimitive();
+}
diff --git a/src/gs/gs-tri.c b/src/gs/gs-tri.c
new file mode 100644
index 00000000..c33454c1
--- /dev/null
+++ b/src/gs/gs-tri.c
@@ -0,0 +1,292 @@
+
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#define GL_GLEXT_PROTOTYPES
+#include <GL/glut.h>
+#include <GL/glext.h>
+
+static const char *filename = NULL;
+static GLuint nr_steps = 0;
+
+static GLuint fragShader;
+static GLuint vertShader;
+static GLuint geoShader;
+static GLuint program;
+
+static void usage( char *name )
+{
+ fprintf(stderr, "usage: %s [ options ] shader_filename\n", name);
+ fprintf(stderr, "\n" );
+ fprintf(stderr, "options:\n" );
+ fprintf(stderr, " -f flat shaded\n" );
+ fprintf(stderr, " -nNr subdivision steps\n" );
+}
+
+
+static void load_and_compile_shader(GLuint shader, const char *text)
+{
+ GLint stat;
+
+ glShaderSource(shader, 1, (const GLchar **) &text, NULL);
+ glCompileShader(shader);
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &stat);
+ if (!stat) {
+ GLchar log[1000];
+ GLsizei len;
+ glGetShaderInfoLog(shader, 1000, &len, log);
+ fprintf(stderr, "gp: problem compiling shader:\n%s\n", log);
+ exit(1);
+ }
+}
+
+static void read_shader(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, "gp: Unable to open shader file %s\n", filename);
+ exit(1);
+ }
+
+ n = fread(buffer, 1, max, f);
+ printf("gp: read %d bytes from shader file %s\n", n, filename);
+ if (n > 0) {
+ buffer[n] = 0;
+ load_and_compile_shader(shader, buffer);
+ }
+
+ fclose(f);
+ free(buffer);
+}
+
+static void check_link(GLuint prog)
+{
+ GLint stat;
+ glGetProgramiv(prog, GL_LINK_STATUS, &stat);
+ if (!stat) {
+ GLchar log[1000];
+ GLsizei len;
+ glGetProgramInfoLog(prog, 1000, &len, log);
+ fprintf(stderr, "Linker error:\n%s\n", log);
+ }
+}
+
+static void prepare_shaders(void)
+{
+ static const char *fragShaderText =
+ "void main() {\n"
+ " gl_FragColor = gl_Color;\n"
+ "}\n";
+ static const char *vertShaderText =
+ "void main() {\n"
+ " gl_FrontColor = gl_Color;\n"
+ " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
+ "}\n";
+ static const char *geoShaderText =
+ "#version 120\n"
+ "#extension GL_ARB_geometry_shader4 : enable\n"
+ "void main()\n"
+ "{\n"
+ " for(int i = 0; i < gl_VerticesIn; ++i)\n"
+ " {\n"
+ " gl_FrontColor = gl_FrontColorIn[i];\n"
+ " gl_Position = gl_PositionIn[i];\n"
+ " EmitVertex();\n"
+ " }\n"
+ "}\n";
+ fragShader = glCreateShader(GL_FRAGMENT_SHADER);
+ load_and_compile_shader(fragShader, fragShaderText);
+
+ vertShader = glCreateShader(GL_VERTEX_SHADER);
+ load_and_compile_shader(vertShader, vertShaderText);
+
+ geoShader = glCreateShader(GL_GEOMETRY_SHADER_ARB);
+ if (filename)
+ read_shader(geoShader, filename);
+ else
+ load_and_compile_shader(geoShader,
+ geoShaderText);
+
+ program = glCreateProgram();
+ glAttachShader(program, vertShader);
+ glAttachShader(program, geoShader);
+ glAttachShader(program, fragShader);
+
+ glProgramParameteriARB(program, GL_GEOMETRY_INPUT_TYPE_ARB, GL_TRIANGLES);
+ glProgramParameteriARB(program, GL_GEOMETRY_OUTPUT_TYPE_ARB,
+ GL_TRIANGLE_STRIP);
+
+ {
+ int temp;
+ glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB,&temp);
+ glProgramParameteriARB(program,GL_GEOMETRY_VERTICES_OUT_ARB,temp);
+ }
+
+ glLinkProgram(program);
+ check_link(program);
+ glUseProgram(program);
+}
+
+static void args(int argc, char *argv[])
+{
+ GLint i;
+
+ for (i = 1; i < argc; i++) {
+ if (strncmp(argv[i], "-n", 2) == 0) {
+ nr_steps = atoi((argv[i]) + 2);
+ }
+ else if (strcmp(argv[i], "-f") == 0) {
+ glShadeModel(GL_FLAT);
+ }
+ else if (i == argc - 1) {
+ filename = argv[i];
+ }
+ else {
+ usage(argv[0]);
+ exit(1);
+ }
+ }
+
+ if (!filename) {
+ usage(argv[0]);
+ exit(1);
+ }
+}
+
+
+
+
+union vert {
+ struct {
+ GLfloat color[3];
+ GLfloat pos[3];
+ } v;
+ GLfloat f[6];
+};
+
+static void make_midpoint( union vert *out,
+ const union vert *v0,
+ const union vert *v1)
+{
+ int i;
+ for (i = 0; i < 6; i++)
+ out->f[i] = v0->f[i] + .5 * (v1->f[i] - v0->f[i]);
+}
+
+static void subdiv( union vert *v0,
+ union vert *v1,
+ union vert *v2,
+ GLuint depth )
+{
+ if (depth == 0) {
+ glColor3fv(v0->v.color);
+ glVertex3fv(v0->v.pos);
+ glColor3fv(v1->v.color);
+ glVertex3fv(v1->v.pos);
+ glColor3fv(v2->v.color);
+ glVertex3fv(v2->v.pos);
+ }
+ else {
+ union vert m[3];
+
+ make_midpoint(&m[0], v0, v1);
+ make_midpoint(&m[1], v1, v2);
+ make_midpoint(&m[2], v2, v0);
+
+ subdiv(&m[0], &m[2], v0, depth-1);
+ subdiv(&m[1], &m[0], v1, depth-1);
+ subdiv(&m[2], &m[1], v2, depth-1);
+ subdiv(&m[0], &m[1], &m[2], depth-1);
+ }
+}
+
+/** Assignment */
+#define ASSIGN_3V( V, V0, V1, V2 ) \
+do { \
+ V[0] = V0; \
+ V[1] = V1; \
+ V[2] = V2; \
+} while(0)
+
+static void Display( void )
+{
+ glClearColor(0.3, 0.3, 0.3, 1);
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
+ glUseProgram(program);
+
+ glBegin(GL_TRIANGLES);
+
+
+ {
+ union vert v[3];
+
+ ASSIGN_3V(v[0].v.color, 0,0,1);
+ ASSIGN_3V(v[0].v.pos, 0.9, -0.9, 0.0);
+ ASSIGN_3V(v[1].v.color, 1,0,0);
+ ASSIGN_3V(v[1].v.pos, 0.9, 0.9, 0.0);
+ ASSIGN_3V(v[2].v.color, 0,1,0);
+ ASSIGN_3V(v[2].v.pos, -0.9, 0, 0.0);
+
+ subdiv(&v[0], &v[1], &v[2], nr_steps);
+ }
+
+ glEnd();
+
+
+ glFlush();
+}
+
+
+static void Reshape( int width, int height )
+{
+ glViewport( 0, 0, width, height );
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ glOrtho(-1.0, 1.0, -1.0, 1.0, -0.5, 1000.0);
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+ /*glTranslatef( 0.0, 0.0, -15.0 );*/
+}
+
+
+static void CleanUp(void)
+{
+ glDeleteShader(fragShader);
+ glDeleteShader(vertShader);
+ glDeleteProgram(program);
+}
+
+static void Key( unsigned char key, int x, int y )
+{
+ (void) x;
+ (void) y;
+ switch (key) {
+ case 27:
+ CleanUp();
+ exit(0);
+ break;
+ }
+ glutPostRedisplay();
+}
+
+int main( int argc, char *argv[] )
+{
+ glutInit( &argc, argv );
+ glutInitWindowPosition( 0, 0 );
+ glutInitWindowSize( 250, 250 );
+ glutInitDisplayMode( GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH );
+ glutCreateWindow(argv[0]);
+ glutReshapeFunc( Reshape );
+ glutKeyboardFunc( Key );
+ glutDisplayFunc( Display );
+ args( argc, argv );
+ prepare_shaders();
+ glutMainLoop();
+ return 0;
+}