132001f49Smrg 232001f49Smrg#include <assert.h> 332001f49Smrg#include <string.h> 432001f49Smrg#include <stdio.h> 532001f49Smrg#include <stdlib.h> 632001f49Smrg#include <math.h> 732001f49Smrg 832001f49Smrg#include <GL/glew.h> 932001f49Smrg#include "glut_wrap.h" 1032001f49Smrg 1132001f49Smrgstatic const char *filename = NULL; 1232001f49Smrgstatic GLuint nr_steps = 4; 1332001f49Smrgstatic GLuint prim = GL_TRIANGLES; 1432001f49Smrgstatic GLfloat psz = 1.0; 1532001f49Smrgstatic GLboolean pointsmooth = 0; 1632001f49Smrgstatic GLboolean program_point_size = 0; 1732001f49Smrg 1832001f49Smrgstatic GLuint fragShader; 1932001f49Smrgstatic GLuint vertShader; 2032001f49Smrgstatic GLuint program; 2132001f49Smrg 2232001f49Smrgstatic void usage( char *name ) 2332001f49Smrg{ 2432001f49Smrg fprintf( stderr, "usage: %s [ options ] shader_filename\n", name ); 2532001f49Smrg fprintf( stderr, "\n" ); 2632001f49Smrg fprintf( stderr, "options:\n" ); 2732001f49Smrg fprintf( stderr, " -f flat shaded\n" ); 2832001f49Smrg fprintf( stderr, " -nNr subdivision steps\n" ); 2932001f49Smrg} 3032001f49Smrg 3132001f49Smrg 3232001f49Smrgstatic void load_and_compile_shader(GLuint shader, const char *text) 3332001f49Smrg{ 3432001f49Smrg GLint stat; 3532001f49Smrg 3632001f49Smrg glShaderSource(shader, 1, (const GLchar **) &text, NULL); 3732001f49Smrg 3832001f49Smrg glCompileShader(shader); 3932001f49Smrg 4032001f49Smrg glGetShaderiv(shader, GL_COMPILE_STATUS, &stat); 4132001f49Smrg if (!stat) { 4232001f49Smrg GLchar log[1000]; 4332001f49Smrg GLsizei len; 4432001f49Smrg glGetShaderInfoLog(shader, 1000, &len, log); 4532001f49Smrg fprintf(stderr, "vp-tris: problem compiling shader:\n%s\n", log); 4632001f49Smrg exit(1); 4732001f49Smrg } 4832001f49Smrg} 4932001f49Smrg 5032001f49Smrgstatic void read_shader(GLuint shader, const char *filename) 5132001f49Smrg{ 5232001f49Smrg const int max = 100*1000; 5332001f49Smrg int n; 5432001f49Smrg char *buffer = (char*) malloc(max); 5532001f49Smrg FILE *f = fopen(filename, "r"); 5632001f49Smrg if (!f) { 5732001f49Smrg fprintf(stderr, "vp-tris: Unable to open shader file %s\n", filename); 5832001f49Smrg exit(1); 5932001f49Smrg } 6032001f49Smrg 6132001f49Smrg n = fread(buffer, 1, max, f); 6232001f49Smrg printf("vp-tris: read %d bytes from shader file %s\n", n, filename); 6332001f49Smrg if (n > 0) { 6432001f49Smrg buffer[n] = 0; 6532001f49Smrg load_and_compile_shader(shader, buffer); 6632001f49Smrg } 6732001f49Smrg 6832001f49Smrg fclose(f); 6932001f49Smrg free(buffer); 7032001f49Smrg} 7132001f49Smrg 7232001f49Smrgstatic void check_link(GLuint prog) 7332001f49Smrg{ 7432001f49Smrg GLint stat; 7532001f49Smrg glGetProgramiv(prog, GL_LINK_STATUS, &stat); 7632001f49Smrg if (!stat) { 7732001f49Smrg GLchar log[1000]; 7832001f49Smrg GLsizei len; 7932001f49Smrg glGetProgramInfoLog(prog, 1000, &len, log); 8032001f49Smrg fprintf(stderr, "Linker error:\n%s\n", log); 8132001f49Smrg } 8232001f49Smrg} 8332001f49Smrg 8432001f49Smrgstatic void setup_uniforms(void) 8532001f49Smrg{ 8632001f49Smrg { 8732001f49Smrg GLint loc1f = glGetUniformLocationARB(program, "Offset1f"); 8832001f49Smrg GLint loc2f = glGetUniformLocationARB(program, "Offset2f"); 8932001f49Smrg GLint loc4f = glGetUniformLocationARB(program, "Offset4f"); 9032001f49Smrg GLfloat vecKer[] = 9132001f49Smrg { 1.0, 0.0, 0.0, 1.0, 9232001f49Smrg 0.0, 1.0, 0.0, 1.0, 9332001f49Smrg 1.0, 0.0, 0.0, 1.0, 9432001f49Smrg 0.0, 0.0, 0.0, 1.0 9532001f49Smrg }; 9632001f49Smrg if (loc1f >= 0) 9732001f49Smrg glUniform1fv(loc1f, 16, vecKer); 9832001f49Smrg 9932001f49Smrg if (loc2f >= 0) 10032001f49Smrg glUniform2fv(loc2f, 8, vecKer); 10132001f49Smrg 10232001f49Smrg if (loc4f >= 0) 10332001f49Smrg glUniform4fv(loc4f, 4, vecKer); 10432001f49Smrg 10532001f49Smrg } 10632001f49Smrg 10732001f49Smrg { 10832001f49Smrg GLint loc1f = glGetUniformLocationARB(program, "KernelValue1f"); 10932001f49Smrg GLint loc2f = glGetUniformLocationARB(program, "KernelValue2f"); 11032001f49Smrg GLint loc4f = glGetUniformLocationARB(program, "KernelValue4f"); 11132001f49Smrg GLfloat vecKer[] = 11232001f49Smrg { 1.0, 0.0, 0.0, 0.25, 11332001f49Smrg 0.0, 1.0, 0.0, 0.25, 11432001f49Smrg 0.0, 0.0, 1.0, 0.25, 11532001f49Smrg 0.0, 0.0, 0.0, 0.25, 11632001f49Smrg 0.5, 0.0, 0.0, 0.35, 11732001f49Smrg 0.0, 0.5, 0.0, 0.35, 11832001f49Smrg 0.0, 0.0, 0.5, 0.35, 11932001f49Smrg 0.0, 0.0, 0.0, 0.35 12032001f49Smrg }; 12132001f49Smrg if (loc1f >= 0) 12232001f49Smrg glUniform1fv(loc1f, 16, vecKer); 12332001f49Smrg 12432001f49Smrg if (loc2f >= 0) 12532001f49Smrg glUniform2fv(loc2f, 8, vecKer); 12632001f49Smrg 12732001f49Smrg if (loc4f >= 0) 12832001f49Smrg glUniform4fv(loc4f, 4, vecKer); 12932001f49Smrg } 13032001f49Smrg} 13132001f49Smrg 13232001f49Smrgstatic void prepare_shaders(void) 13332001f49Smrg{ 13432001f49Smrg static const char *fragShaderText = 13532001f49Smrg "void main() {\n" 13632001f49Smrg " gl_FragColor = gl_Color;\n" 13732001f49Smrg "}\n"; 13832001f49Smrg static const char *vertShaderText = 13932001f49Smrg "void main() {\n" 14032001f49Smrg " gl_FrontColor = gl_Color;\n" 14132001f49Smrg " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" 14232001f49Smrg "}\n"; 14332001f49Smrg fragShader = glCreateShader(GL_FRAGMENT_SHADER); 14432001f49Smrg load_and_compile_shader(fragShader, fragShaderText); 14532001f49Smrg 14632001f49Smrg 14732001f49Smrg vertShader = glCreateShader(GL_VERTEX_SHADER); 14832001f49Smrg if (filename) 14932001f49Smrg read_shader(vertShader, filename); 15032001f49Smrg else 15132001f49Smrg load_and_compile_shader(vertShader, vertShaderText); 15232001f49Smrg 15332001f49Smrg program = glCreateProgram(); 15432001f49Smrg glAttachShader(program, fragShader); 15532001f49Smrg glAttachShader(program, vertShader); 15632001f49Smrg glLinkProgram(program); 15732001f49Smrg check_link(program); 15832001f49Smrg glUseProgram(program); 15932001f49Smrg 16032001f49Smrg setup_uniforms(); 16132001f49Smrg} 16232001f49Smrg 16332001f49Smrgstatic void args(int argc, char *argv[]) 16432001f49Smrg{ 16532001f49Smrg GLint i; 16632001f49Smrg 16732001f49Smrg for (i = 1; i < argc; i++) { 16832001f49Smrg if (strncmp(argv[i], "-n", 2) == 0) { 16932001f49Smrg nr_steps = atoi((argv[i]) + 2); 17032001f49Smrg } 17132001f49Smrg else if (strcmp(argv[i], "-f") == 0) { 17232001f49Smrg glShadeModel(GL_FLAT); 17332001f49Smrg } 17432001f49Smrg else if (i == argc - 1) { 17532001f49Smrg filename = argv[i]; 17632001f49Smrg } 17732001f49Smrg else { 17832001f49Smrg usage(argv[0]); 17932001f49Smrg exit(1); 18032001f49Smrg } 18132001f49Smrg } 18232001f49Smrg 18332001f49Smrg if (!filename) { 18432001f49Smrg usage(argv[0]); 18532001f49Smrg exit(1); 18632001f49Smrg } 18732001f49Smrg} 18832001f49Smrg 18932001f49Smrg 19032001f49Smrg 19132001f49Smrg 19232001f49Smrgunion vert { 19332001f49Smrg struct { 19432001f49Smrg GLfloat color[3]; 19532001f49Smrg GLfloat pos[3]; 19632001f49Smrg } v; 19732001f49Smrg GLfloat f[6]; 19832001f49Smrg}; 19932001f49Smrg 20032001f49Smrgstatic void make_midpoint( union vert *out, 20132001f49Smrg const union vert *v0, 20232001f49Smrg const union vert *v1) 20332001f49Smrg{ 20432001f49Smrg int i; 20532001f49Smrg for (i = 0; i < 6; i++) 20632001f49Smrg out->f[i] = v0->f[i] + .5 * (v1->f[i] - v0->f[i]); 20732001f49Smrg} 20832001f49Smrg 20932001f49Smrgstatic void subdiv( union vert *v0, 21032001f49Smrg union vert *v1, 21132001f49Smrg union vert *v2, 21232001f49Smrg GLuint depth ) 21332001f49Smrg{ 21432001f49Smrg if (depth == 0) { 21532001f49Smrg glColor3fv(v0->v.color); 21632001f49Smrg glVertex3fv(v0->v.pos); 21732001f49Smrg glColor3fv(v1->v.color); 21832001f49Smrg glVertex3fv(v1->v.pos); 21932001f49Smrg glColor3fv(v2->v.color); 22032001f49Smrg glVertex3fv(v2->v.pos); 22132001f49Smrg } 22232001f49Smrg else { 22332001f49Smrg union vert m[3]; 22432001f49Smrg 22532001f49Smrg make_midpoint(&m[0], v0, v1); 22632001f49Smrg make_midpoint(&m[1], v1, v2); 22732001f49Smrg make_midpoint(&m[2], v2, v0); 22832001f49Smrg 22932001f49Smrg subdiv(&m[0], &m[2], v0, depth-1); 23032001f49Smrg subdiv(&m[1], &m[0], v1, depth-1); 23132001f49Smrg subdiv(&m[2], &m[1], v2, depth-1); 23232001f49Smrg subdiv(&m[0], &m[1], &m[2], depth-1); 23332001f49Smrg } 23432001f49Smrg} 23532001f49Smrg 23632001f49Smrgstatic void enable( GLenum value, GLboolean flag ) 23732001f49Smrg{ 23832001f49Smrg if (flag) 23932001f49Smrg glEnable(value); 24032001f49Smrg else 24132001f49Smrg glDisable(value); 24232001f49Smrg} 24332001f49Smrg 24432001f49Smrg/** Assignment */ 24532001f49Smrg#define ASSIGN_3V( V, V0, V1, V2 ) \ 24632001f49Smrgdo { \ 24732001f49Smrg V[0] = V0; \ 24832001f49Smrg V[1] = V1; \ 24932001f49Smrg V[2] = V2; \ 25032001f49Smrg} while(0) 25132001f49Smrg 25232001f49Smrgstatic void Display( void ) 25332001f49Smrg{ 25432001f49Smrg glClearColor(0.3, 0.3, 0.3, 1); 25532001f49Smrg glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 25632001f49Smrg glPointSize(psz); 25732001f49Smrg 25832001f49Smrg glUseProgram(program); 25932001f49Smrg enable( GL_POINT_SMOOTH, pointsmooth ); 26032001f49Smrg enable( GL_VERTEX_PROGRAM_POINT_SIZE_ARB, program_point_size ); 26132001f49Smrg 26232001f49Smrg glBegin(prim); 26332001f49Smrg 26432001f49Smrg 26532001f49Smrg { 26632001f49Smrg union vert v[3]; 26732001f49Smrg 26832001f49Smrg ASSIGN_3V(v[0].v.color, 0,0,1); 26932001f49Smrg ASSIGN_3V(v[0].v.pos, 0.9, -0.9, 0.0); 27032001f49Smrg ASSIGN_3V(v[1].v.color, 1,0,0); 27132001f49Smrg ASSIGN_3V(v[1].v.pos, 0.9, 0.9, 0.0); 27232001f49Smrg ASSIGN_3V(v[2].v.color, 0,1,0); 27332001f49Smrg ASSIGN_3V(v[2].v.pos, -0.9, 0, 0.0); 27432001f49Smrg 27532001f49Smrg subdiv(&v[0], &v[1], &v[2], nr_steps); 27632001f49Smrg } 27732001f49Smrg 27832001f49Smrg glEnd(); 27932001f49Smrg 28032001f49Smrg 28132001f49Smrg glFlush(); 28232001f49Smrg} 28332001f49Smrg 28432001f49Smrg 28532001f49Smrgstatic void Reshape( int width, int height ) 28632001f49Smrg{ 28732001f49Smrg glViewport( 0, 0, width, height ); 28832001f49Smrg glMatrixMode( GL_PROJECTION ); 28932001f49Smrg glLoadIdentity(); 29032001f49Smrg glOrtho(-1.0, 1.0, -1.0, 1.0, -0.5, 1000.0); 29132001f49Smrg glMatrixMode( GL_MODELVIEW ); 29232001f49Smrg glLoadIdentity(); 29332001f49Smrg /*glTranslatef( 0.0, 0.0, -15.0 );*/ 29432001f49Smrg} 29532001f49Smrg 29632001f49Smrg 29732001f49Smrgstatic void CleanUp(void) 29832001f49Smrg{ 29932001f49Smrg glDeleteShader(fragShader); 30032001f49Smrg glDeleteShader(vertShader); 30132001f49Smrg glDeleteProgram(program); 30232001f49Smrg} 30332001f49Smrg 30432001f49Smrgstatic void Key( unsigned char key, int x, int y ) 30532001f49Smrg{ 30632001f49Smrg (void) x; 30732001f49Smrg (void) y; 30832001f49Smrg switch (key) { 30932001f49Smrg case 'p': 31032001f49Smrg prim = GL_POINTS; 31132001f49Smrg break; 31232001f49Smrg case 't': 31332001f49Smrg prim = GL_TRIANGLES; 31432001f49Smrg break; 31532001f49Smrg case 's': 31632001f49Smrg psz += .5; 31732001f49Smrg break; 31832001f49Smrg case 'S': 31932001f49Smrg if (psz > .5) 32032001f49Smrg psz -= .5; 32132001f49Smrg break; 32232001f49Smrg case 'm': 32332001f49Smrg pointsmooth = !pointsmooth; 32432001f49Smrg break; 32532001f49Smrg case 'z': 32632001f49Smrg program_point_size = !program_point_size; 32732001f49Smrg break; 32832001f49Smrg case '+': 32932001f49Smrg nr_steps++; 33032001f49Smrg break; 33132001f49Smrg case '-': 33232001f49Smrg if (nr_steps) 33332001f49Smrg nr_steps--; 33432001f49Smrg break; 33532001f49Smrg case ' ': 33632001f49Smrg psz = 1.0; 33732001f49Smrg prim = GL_TRIANGLES; 33832001f49Smrg nr_steps = 4; 33932001f49Smrg break; 34032001f49Smrg case 27: 34132001f49Smrg CleanUp(); 34232001f49Smrg exit(0); 34332001f49Smrg break; 34432001f49Smrg } 34532001f49Smrg glutPostRedisplay(); 34632001f49Smrg} 34732001f49Smrg 34832001f49Smrgint main( int argc, char *argv[] ) 34932001f49Smrg{ 35032001f49Smrg glutInit( &argc, argv ); 35132001f49Smrg glutInitWindowPosition( 0, 0 ); 35232001f49Smrg glutInitWindowSize( 250, 250 ); 35332001f49Smrg glutInitDisplayMode( GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH ); 35432001f49Smrg glutCreateWindow(argv[argc-1]); 35532001f49Smrg glewInit(); 35632001f49Smrg glutReshapeFunc( Reshape ); 35732001f49Smrg glutKeyboardFunc( Key ); 35832001f49Smrg glutDisplayFunc( Display ); 35932001f49Smrg args( argc, argv ); 36032001f49Smrg prepare_shaders(); 36132001f49Smrg glutMainLoop(); 36232001f49Smrg return 0; 36332001f49Smrg} 364