rayzor

view src/renderer.cc @ 18:859ccadca671

portability fixes
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 14 Apr 2014 18:35:37 +0300
parents 79609d482762
children
line source
1 #include <string.h>
2 #include <stdarg.h>
3 #include "renderer.h"
4 #include "rayzor.h"
5 #include "scene.h"
6 #include "keyb.h"
7 #include "scrman.h"
8 #include "timer.h"
9 #include "logger.h"
10 #include "raytrace.h"
12 enum {
13 MSG_START,
14 MSG_GAMMA,
15 MSG_USE_GAMMA,
17 NUM_MESSAGES
18 };
20 struct RendererImpl {
21 bool in_progress;
22 int cur_x, cur_y; // current pixel being rendered
24 uint32_t *pixels;
26 float gamma, inv_gamma;
27 bool use_gamma;
29 MsgAtom msg[NUM_MESSAGES];
30 };
33 Renderer::Renderer()
34 {
35 set_name("renderer");
36 }
38 bool Renderer::init()
39 {
40 rend = new RendererImpl;
41 memset(rend, 0, sizeof *rend);
43 rend->pixels = new uint32_t[fb_width * fb_height];
44 if(!rend->pixels) {
45 return false;
46 }
47 memset(rend->pixels, 0, fb_width * fb_height * 4);
49 rend->gamma = 1.8;
50 rend->inv_gamma = 1.0 / rend->gamma;
51 rend->use_gamma = true;
53 rend->msg[MSG_START] = message_atom("start");
54 rend->msg[MSG_GAMMA] = message_atom("gamma");
55 rend->msg[MSG_USE_GAMMA] = message_atom("use-gamma");
57 return true;
58 }
60 void Renderer::shutdown()
61 {
62 if(rend) {
63 delete [] rend->pixels;
64 delete rend;
65 rend = 0;
66 }
67 }
69 void Renderer::draw() const
70 {
71 Camera *cam = scene->get_active_camera();
73 // if a rendering is not in progress, just show the last buffer
74 if(!rend->in_progress || !cam) {
75 memcpy(fb_pixels, rend->pixels, fb_width * fb_height * 4);
76 return;
77 }
79 // render for approximately half a second, then show and return
80 unsigned long start = get_msec();
81 uint32_t *dest = rend->pixels + rend->cur_y * fb_width + rend->cur_x;
83 for(;;) {
84 Ray ray = cam->get_primary_ray(rend->cur_x, rend->cur_y);
85 Vector3 color = ray_trace(ray);
87 // gamma-correct before storing the pixel
88 if(rend->use_gamma) {
89 color.x = pow(color.x, rend->inv_gamma);
90 color.y = pow(color.y, rend->inv_gamma);
91 color.z = pow(color.z, rend->inv_gamma);
92 }
94 int r = color.x > 1.0 ? 255 : (int)(color.x * 255.0);
95 int g = color.y > 1.0 ? 255 : (int)(color.y * 255.0);
96 int b = color.z > 1.0 ? 255 : (int)(color.z * 255.0);
98 *dest++ = (r << 16) | (g << 8) | b;
100 if(++rend->cur_x >= fb_width) {
101 rend->cur_x = 0;
102 if(++rend->cur_y >= fb_height) {
103 rend->in_progress = false;
104 printlog("done!\n");
105 break;
106 }
107 }
109 if(get_msec() - start >= 500) {
110 break;
111 }
112 }
114 memcpy(fb_pixels, rend->pixels, fb_width * fb_height * 4);
115 }
117 void Renderer::handle_keyboard(int key, bool press)
118 {
119 switch(key) {
120 case KB_ESC:
121 deactivate_screen();
122 break;
124 default:
125 break;
126 }
127 }
129 void Renderer::message(MsgAtom msg, ...)
130 {
131 va_list ap;
132 va_start(ap, msg);
134 for(int i=0; i<NUM_MESSAGES; i++) {
135 if(msg == rend->msg[i]) {
136 switch(i) {
137 case MSG_START:
138 rend->cur_x = rend->cur_y = 0;
139 rend->in_progress = true;
140 memset(rend->pixels, 0, fb_width * fb_height * 4);
142 printlog("starting a new rendering!\n");
143 break;
145 case MSG_GAMMA:
146 rend->gamma = va_arg(ap, double);
147 rend->inv_gamma = 1.0 / rend->gamma;
148 break;
150 case MSG_USE_GAMMA:
151 rend->use_gamma = va_arg(ap, int);
152 break;
153 }
154 }
155 }
157 va_end(ap);
158 }