rev |
line source |
nuclear@0
|
1 #include <stdio.h>
|
nuclear@0
|
2 #include <stdlib.h>
|
nuclear@0
|
3 #include <stdarg.h>
|
nuclear@0
|
4 #include <assert.h>
|
nuclear@0
|
5 #include "opengl.h"
|
nuclear@0
|
6
|
nuclear@0
|
7 #include "gpuscene.h"
|
nuclear@0
|
8 #include "sphere.h"
|
nuclear@0
|
9 #include "plane.h"
|
nuclear@0
|
10 #include "image.h"
|
nuclear@0
|
11 #include "rend.h"
|
nuclear@0
|
12 #include "glsdr.h"
|
nuclear@0
|
13
|
nuclear@0
|
14 static bool init(const char *scene_fname);
|
nuclear@0
|
15 static void cleanup();
|
nuclear@0
|
16 static void disp();
|
nuclear@0
|
17 static void draw_text(float r, float g, float b, const char *fmt, ...);
|
nuclear@0
|
18 //static void update_texture(const float *fb);
|
nuclear@0
|
19 static void idle();
|
nuclear@0
|
20 static void reshape(int x, int y);
|
nuclear@0
|
21 static void handle_keys(float dt);
|
nuclear@0
|
22 static void keyb(unsigned char key, int x, int y);
|
nuclear@0
|
23 static void keyb_up(unsigned char key, int x, int y);
|
nuclear@0
|
24 static void skeyb(int key, int x, int y);
|
nuclear@0
|
25 static void mouse(int bn, int st, int x, int y);
|
nuclear@0
|
26 static void motion(int x, int y);
|
nuclear@0
|
27 static void sball_motion(int x, int y, int z);
|
nuclear@0
|
28 static void sball_rotate(int x, int y, int z);
|
nuclear@0
|
29 static void sball_button(int bn, int state);
|
nuclear@0
|
30
|
nuclear@0
|
31 static unsigned int tex;
|
nuclear@0
|
32 static long last_fps_upd, first_time = -1;
|
nuclear@0
|
33 static long frames, total_frames;
|
nuclear@0
|
34 static float fps;
|
nuclear@0
|
35 static int xsz = 800;
|
nuclear@0
|
36 static int ysz = 450;
|
nuclear@0
|
37 //static int tex_xsz, tex_ysz;
|
nuclear@0
|
38
|
nuclear@0
|
39 static GPUScene *scn;
|
nuclear@0
|
40 static FlyCamera *cam;
|
nuclear@0
|
41
|
nuclear@0
|
42 static float img_scale = 1.0f;
|
nuclear@0
|
43 static bool keystate[256];
|
nuclear@0
|
44
|
nuclear@0
|
45 static char *scene_fname;
|
nuclear@0
|
46 static bool sdr_valid = true;
|
nuclear@0
|
47
|
nuclear@0
|
48 int main(int argc, char **argv)
|
nuclear@0
|
49 {
|
nuclear@0
|
50 glutInit(&argc, argv);
|
nuclear@0
|
51
|
nuclear@0
|
52 int num_samples = 1;
|
nuclear@0
|
53
|
nuclear@0
|
54 for(int i=1; i<argc; i++) {
|
nuclear@0
|
55 if(argv[i][0] == '-') {
|
nuclear@0
|
56 if(strcmp(argv[i], "-size") == 0) {
|
nuclear@0
|
57 if(sscanf(argv[++i], "%dx%d", &xsz, &ysz) < 2) {
|
nuclear@0
|
58 fprintf(stderr, "-size must be followed by the image resolution (WxH)\n");
|
nuclear@0
|
59 return 1;
|
nuclear@0
|
60 }
|
nuclear@0
|
61
|
nuclear@0
|
62 } else if(strcmp(argv[i], "-samples") == 0) {
|
nuclear@0
|
63 num_samples = atoi(argv[++i]);
|
nuclear@0
|
64 if(num_samples <= 0) {
|
nuclear@0
|
65 fprintf(stderr, "-samples must be followed by the number of samples per pixel\n");
|
nuclear@0
|
66 return 1;
|
nuclear@0
|
67 }
|
nuclear@0
|
68 } else if(strcmp(argv[i], "-scale") == 0) {
|
nuclear@0
|
69 img_scale = atof(argv[++i]);
|
nuclear@0
|
70 if(img_scale <= 1.0f) {
|
nuclear@0
|
71 fprintf(stderr, "-scale must be followed by an image scale factor >= 1\n");
|
nuclear@0
|
72 return 1;
|
nuclear@0
|
73 }
|
nuclear@0
|
74 } else {
|
nuclear@0
|
75 fprintf(stderr, "invalid option: %s\n", argv[i]);
|
nuclear@0
|
76 return 1;
|
nuclear@0
|
77 }
|
nuclear@0
|
78 } else {
|
nuclear@0
|
79 if(scene_fname) {
|
nuclear@0
|
80 fprintf(stderr, "unexpected argument: %s\n", argv[i]);
|
nuclear@0
|
81 return 1;
|
nuclear@0
|
82 }
|
nuclear@0
|
83 scene_fname = argv[i];
|
nuclear@0
|
84 }
|
nuclear@0
|
85 }
|
nuclear@0
|
86
|
nuclear@0
|
87 glutInitWindowSize(xsz * img_scale, ysz * img_scale);
|
nuclear@0
|
88 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
|
nuclear@0
|
89 glutCreateWindow("single threaded");
|
nuclear@0
|
90
|
nuclear@0
|
91 glutDisplayFunc(disp);
|
nuclear@0
|
92 glutIdleFunc(idle);
|
nuclear@0
|
93 glutReshapeFunc(reshape);
|
nuclear@0
|
94 glutKeyboardFunc(keyb);
|
nuclear@0
|
95 glutKeyboardUpFunc(keyb_up);
|
nuclear@0
|
96 glutSpecialFunc(skeyb);
|
nuclear@0
|
97 glutMouseFunc(mouse);
|
nuclear@0
|
98 glutMotionFunc(motion);
|
nuclear@0
|
99 glutSpaceballMotionFunc(sball_motion);
|
nuclear@0
|
100 glutSpaceballRotateFunc(sball_rotate);
|
nuclear@0
|
101 glutSpaceballButtonFunc(sball_button);
|
nuclear@0
|
102
|
nuclear@0
|
103 glewInit();
|
nuclear@0
|
104
|
nuclear@0
|
105 if(!init(scene_fname)) {
|
nuclear@0
|
106 return 1;
|
nuclear@0
|
107 }
|
nuclear@0
|
108 atexit(cleanup);
|
nuclear@0
|
109
|
nuclear@0
|
110 glutMainLoop();
|
nuclear@0
|
111 return 0;
|
nuclear@0
|
112 }
|
nuclear@0
|
113
|
nuclear@0
|
114 static bool init(const char *scene_fname)
|
nuclear@0
|
115 {
|
nuclear@0
|
116 scn = new GPUScene;
|
nuclear@0
|
117 if(!scn->load(scene_fname ? scene_fname : "scene")) {
|
nuclear@0
|
118 return false;
|
nuclear@0
|
119 }
|
nuclear@0
|
120
|
nuclear@0
|
121 cam = new FlyCamera;
|
nuclear@0
|
122 cam->input_move(0, 1.5, -10);
|
nuclear@0
|
123 cam->input_rotate(25, 0, 0);
|
nuclear@0
|
124 scn->set_camera(cam);
|
nuclear@0
|
125
|
nuclear@0
|
126 if(!init_renderer(scn, xsz, ysz)) {
|
nuclear@0
|
127 return false;
|
nuclear@0
|
128 }
|
nuclear@0
|
129
|
nuclear@0
|
130 glGenTextures(1, &tex);
|
nuclear@0
|
131 glBindTexture(GL_TEXTURE_2D, tex);
|
nuclear@0
|
132 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
nuclear@0
|
133 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
nuclear@0
|
134 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
nuclear@0
|
135 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
nuclear@0
|
136
|
nuclear@0
|
137 int srgb_capable;
|
nuclear@0
|
138 if(GLEW_EXT_framebuffer_sRGB && (glGetIntegerv(GL_FRAMEBUFFER_SRGB_CAPABLE_EXT, &srgb_capable), srgb_capable)) {
|
nuclear@0
|
139 printf("enabling sRGB framebuffer\n");
|
nuclear@0
|
140 glEnable(GL_FRAMEBUFFER_SRGB);
|
nuclear@0
|
141 } else {
|
nuclear@0
|
142 printf("using post shader for gamma correction\n");
|
nuclear@0
|
143 unsigned int post_sdr = create_program_load(0, "sdr/postsdr.glsl");
|
nuclear@0
|
144 if(post_sdr) {
|
nuclear@0
|
145 glUseProgram(post_sdr);
|
nuclear@0
|
146 }
|
nuclear@0
|
147 }
|
nuclear@0
|
148
|
nuclear@0
|
149 last_fps_upd = glutGet(GLUT_ELAPSED_TIME);
|
nuclear@0
|
150 first_time = last_fps_upd;
|
nuclear@0
|
151 total_frames = 0;
|
nuclear@0
|
152 return true;
|
nuclear@0
|
153 }
|
nuclear@0
|
154
|
nuclear@0
|
155 static void cleanup()
|
nuclear@0
|
156 {
|
nuclear@0
|
157 long interval = glutGet(GLUT_ELAPSED_TIME) - first_time;
|
nuclear@0
|
158 printf("average fps: %.2f\n", (float)total_frames / ((float)interval / 1000.0f));
|
nuclear@0
|
159
|
nuclear@0
|
160 glDeleteTextures(1, &tex);
|
nuclear@0
|
161
|
nuclear@0
|
162 destroy_renderer();
|
nuclear@0
|
163 delete scn;
|
nuclear@0
|
164 }
|
nuclear@0
|
165
|
nuclear@0
|
166 static void disp()
|
nuclear@0
|
167 {
|
nuclear@0
|
168 static long prev_msec;
|
nuclear@0
|
169 long interval, msec = glutGet(GLUT_ELAPSED_TIME);
|
nuclear@0
|
170
|
nuclear@0
|
171 handle_keys((msec - prev_msec) / 1000.0f);
|
nuclear@0
|
172 prev_msec = msec;
|
nuclear@0
|
173
|
nuclear@0
|
174 //update_texture();
|
nuclear@0
|
175 if(sdr_valid) {
|
nuclear@0
|
176 render_frame(msec);
|
nuclear@0
|
177 } else {
|
nuclear@0
|
178 glUseProgram(0);
|
nuclear@0
|
179 glMatrixMode(GL_MODELVIEW);
|
nuclear@0
|
180 glLoadIdentity();
|
nuclear@0
|
181 glMatrixMode(GL_PROJECTION);
|
nuclear@0
|
182 glLoadIdentity();
|
nuclear@0
|
183
|
nuclear@0
|
184 glLineWidth(8.0);
|
nuclear@0
|
185 glBegin(GL_LINES);
|
nuclear@0
|
186 glColor3f(1, 0, 0);
|
nuclear@0
|
187 glVertex2f(-1, -1);
|
nuclear@0
|
188 glVertex2f(1, 1);
|
nuclear@0
|
189 glVertex2f(-1, 1);
|
nuclear@0
|
190 glVertex2f(1, -1);
|
nuclear@0
|
191 glEnd();
|
nuclear@0
|
192 glLineWidth(1.0);
|
nuclear@0
|
193 }
|
nuclear@0
|
194
|
nuclear@0
|
195 draw_text(0.8, 0.75, 0, "fps: %.2f", fps);
|
nuclear@0
|
196
|
nuclear@0
|
197 glutSwapBuffers();
|
nuclear@0
|
198 frames++;
|
nuclear@0
|
199 total_frames++;
|
nuclear@0
|
200
|
nuclear@0
|
201 interval = (msec = glutGet(GLUT_ELAPSED_TIME)) - last_fps_upd;
|
nuclear@0
|
202 if(interval >= 2000) {
|
nuclear@0
|
203 float tm = (float)interval / 1000.0f;
|
nuclear@0
|
204 fps = (float)frames / tm;
|
nuclear@0
|
205 /*printf("%.2f fps \r", (float)frames / tm);
|
nuclear@0
|
206 fflush(stdout);*/
|
nuclear@0
|
207 last_fps_upd = msec;
|
nuclear@0
|
208 frames = 0;
|
nuclear@0
|
209 }
|
nuclear@0
|
210 }
|
nuclear@0
|
211
|
nuclear@0
|
212 void draw_text(float r, float g, float b, const char *fmt, ...)
|
nuclear@0
|
213 {
|
nuclear@0
|
214 char buf[256], *text = buf;
|
nuclear@0
|
215 va_list ap;
|
nuclear@0
|
216
|
nuclear@0
|
217 va_start(ap, fmt);
|
nuclear@0
|
218 vsprintf(buf, fmt, ap);
|
nuclear@0
|
219 va_end(ap);
|
nuclear@0
|
220
|
nuclear@0
|
221 glUseProgram(0);
|
nuclear@0
|
222
|
nuclear@0
|
223 glMatrixMode(GL_MODELVIEW);
|
nuclear@0
|
224 glPushMatrix();
|
nuclear@0
|
225 glLoadIdentity();
|
nuclear@0
|
226 glMatrixMode(GL_PROJECTION);
|
nuclear@0
|
227 glPushMatrix();
|
nuclear@0
|
228 glLoadIdentity();
|
nuclear@0
|
229 glOrtho(0, xsz, 0, ysz, -1, 1);
|
nuclear@0
|
230
|
nuclear@0
|
231 glColor3f(r, g, b);
|
nuclear@0
|
232 glRasterPos2f(2, 4);
|
nuclear@0
|
233 while(*text) {
|
nuclear@0
|
234 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *text++);
|
nuclear@0
|
235 }
|
nuclear@0
|
236 glColor3f(1, 1, 1);
|
nuclear@0
|
237
|
nuclear@0
|
238 glPopMatrix();
|
nuclear@0
|
239 glMatrixMode(GL_MODELVIEW);
|
nuclear@0
|
240 glPopMatrix();
|
nuclear@0
|
241 }
|
nuclear@0
|
242
|
nuclear@0
|
243
|
nuclear@0
|
244 /*
|
nuclear@0
|
245 static void update_texture()
|
nuclear@0
|
246 {
|
nuclear@0
|
247 int ntx = next_pow2(xsz);
|
nuclear@0
|
248 int nty = next_pow2(ysz);
|
nuclear@0
|
249
|
nuclear@0
|
250 if(ntx != tex_xsz || nty != tex_ysz) {
|
nuclear@0
|
251 tex_xsz = ntx;
|
nuclear@0
|
252 tex_ysz = nty;
|
nuclear@0
|
253
|
nuclear@0
|
254 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, tex_xsz, tex_ysz, 0, GL_RGB, GL_FLOAT, 0);
|
nuclear@0
|
255 }
|
nuclear@0
|
256 }
|
nuclear@0
|
257 */
|
nuclear@0
|
258
|
nuclear@0
|
259 static void idle()
|
nuclear@0
|
260 {
|
nuclear@0
|
261 glutPostRedisplay();
|
nuclear@0
|
262 }
|
nuclear@0
|
263
|
nuclear@0
|
264 static void reshape(int x, int y)
|
nuclear@0
|
265 {
|
nuclear@0
|
266 int tx, ty;
|
nuclear@0
|
267
|
nuclear@0
|
268 xsz = x / img_scale;
|
nuclear@0
|
269 ysz = y / img_scale;
|
nuclear@0
|
270
|
nuclear@0
|
271 glViewport(0, 0, x, y);
|
nuclear@0
|
272
|
nuclear@0
|
273 /* setup the texture matrix that maps just the visible area
|
nuclear@0
|
274 * of the texture to [0, 1]
|
nuclear@0
|
275 */
|
nuclear@0
|
276 tx = next_pow2(xsz);
|
nuclear@0
|
277 ty = next_pow2(ysz);
|
nuclear@0
|
278
|
nuclear@0
|
279 glMatrixMode(GL_TEXTURE);
|
nuclear@0
|
280 glLoadIdentity();
|
nuclear@0
|
281 glScalef((float)xsz / tx, (float)ysz / ty, 1.0f);
|
nuclear@0
|
282
|
nuclear@0
|
283 resize_renderer(xsz, ysz);
|
nuclear@0
|
284 }
|
nuclear@0
|
285
|
nuclear@0
|
286 static void handle_keys(float dt)
|
nuclear@0
|
287 {
|
nuclear@0
|
288 Vector3 move;
|
nuclear@0
|
289 float tilt = 0.0f;
|
nuclear@0
|
290 float offs = dt * 8.0;
|
nuclear@0
|
291
|
nuclear@0
|
292 if(keystate['w']) {
|
nuclear@0
|
293 move.z += offs;
|
nuclear@0
|
294 }
|
nuclear@0
|
295 if(keystate['s']) {
|
nuclear@0
|
296 move.z -= offs;
|
nuclear@0
|
297 }
|
nuclear@0
|
298 if(keystate['d']) {
|
nuclear@0
|
299 move.x += offs;
|
nuclear@0
|
300 }
|
nuclear@0
|
301 if(keystate['a']) {
|
nuclear@0
|
302 move.x -= offs;
|
nuclear@0
|
303 }
|
nuclear@0
|
304
|
nuclear@0
|
305 if(keystate['q']) {
|
nuclear@0
|
306 tilt -= dt;
|
nuclear@0
|
307 }
|
nuclear@0
|
308 if(keystate['e']) {
|
nuclear@0
|
309 tilt += dt;
|
nuclear@0
|
310 }
|
nuclear@0
|
311
|
nuclear@0
|
312 cam->input_move(move.x, move.y, move.z);
|
nuclear@0
|
313 cam->input_rotate(0, 0, tilt);
|
nuclear@0
|
314 }
|
nuclear@0
|
315
|
nuclear@0
|
316 static void keyb(unsigned char key, int x, int y)
|
nuclear@0
|
317 {
|
nuclear@0
|
318 keystate[key] = true;
|
nuclear@0
|
319
|
nuclear@0
|
320 switch(key) {
|
nuclear@0
|
321 case 27:
|
nuclear@0
|
322 exit(0);
|
nuclear@0
|
323
|
nuclear@0
|
324 case '`':
|
nuclear@0
|
325 sdr_valid = reload_shader();
|
nuclear@0
|
326 break;
|
nuclear@0
|
327 }
|
nuclear@0
|
328 }
|
nuclear@0
|
329
|
nuclear@0
|
330 static void keyb_up(unsigned char key, int x, int y)
|
nuclear@0
|
331 {
|
nuclear@0
|
332 keystate[key] = false;
|
nuclear@0
|
333 }
|
nuclear@0
|
334
|
nuclear@0
|
335 static void skeyb(int key, int x, int y)
|
nuclear@0
|
336 {
|
nuclear@0
|
337 switch(key) {
|
nuclear@0
|
338 case GLUT_KEY_F1:
|
nuclear@0
|
339 printf("reinitializing\n");
|
nuclear@0
|
340 cleanup();
|
nuclear@0
|
341 sdr_valid = init(scene_fname);
|
nuclear@0
|
342 break;
|
nuclear@0
|
343
|
nuclear@0
|
344 default:
|
nuclear@0
|
345 break;
|
nuclear@0
|
346 }
|
nuclear@0
|
347 }
|
nuclear@0
|
348
|
nuclear@0
|
349 static int prev_x, prev_y;
|
nuclear@0
|
350
|
nuclear@0
|
351 static void mouse(int bn, int st, int x, int y)
|
nuclear@0
|
352 {
|
nuclear@0
|
353 prev_x = x;
|
nuclear@0
|
354 prev_y = y;
|
nuclear@0
|
355 }
|
nuclear@0
|
356
|
nuclear@0
|
357 static void motion(int x, int y)
|
nuclear@0
|
358 {
|
nuclear@0
|
359 int dx = x - prev_x;
|
nuclear@0
|
360 int dy = y - prev_y;
|
nuclear@0
|
361 prev_x = x;
|
nuclear@0
|
362 prev_y = y;
|
nuclear@0
|
363 cam->input_rotate(-dy * 0.01, -dx * 0.01, 0);
|
nuclear@0
|
364 }
|
nuclear@0
|
365
|
nuclear@0
|
366 static void sball_motion(int x, int y, int z)
|
nuclear@0
|
367 {
|
nuclear@0
|
368 float fx = x * 0.01;
|
nuclear@0
|
369 float fy = y * 0.01;
|
nuclear@0
|
370 float fz = z * 0.01;
|
nuclear@0
|
371 cam->input_move(fx, fy, fz);
|
nuclear@0
|
372 }
|
nuclear@0
|
373
|
nuclear@0
|
374 static void sball_rotate(int x, int y, int z)
|
nuclear@0
|
375 {
|
nuclear@0
|
376 float fx = x * 0.00025;
|
nuclear@0
|
377 float fy = y * 0.00025;
|
nuclear@0
|
378 float fz = z * 0.00025;
|
nuclear@0
|
379 cam->input_rotate(fx, fy, fz);
|
nuclear@0
|
380 }
|
nuclear@0
|
381
|
nuclear@0
|
382 static void sball_button(int bn, int state)
|
nuclear@0
|
383 {
|
nuclear@0
|
384 }
|
nuclear@0
|
385
|
nuclear@0
|
386
|
nuclear@0
|
387 int next_pow2(int x)
|
nuclear@0
|
388 {
|
nuclear@0
|
389 x--;
|
nuclear@0
|
390 x = (x >> 1) | x;
|
nuclear@0
|
391 x = (x >> 2) | x;
|
nuclear@0
|
392 x = (x >> 4) | x;
|
nuclear@0
|
393 x = (x >> 8) | x;
|
nuclear@0
|
394 x = (x >> 16) | x;
|
nuclear@0
|
395 return x + 1;
|
nuclear@0
|
396 }
|