blob: 6a1fa3d3bf065531bc4dc730bc8a3d73a75be752 [file] [log] [blame]
Zack Rusine842b5e2007-10-25 07:19:02 -04001
2#include <assert.h>
3#include <string.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <math.h>
Keith Whitwellce0ac902009-03-09 17:10:12 +00007
8#include <GL/glew.h>
Zack Rusine842b5e2007-10-25 07:19:02 -04009#include <GL/glut.h>
10
11static const char *filename = NULL;
12static GLuint nr_steps = 4;
Keith Whitwell97f59532009-05-14 15:57:27 +010013static GLuint prim = GL_TRIANGLES;
14static GLfloat psz = 1.0;
15static GLboolean pointsmooth = 0;
16static GLboolean program_point_size = 0;
Zack Rusine842b5e2007-10-25 07:19:02 -040017
18static GLuint fragShader;
19static GLuint vertShader;
20static GLuint program;
21
22static void usage( char *name )
23{
24 fprintf( stderr, "usage: %s [ options ] shader_filename\n", name );
25 fprintf( stderr, "\n" );
26 fprintf( stderr, "options:\n" );
27 fprintf( stderr, " -f flat shaded\n" );
28 fprintf( stderr, " -nNr subdivision steps\n" );
29}
30
31
32static void load_and_compile_shader(GLuint shader, const char *text)
33{
34 GLint stat;
35
36 glShaderSource(shader, 1, (const GLchar **) &text, NULL);
37
38 glCompileShader(shader);
39
40 glGetShaderiv(shader, GL_COMPILE_STATUS, &stat);
41 if (!stat) {
42 GLchar log[1000];
43 GLsizei len;
44 glGetShaderInfoLog(shader, 1000, &len, log);
45 fprintf(stderr, "vp-tris: problem compiling shader:\n%s\n", log);
46 exit(1);
47 }
48}
49
50static void read_shader(GLuint shader, const char *filename)
51{
52 const int max = 100*1000;
53 int n;
54 char *buffer = (char*) malloc(max);
55 FILE *f = fopen(filename, "r");
56 if (!f) {
57 fprintf(stderr, "vp-tris: Unable to open shader file %s\n", filename);
58 exit(1);
59 }
60
61 n = fread(buffer, 1, max, f);
Zack Rusin1d26e9c2007-10-25 07:52:59 -040062 printf("vp-tris: read %d bytes from shader file %s\n", n, filename);
Zack Rusine842b5e2007-10-25 07:19:02 -040063 if (n > 0) {
64 buffer[n] = 0;
65 load_and_compile_shader(shader, buffer);
66 }
67
68 fclose(f);
69 free(buffer);
70}
71
72static void check_link(GLuint prog)
73{
74 GLint stat;
75 glGetProgramiv(prog, GL_LINK_STATUS, &stat);
76 if (!stat) {
77 GLchar log[1000];
78 GLsizei len;
79 glGetProgramInfoLog(prog, 1000, &len, log);
80 fprintf(stderr, "Linker error:\n%s\n", log);
81 }
82}
83
Zack Rusinf49dd472008-06-12 00:04:30 -040084static void setup_uniforms()
85{
86 {
Vinson Leed642edd2009-12-05 01:11:26 -080087 GLint loc1f = glGetUniformLocationARB(program, "Offset1f");
88 GLint loc2f = glGetUniformLocationARB(program, "Offset2f");
89 GLint loc4f = glGetUniformLocationARB(program, "Offset4f");
Zack Rusinf49dd472008-06-12 00:04:30 -040090 GLfloat vecKer[] =
91 { 1.0, 0.0, 0.0, 1.0,
92 0.0, 1.0, 0.0, 1.0,
93 1.0, 0.0, 0.0, 1.0,
94 0.0, 0.0, 0.0, 1.0
95 };
96 if (loc1f >= 0)
97 glUniform1fv(loc1f, 16, vecKer);
98
99 if (loc2f >= 0)
100 glUniform2fv(loc2f, 8, vecKer);
101
102 if (loc4f >= 0)
103 glUniform4fv(loc4f, 4, vecKer);
104
105 }
106
Keith Whitwellce0ac902009-03-09 17:10:12 +0000107 {
Vinson Leed642edd2009-12-05 01:11:26 -0800108 GLint loc1f = glGetUniformLocationARB(program, "KernelValue1f");
109 GLint loc2f = glGetUniformLocationARB(program, "KernelValue2f");
110 GLint loc4f = glGetUniformLocationARB(program, "KernelValue4f");
Keith Whitwellce0ac902009-03-09 17:10:12 +0000111 GLfloat vecKer[] =
112 { 1.0, 0.0, 0.0, 0.25,
113 0.0, 1.0, 0.0, 0.25,
114 0.0, 0.0, 1.0, 0.25,
115 0.0, 0.0, 0.0, 0.25,
116 0.5, 0.0, 0.0, 0.35,
117 0.0, 0.5, 0.0, 0.35,
118 0.0, 0.0, 0.5, 0.35,
119 0.0, 0.0, 0.0, 0.35
120 };
121 if (loc1f >= 0)
122 glUniform1fv(loc1f, 16, vecKer);
Zack Rusinf49dd472008-06-12 00:04:30 -0400123
Keith Whitwellce0ac902009-03-09 17:10:12 +0000124 if (loc2f >= 0)
125 glUniform2fv(loc2f, 8, vecKer);
Zack Rusinf49dd472008-06-12 00:04:30 -0400126
Keith Whitwellce0ac902009-03-09 17:10:12 +0000127 if (loc4f >= 0)
128 glUniform4fv(loc4f, 4, vecKer);
129 }
Zack Rusinf49dd472008-06-12 00:04:30 -0400130}
131
Zack Rusine842b5e2007-10-25 07:19:02 -0400132static void prepare_shaders()
133{
134 static const char *fragShaderText =
135 "void main() {\n"
136 " gl_FragColor = gl_Color;\n"
137 "}\n";
138 static const char *vertShaderText =
139 "void main() {\n"
140 " gl_FrontColor = gl_Color;\n"
141 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
142 "}\n";
143 fragShader = glCreateShader(GL_FRAGMENT_SHADER);
144 load_and_compile_shader(fragShader, fragShaderText);
145
146
147 vertShader = glCreateShader(GL_VERTEX_SHADER);
148 if (filename)
149 read_shader(vertShader, filename);
150 else
151 load_and_compile_shader(vertShader, vertShaderText);
152
153 program = glCreateProgram();
154 glAttachShader(program, fragShader);
155 glAttachShader(program, vertShader);
156 glLinkProgram(program);
157 check_link(program);
158 glUseProgram(program);
Zack Rusinf49dd472008-06-12 00:04:30 -0400159
160 setup_uniforms();
Zack Rusine842b5e2007-10-25 07:19:02 -0400161}
162
163static void args(int argc, char *argv[])
164{
165 GLint i;
166
167 for (i = 1; i < argc; i++) {
168 if (strncmp(argv[i], "-n", 2) == 0) {
169 nr_steps = atoi((argv[i]) + 2);
170 }
171 else if (strcmp(argv[i], "-f") == 0) {
172 glShadeModel(GL_FLAT);
173 }
174 else if (i == argc - 1) {
175 filename = argv[i];
176 }
177 else {
178 usage(argv[0]);
179 exit(1);
180 }
181 }
182
183 if (!filename) {
184 usage(argv[0]);
185 exit(1);
186 }
187}
188
189
190
191
192union vert {
193 struct {
194 GLfloat color[3];
195 GLfloat pos[3];
196 } v;
197 GLfloat f[6];
198};
199
200static void make_midpoint( union vert *out,
201 const union vert *v0,
202 const union vert *v1)
203{
204 int i;
205 for (i = 0; i < 6; i++)
206 out->f[i] = v0->f[i] + .5 * (v1->f[i] - v0->f[i]);
207}
208
209static void subdiv( union vert *v0,
210 union vert *v1,
211 union vert *v2,
212 GLuint depth )
213{
214 if (depth == 0) {
215 glColor3fv(v0->v.color);
216 glVertex3fv(v0->v.pos);
217 glColor3fv(v1->v.color);
218 glVertex3fv(v1->v.pos);
219 glColor3fv(v2->v.color);
220 glVertex3fv(v2->v.pos);
221 }
222 else {
223 union vert m[3];
224
225 make_midpoint(&m[0], v0, v1);
226 make_midpoint(&m[1], v1, v2);
227 make_midpoint(&m[2], v2, v0);
228
229 subdiv(&m[0], &m[2], v0, depth-1);
230 subdiv(&m[1], &m[0], v1, depth-1);
231 subdiv(&m[2], &m[1], v2, depth-1);
232 subdiv(&m[0], &m[1], &m[2], depth-1);
233 }
234}
235
Keith Whitwell97f59532009-05-14 15:57:27 +0100236static void enable( GLenum value, GLboolean flag )
237{
238 if (flag)
239 glEnable(value);
240 else
241 glDisable(value);
242}
243
Zack Rusine842b5e2007-10-25 07:19:02 -0400244/** Assignment */
245#define ASSIGN_3V( V, V0, V1, V2 ) \
246do { \
247 V[0] = V0; \
248 V[1] = V1; \
249 V[2] = V2; \
250} while(0)
251
252static void Display( void )
253{
254 glClearColor(0.3, 0.3, 0.3, 1);
255 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
Keith Whitwell97f59532009-05-14 15:57:27 +0100256 glPointSize(psz);
Zack Rusine842b5e2007-10-25 07:19:02 -0400257
258 glUseProgram(program);
Keith Whitwell97f59532009-05-14 15:57:27 +0100259 enable( GL_POINT_SMOOTH, pointsmooth );
260 enable( GL_VERTEX_PROGRAM_POINT_SIZE_ARB, program_point_size );
Zack Rusine842b5e2007-10-25 07:19:02 -0400261
Keith Whitwell97f59532009-05-14 15:57:27 +0100262 glBegin(prim);
Zack Rusine842b5e2007-10-25 07:19:02 -0400263
264
265 {
266 union vert v[3];
267
268 ASSIGN_3V(v[0].v.color, 0,0,1);
269 ASSIGN_3V(v[0].v.pos, 0.9, -0.9, 0.0);
270 ASSIGN_3V(v[1].v.color, 1,0,0);
271 ASSIGN_3V(v[1].v.pos, 0.9, 0.9, 0.0);
272 ASSIGN_3V(v[2].v.color, 0,1,0);
273 ASSIGN_3V(v[2].v.pos, -0.9, 0, 0.0);
274
275 subdiv(&v[0], &v[1], &v[2], nr_steps);
276 }
277
278 glEnd();
279
280
281 glFlush();
282}
283
284
285static void Reshape( int width, int height )
286{
287 glViewport( 0, 0, width, height );
288 glMatrixMode( GL_PROJECTION );
289 glLoadIdentity();
290 glOrtho(-1.0, 1.0, -1.0, 1.0, -0.5, 1000.0);
291 glMatrixMode( GL_MODELVIEW );
292 glLoadIdentity();
293 /*glTranslatef( 0.0, 0.0, -15.0 );*/
294}
295
296
297static void CleanUp(void)
298{
299 glDeleteShader(fragShader);
300 glDeleteShader(vertShader);
301 glDeleteProgram(program);
302}
303
304static void Key( unsigned char key, int x, int y )
305{
306 (void) x;
307 (void) y;
308 switch (key) {
Keith Whitwell97f59532009-05-14 15:57:27 +0100309 case 'p':
310 prim = GL_POINTS;
311 break;
312 case 't':
313 prim = GL_TRIANGLES;
314 break;
315 case 's':
316 psz += .5;
317 break;
318 case 'S':
319 if (psz > .5)
320 psz -= .5;
321 break;
322 case 'm':
323 pointsmooth = !pointsmooth;
324 break;
325 case 'z':
326 program_point_size = !program_point_size;
327 break;
328 case '+':
329 nr_steps++;
330 break;
331 case '-':
332 if (nr_steps)
333 nr_steps--;
334 break;
335 case ' ':
336 psz = 1.0;
337 prim = GL_TRIANGLES;
338 nr_steps = 4;
339 break;
340 case 27:
341 CleanUp();
342 exit(0);
343 break;
Zack Rusine842b5e2007-10-25 07:19:02 -0400344 }
345 glutPostRedisplay();
346}
347
348int main( int argc, char *argv[] )
349{
350 glutInit( &argc, argv );
351 glutInitWindowPosition( 0, 0 );
352 glutInitWindowSize( 250, 250 );
353 glutInitDisplayMode( GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH );
Keith Whitwell97f59532009-05-14 15:57:27 +0100354 glutCreateWindow(argv[argc-1]);
Keith Whitwellce0ac902009-03-09 17:10:12 +0000355 glewInit();
Zack Rusine842b5e2007-10-25 07:19:02 -0400356 glutReshapeFunc( Reshape );
357 glutKeyboardFunc( Key );
358 glutDisplayFunc( Display );
359 args( argc, argv );
360 prepare_shaders();
361 glutMainLoop();
362 return 0;
363}