1/* 2 * Simple example for testing basic features of 3 * geometry shaders 4 */ 5 6#include <assert.h> 7#include <string.h> 8#include <stdio.h> 9#include <stdlib.h> 10#include <math.h> 11#define GL_GLEXT_PROTOTYPES 12#include <GL/glew.h> 13#include "glut_wrap.h" 14#include "shaderutil.h" 15 16static const char *filename = "bezier.geom"; 17 18static GLuint fragShader; 19static GLuint vertShader; 20static GLuint geoShader; 21static GLuint program; 22 23#define QUIT 9999 24 25GLfloat vertices[][3] = 26 { { -0.9, -0.9, 0.0 }, 27 { -0.5, 0.9, 0.0 }, 28 { 0.5, 0.9, 0.0 }, 29 { 0.9, -0.9, 0.0 } }; 30 31GLfloat color[][4] = 32{ { 1, 1, 1, 1 }, 33 { 1, 1, 1, 1 }, 34 { 1, 1, 1, 1 }, 35 { 1, 1, 1, 1 } }; 36 37 38static struct uniform_info Uniforms[] = { 39 { "NumSubdivisions", 1, GL_INT, { 50, 0, 0, 0 }, -1 }, 40 END_OF_UNIFORMS 41}; 42 43static void usage( char *name ) 44{ 45 fprintf(stderr, "usage: %s\n", name); 46 fprintf(stderr, "\n" ); 47} 48 49 50static void load_and_compile_shader(GLuint shader, const char *text) 51{ 52 GLint stat; 53 54 glShaderSource(shader, 1, (const GLchar **) &text, NULL); 55 glCompileShader(shader); 56 glGetShaderiv(shader, GL_COMPILE_STATUS, &stat); 57 if (!stat) { 58 GLchar log[1000]; 59 GLsizei len; 60 glGetShaderInfoLog(shader, 1000, &len, log); 61 fprintf(stderr, "bezier: problem compiling shader:\n%s\n", log); 62 exit(1); 63 } 64} 65 66static void read_shader(GLuint shader, const char *filename) 67{ 68 const int max = 100*1000; 69 int n; 70 char *buffer = (char*) malloc(max); 71 FILE *f = fopen(filename, "r"); 72 if (!f) { 73 fprintf(stderr, "bezier: Unable to open shader file %s\n", filename); 74 exit(1); 75 } 76 77 n = fread(buffer, 1, max, f); 78 printf("bezier: read %d bytes from shader file %s\n", n, filename); 79 if (n > 0) { 80 buffer[n] = 0; 81 load_and_compile_shader(shader, buffer); 82 } 83 84 fclose(f); 85 free(buffer); 86} 87 88static void check_link(GLuint prog) 89{ 90 GLint stat; 91 glGetProgramiv(prog, GL_LINK_STATUS, &stat); 92 if (!stat) { 93 GLchar log[1000]; 94 GLsizei len; 95 glGetProgramInfoLog(prog, 1000, &len, log); 96 fprintf(stderr, "Linker error:\n%s\n", log); 97 } 98} 99 100static void menu_selected(int entry) 101{ 102 switch (entry) { 103 case QUIT: 104 exit(0); 105 break; 106 default: 107 Uniforms[0].value[0] = entry; 108 } 109 110 SetUniformValues(program, Uniforms); 111 glutPostRedisplay(); 112} 113 114 115static void menu_init(void) 116{ 117 glutCreateMenu(menu_selected); 118 119 glutAddMenuEntry("1 Subdivision", 1); 120 glutAddMenuEntry("2 Subdivisions", 2); 121 glutAddMenuEntry("3 Subdivisions", 3); 122 glutAddMenuEntry("4 Subdivisions", 4); 123 glutAddMenuEntry("5 Subdivisions", 5); 124 glutAddMenuEntry("6 Subdivisions", 6); 125 glutAddMenuEntry("7 Subdivisions", 7); 126 glutAddMenuEntry("10 Subdivisions", 10); 127 glutAddMenuEntry("50 Subdivisions", 50); 128 glutAddMenuEntry("100 Subdivisions", 100); 129 glutAddMenuEntry("500 Subdivisions", 500); 130 131 glutAddMenuEntry("Quit", QUIT); 132 133 glutAttachMenu(GLUT_RIGHT_BUTTON); 134} 135 136static void init(void) 137{ 138 static const char *fragShaderText = 139 "void main() {\n" 140 " gl_FragColor = gl_Color;\n" 141 "}\n"; 142 static const char *vertShaderText = 143 "void main() {\n" 144 " gl_FrontColor = gl_Color;\n" 145 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" 146 "}\n"; 147 static const char *geoShaderText = 148 "#version 120\n" 149 "#extension GL_ARB_geometry_shader4 : enable\n" 150 "void main()\n" 151 "{\n" 152 " for(int i = 0; i < gl_VerticesIn; ++i)\n" 153 " {\n" 154 " gl_FrontColor = gl_FrontColorIn[i];\n" 155 " gl_Position = gl_PositionIn[i];\n" 156 " EmitVertex();\n" 157 " }\n" 158 "}\n"; 159 160 161 if (!ShadersSupported()) 162 exit(1); 163 164 if (!glutExtensionSupported("GL_ARB_geometry_shader4")) { 165 printf("This demo requires GL_ARB_geometry_shader4\n"); 166 exit(1); 167 } 168 169 menu_init(); 170 171 fragShader = glCreateShader(GL_FRAGMENT_SHADER); 172 load_and_compile_shader(fragShader, fragShaderText); 173 174 vertShader = glCreateShader(GL_VERTEX_SHADER); 175 load_and_compile_shader(vertShader, vertShaderText); 176 177 geoShader = glCreateShader(GL_GEOMETRY_SHADER_ARB); 178 if (filename) 179 read_shader(geoShader, filename); 180 else 181 load_and_compile_shader(geoShader, 182 geoShaderText); 183 184 program = glCreateProgram(); 185 glAttachShader(program, vertShader); 186 glAttachShader(program, geoShader); 187 glAttachShader(program, fragShader); 188 189 glProgramParameteriARB(program, GL_GEOMETRY_INPUT_TYPE_ARB, 190 GL_LINES_ADJACENCY_ARB); 191 glProgramParameteriARB(program, GL_GEOMETRY_OUTPUT_TYPE_ARB, 192 GL_LINE_STRIP); 193 194 { 195 int temp; 196 glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB,&temp); 197 glProgramParameteriARB(program,GL_GEOMETRY_VERTICES_OUT_ARB,temp); 198 } 199 200 glLinkProgram(program); 201 check_link(program); 202 glUseProgram(program); 203 204 SetUniformValues(program, Uniforms); 205 PrintUniforms(Uniforms); 206 207 assert(glGetError() == 0); 208 209 glEnableClientState( GL_VERTEX_ARRAY ); 210 glEnableClientState( GL_COLOR_ARRAY ); 211 212 glVertexPointer( 3, GL_FLOAT, sizeof(vertices[0]), vertices ); 213 glColorPointer( 4, GL_FLOAT, sizeof(color[0]), color ); 214} 215 216static void args(int argc, char *argv[]) 217{ 218 if (argc != 1) { 219 usage(argv[0]); 220 exit(1); 221 } 222} 223 224static void Display( void ) 225{ 226 glClearColor(0, 0, 0, 1); 227 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 228 229 glUseProgram(program); 230 231 glEnable(GL_VERTEX_PROGRAM_ARB); 232 233 glDrawArrays(GL_LINES_ADJACENCY_ARB, 0, 4); 234 235 glFlush(); 236} 237 238 239static void Reshape( int width, int height ) 240{ 241 glViewport( 0, 0, width, height ); 242 glMatrixMode( GL_PROJECTION ); 243 glLoadIdentity(); 244 glOrtho(-1.0, 1.0, -1.0, 1.0, -0.5, 1000.0); 245 glMatrixMode( GL_MODELVIEW ); 246 glLoadIdentity(); 247 /*glTranslatef( 0.0, 0.0, -15.0 );*/ 248} 249 250 251static void CleanUp(void) 252{ 253 glDeleteShader(fragShader); 254 glDeleteShader(vertShader); 255 glDeleteProgram(program); 256} 257 258static void Key( unsigned char key, int x, int y ) 259{ 260 (void) x; 261 (void) y; 262 switch (key) { 263 case 27: 264 CleanUp(); 265 exit(0); 266 break; 267 } 268 glutPostRedisplay(); 269} 270 271int main( int argc, char *argv[] ) 272{ 273 glutInit( &argc, argv ); 274 glutInitWindowPosition( 0, 0 ); 275 glutInitWindowSize( 250, 250 ); 276 glutInitDisplayMode( GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH ); 277 glutCreateWindow(argv[0]); 278 glewInit(); 279 glutReshapeFunc( Reshape ); 280 glutKeyboardFunc( Key ); 281 glutDisplayFunc( Display ); 282 args(argc, argv); 283 init(); 284 glutMainLoop(); 285 return 0; 286} 287