rayzor

annotate src/renderer.cc @ 21:8c4859442200

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