erebus
view src/main.cc @ 28:4a0a288ffb27
phong/lafortune BRDF
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Fri, 06 Jun 2014 14:39:40 +0300 |
parents | 56d504cc555a |
children | fb20e3855740 |
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <vector>
5 #include <chrono>
6 #include "opengl.h"
7 #include "erebus.h"
9 using namespace std::chrono;
11 #define SCALE 2
13 static bool init();
14 static void cleanup();
15 static void resize_rtarget(int xsz, int ysz);
16 static void update_rect(int x, int y, int xsz, int ysz, float *pixels);
17 static void idle();
18 static void display();
19 static void reshape(int x, int y);
20 static void keyb(unsigned char key, int x, int y);
21 static void keyb_up(unsigned char key, int x, int y);
22 static void mouse(int bn, int st, int x, int y);
23 static void motion(int x, int y);
24 static void sball_button(int bn, int st);
25 static void sball_motion(int x, int y, int z);
26 static int next_pow2(int x);
28 static int width, height, rtex_width, rtex_height;
29 static unsigned int rtex;
31 static erebus *erb;
32 static bool render_pending;
34 static std::vector<char*> sfiles;
36 int main(int argc, char **argv)
37 {
38 glutInitWindowSize(1024, 600);
39 glutInit(&argc, argv);
41 for(int i=1; i<argc; i++) {
42 sfiles.push_back(argv[i]);
43 }
45 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
46 glutCreateWindow("erebus OpenGL frontend");
48 glutDisplayFunc(display);
49 glutReshapeFunc(reshape);
50 glutKeyboardFunc(keyb);
51 glutKeyboardUpFunc(keyb_up);
52 glutMouseFunc(mouse);
53 glutMotionFunc(motion);
54 glutSpaceballButtonFunc(sball_button);
55 glutSpaceballMotionFunc(sball_motion);
57 if(!init()) {
58 return 1;
59 }
60 atexit(cleanup);
62 glutMainLoop();
63 }
65 static bool init()
66 {
67 width = glutGet(GLUT_WINDOW_WIDTH) / SCALE;
68 height = glutGet(GLUT_WINDOW_HEIGHT) / SCALE;
70 if(!(erb = erb_init())) {
71 return false;
72 }
73 erb_setopti(erb, ERB_OPT_WIDTH, width);
74 erb_setopti(erb, ERB_OPT_HEIGHT, height);
76 for(size_t i=0; i<sfiles.size(); i++) {
77 printf("loading scene file: %s\n", sfiles[i]);
78 if(erb_load_scene(erb, sfiles[i]) == -1) {
79 return false;
80 }
81 }
83 if(!sfiles.empty()) {
84 printf("begin rendering\n");
85 render_pending = true;
86 glutIdleFunc(idle);
87 erb_begin_frame(erb, 0);
88 }
90 glEnable(GL_TEXTURE_2D);
91 return true;
92 }
94 static void cleanup()
95 {
96 erb_destroy(erb);
97 }
99 static void resize_rtarget(int xsz, int ysz)
100 {
101 static unsigned char *defpix;
103 width = xsz / SCALE;
104 height = ysz / SCALE;
106 if(width <= rtex_width && height <= rtex_height) {
107 return;
108 }
109 rtex_width = next_pow2(width);
110 rtex_height = next_pow2(height);
112 printf("resizing framebuffer texture: %dx%d\n", rtex_width, rtex_height);
114 if(!rtex) {
115 glGenTextures(1, &rtex);
116 }
118 delete [] defpix;
119 defpix = new unsigned char[rtex_width * rtex_height * 4];
120 unsigned char *ptr = defpix;
121 for(int i=0; i<rtex_height; i++) {
122 for(int j=0; j<rtex_width; j++) {
123 bool chess = ((i >> 4) & 1) == ((j >> 4) & 1);
125 int val = chess ? 64 : 48;
127 *ptr++ = val;
128 *ptr++ = val;
129 *ptr++ = val;
130 *ptr++ = 255;
131 }
132 }
134 glBindTexture(GL_TEXTURE_2D, rtex);
135 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
136 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
137 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, rtex_width, rtex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, defpix);
138 }
140 static void update_rect(int x, int y, int xsz, int ysz, float *pixels)
141 {
142 glBindTexture(GL_TEXTURE_2D, rtex);
143 glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, xsz, ysz, GL_RGBA, GL_FLOAT, pixels);
144 }
146 static void idle()
147 {
148 glutPostRedisplay();
149 }
151 static void display()
152 {
153 if(render_pending) {
154 if(erb_render(erb, 64) == 0) {
155 render_pending = false;
156 glutIdleFunc(0);
157 }
158 update_rect(0, 0, width, height, erb_get_framebuffer(erb));
159 }
161 float maxu = (float)width / (float)rtex_width;
162 float maxv = (float)height / (float)rtex_height;
164 glBegin(GL_QUADS);
165 glTexCoord2f(0, maxv); glVertex2f(-1, -1);
166 glTexCoord2f(maxu, maxv); glVertex2f(1, -1);
167 glTexCoord2f(maxu, 0); glVertex2f(1, 1);
168 glTexCoord2f(0, 0); glVertex2f(-1, 1);
169 glEnd();
171 glutSwapBuffers();
172 assert(glGetError() == GL_NO_ERROR);
173 }
175 static void reshape(int x, int y)
176 {
177 glViewport(0, 0, x, y);
178 resize_rtarget(x, y);
180 erb_setopti(erb, ERB_OPT_WIDTH, width);
181 erb_setopti(erb, ERB_OPT_HEIGHT, height);
182 }
184 static void keyb(unsigned char key, int x, int y)
185 {
186 switch(key) {
187 case 27:
188 exit(0);
190 case ' ':
191 printf("begin rendering\n");
192 render_pending = true;
193 glutIdleFunc(idle);
194 erb_begin_frame(erb, 0);
195 break;
196 }
198 if(erb_input_keyboard(erb, key, true)) {
199 glutPostRedisplay();
200 }
201 }
203 static void keyb_up(unsigned char key, int x, int y)
204 {
205 if(erb_input_keyboard(erb, key, false)) {
206 glutPostRedisplay();
207 }
208 }
210 static void mouse(int bn, int st, int x, int y)
211 {
212 if(erb_input_mouse_button(erb, bn - GLUT_LEFT_BUTTON, st == GLUT_DOWN, x, y)) {
213 glutPostRedisplay();
214 }
215 }
217 static void motion(int x, int y)
218 {
219 if(erb_input_mouse_motion(erb, x, y)) {
220 glutPostRedisplay();
221 }
222 }
224 static void sball_button(int bn, int state)
225 {
226 if(erb_input_6dof_button(erb, bn, state == GLUT_DOWN)) {
227 glutPostRedisplay();
228 }
229 }
231 static void sball_motion(int x, int y, int z)
232 {
233 if(erb_input_6dof_motion(erb, x / 65536.0, y / 65536.0, z / 65536.0)) {
234 glutPostRedisplay();
235 }
236 }
238 static int next_pow2(int x)
239 {
240 int res = 2;
241 while(res < x) {
242 res <<= 1;
243 }
244 return res;
245 }