blob: 9ae410bf98436b84e61bada10fe2b49ff91ec977 [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;
13
14static GLuint fragShader;
15static GLuint vertShader;
16static GLuint program;
17
18static void usage( char *name )
19{
20 fprintf( stderr, "usage: %s [ options ] shader_filename\n", name );
21 fprintf( stderr, "\n" );
22 fprintf( stderr, "options:\n" );
23 fprintf( stderr, " -f flat shaded\n" );
24 fprintf( stderr, " -nNr subdivision steps\n" );
25}
26
27
28static void load_and_compile_shader(GLuint shader, const char *text)
29{
30 GLint stat;
31
32 glShaderSource(shader, 1, (const GLchar **) &text, NULL);
33
34 glCompileShader(shader);
35
36 glGetShaderiv(shader, GL_COMPILE_STATUS, &stat);
37 if (!stat) {
38 GLchar log[1000];
39 GLsizei len;
40 glGetShaderInfoLog(shader, 1000, &len, log);
41 fprintf(stderr, "vp-tris: problem compiling shader:\n%s\n", log);
42 exit(1);
43 }
44}
45
46static void read_shader(GLuint shader, const char *filename)
47{
48 const int max = 100*1000;
49 int n;
50 char *buffer = (char*) malloc(max);
51 FILE *f = fopen(filename, "r");
52 if (!f) {
53 fprintf(stderr, "vp-tris: Unable to open shader file %s\n", filename);
54 exit(1);
55 }
56
57 n = fread(buffer, 1, max, f);
Zack Rusin1d26e9c2007-10-25 07:52:59 -040058 printf("vp-tris: read %d bytes from shader file %s\n", n, filename);
Zack Rusine842b5e2007-10-25 07:19:02 -040059 if (n > 0) {
60 buffer[n] = 0;
61 load_and_compile_shader(shader, buffer);
62 }
63
64 fclose(f);
65 free(buffer);
66}
67
68static void check_link(GLuint prog)
69{
70 GLint stat;
71 glGetProgramiv(prog, GL_LINK_STATUS, &stat);
72 if (!stat) {
73 GLchar log[1000];
74 GLsizei len;
75 glGetProgramInfoLog(prog, 1000, &len, log);
76 fprintf(stderr, "Linker error:\n%s\n", log);
77 }
78}
79
Zack Rusinf49dd472008-06-12 00:04:30 -040080static void setup_uniforms()
81{
82 {
83 GLuint loc1f = glGetUniformLocationARB(program, "Offset1f");
84 GLuint loc2f = glGetUniformLocationARB(program, "Offset2f");
85 GLuint loc4f = glGetUniformLocationARB(program, "Offset4f");
86 GLfloat vecKer[] =
87 { 1.0, 0.0, 0.0, 1.0,
88 0.0, 1.0, 0.0, 1.0,
89 1.0, 0.0, 0.0, 1.0,
90 0.0, 0.0, 0.0, 1.0
91 };
92 if (loc1f >= 0)
93 glUniform1fv(loc1f, 16, vecKer);
94
95 if (loc2f >= 0)
96 glUniform2fv(loc2f, 8, vecKer);
97
98 if (loc4f >= 0)
99 glUniform4fv(loc4f, 4, vecKer);
100
101 }
102
Keith Whitwellce0ac902009-03-09 17:10:12 +0000103 {
104 GLuint loc1f = glGetUniformLocationARB(program, "KernelValue1f");
105 GLuint loc2f = glGetUniformLocationARB(program, "KernelValue2f");
106 GLuint loc4f = glGetUniformLocationARB(program, "KernelValue4f");
107 GLfloat vecKer[] =
108 { 1.0, 0.0, 0.0, 0.25,
109 0.0, 1.0, 0.0, 0.25,
110 0.0, 0.0, 1.0, 0.25,
111 0.0, 0.0, 0.0, 0.25,
112 0.5, 0.0, 0.0, 0.35,
113 0.0, 0.5, 0.0, 0.35,
114 0.0, 0.0, 0.5, 0.35,
115 0.0, 0.0, 0.0, 0.35
116 };
117 if (loc1f >= 0)
118 glUniform1fv(loc1f, 16, vecKer);
Zack Rusinf49dd472008-06-12 00:04:30 -0400119
Keith Whitwellce0ac902009-03-09 17:10:12 +0000120 if (loc2f >= 0)
121 glUniform2fv(loc2f, 8, vecKer);
Zack Rusinf49dd472008-06-12 00:04:30 -0400122
Keith Whitwellce0ac902009-03-09 17:10:12 +0000123 if (loc4f >= 0)
124 glUniform4fv(loc4f, 4, vecKer);
125 }
Zack Rusinf49dd472008-06-12 00:04:30 -0400126}
127
Zack Rusine842b5e2007-10-25 07:19:02 -0400128static void prepare_shaders()
129{
130 static const char *fragShaderText =
131 "void main() {\n"
132 " gl_FragColor = gl_Color;\n"
133 "}\n";
134 static const char *vertShaderText =
135 "void main() {\n"
136 " gl_FrontColor = gl_Color;\n"
137 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
138 "}\n";
139 fragShader = glCreateShader(GL_FRAGMENT_SHADER);
140 load_and_compile_shader(fragShader, fragShaderText);
141
142
143 vertShader = glCreateShader(GL_VERTEX_SHADER);
144 if (filename)
145 read_shader(vertShader, filename);
146 else
147 load_and_compile_shader(vertShader, vertShaderText);
148
149 program = glCreateProgram();
150 glAttachShader(program, fragShader);
151 glAttachShader(program, vertShader);
152 glLinkProgram(program);
153 check_link(program);
154 glUseProgram(program);
Zack Rusinf49dd472008-06-12 00:04:30 -0400155
156 setup_uniforms();
Zack Rusine842b5e2007-10-25 07:19:02 -0400157}
158
159static void args(int argc, char *argv[])
160{
161 GLint i;
162
163 for (i = 1; i < argc; i++) {
164 if (strncmp(argv[i], "-n", 2) == 0) {
165 nr_steps = atoi((argv[i]) + 2);
166 }
167 else if (strcmp(argv[i], "-f") == 0) {
168 glShadeModel(GL_FLAT);
169 }
170 else if (i == argc - 1) {
171 filename = argv[i];
172 }
173 else {
174 usage(argv[0]);
175 exit(1);
176 }
177 }
178
179 if (!filename) {
180 usage(argv[0]);
181 exit(1);
182 }
183}
184
185
186
187
188union vert {
189 struct {
190 GLfloat color[3];
191 GLfloat pos[3];
192 } v;
193 GLfloat f[6];
194};
195
196static void make_midpoint( union vert *out,
197 const union vert *v0,
198 const union vert *v1)
199{
200 int i;
201 for (i = 0; i < 6; i++)
202 out->f[i] = v0->f[i] + .5 * (v1->f[i] - v0->f[i]);
203}
204
205static void subdiv( union vert *v0,
206 union vert *v1,
207 union vert *v2,
208 GLuint depth )
209{
210 if (depth == 0) {
211 glColor3fv(v0->v.color);
212 glVertex3fv(v0->v.pos);
213 glColor3fv(v1->v.color);
214 glVertex3fv(v1->v.pos);
215 glColor3fv(v2->v.color);
216 glVertex3fv(v2->v.pos);
217 }
218 else {
219 union vert m[3];
220
221 make_midpoint(&m[0], v0, v1);
222 make_midpoint(&m[1], v1, v2);
223 make_midpoint(&m[2], v2, v0);
224
225 subdiv(&m[0], &m[2], v0, depth-1);
226 subdiv(&m[1], &m[0], v1, depth-1);
227 subdiv(&m[2], &m[1], v2, depth-1);
228 subdiv(&m[0], &m[1], &m[2], depth-1);
229 }
230}
231
232/** Assignment */
233#define ASSIGN_3V( V, V0, V1, V2 ) \
234do { \
235 V[0] = V0; \
236 V[1] = V1; \
237 V[2] = V2; \
238} while(0)
239
240static void Display( void )
241{
242 glClearColor(0.3, 0.3, 0.3, 1);
243 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
244
245 glUseProgram(program);
246
247 glBegin(GL_TRIANGLES);
248
249
250 {
251 union vert v[3];
252
253 ASSIGN_3V(v[0].v.color, 0,0,1);
254 ASSIGN_3V(v[0].v.pos, 0.9, -0.9, 0.0);
255 ASSIGN_3V(v[1].v.color, 1,0,0);
256 ASSIGN_3V(v[1].v.pos, 0.9, 0.9, 0.0);
257 ASSIGN_3V(v[2].v.color, 0,1,0);
258 ASSIGN_3V(v[2].v.pos, -0.9, 0, 0.0);
259
260 subdiv(&v[0], &v[1], &v[2], nr_steps);
261 }
262
263 glEnd();
264
265
266 glFlush();
267}
268
269
270static void Reshape( int width, int height )
271{
272 glViewport( 0, 0, width, height );
273 glMatrixMode( GL_PROJECTION );
274 glLoadIdentity();
275 glOrtho(-1.0, 1.0, -1.0, 1.0, -0.5, 1000.0);
276 glMatrixMode( GL_MODELVIEW );
277 glLoadIdentity();
278 /*glTranslatef( 0.0, 0.0, -15.0 );*/
279}
280
281
282static void CleanUp(void)
283{
284 glDeleteShader(fragShader);
285 glDeleteShader(vertShader);
286 glDeleteProgram(program);
287}
288
289static void Key( unsigned char key, int x, int y )
290{
291 (void) x;
292 (void) y;
293 switch (key) {
294 case 27:
295 CleanUp();
296 exit(0);
297 break;
298 }
299 glutPostRedisplay();
300}
301
302int main( int argc, char *argv[] )
303{
304 glutInit( &argc, argv );
305 glutInitWindowPosition( 0, 0 );
306 glutInitWindowSize( 250, 250 );
307 glutInitDisplayMode( GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH );
308 glutCreateWindow(argv[0]);
Keith Whitwellce0ac902009-03-09 17:10:12 +0000309 glewInit();
Zack Rusine842b5e2007-10-25 07:19:02 -0400310 glutReshapeFunc( Reshape );
311 glutKeyboardFunc( Key );
312 glutDisplayFunc( Display );
313 args( argc, argv );
314 prepare_shaders();
315 glutMainLoop();
316 return 0;
317}