erebus
diff liberebus/src/erebus.cc @ 8:e2d9bf168a41
semi-works ...
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 24 May 2014 06:12:57 +0300 |
parents | 9621beb22694 |
children | d38e13d6063c |
line diff
1.1 --- a/liberebus/src/erebus.cc Sat May 24 02:27:08 2014 +0300 1.2 +++ b/liberebus/src/erebus.cc Sat May 24 06:12:57 2014 +0300 1.3 @@ -9,6 +9,8 @@ 1.4 #include "geomobj.h" 1.5 #include "rt.h" 1.6 1.7 +#define INF_SAMPLES (INT_MAX / 2) 1.8 + 1.9 using namespace std::chrono; 1.10 1.11 struct Rect { 1.12 @@ -24,15 +26,17 @@ 1.13 Scene *scn; 1.14 1.15 Image<float> fbimg; 1.16 + Image<float> accum; // sample accumulator per pixel 1.17 Vector4 options[ERB_NUM_OPTIONS]; 1.18 1.19 // render state 1.20 long cur_time; 1.21 int cur_pixel_x, cur_pixel_y; 1.22 Rect cur_rect; 1.23 + int cur_sample; 1.24 }; 1.25 1.26 -static void render_pixel(struct erebus *ctx, int x, int y); 1.27 +static void render_pixel(struct erebus *ctx, int x, int y, int sample); 1.28 1.29 static std::mt19937 rnd_gen; 1.30 1.31 @@ -51,6 +55,8 @@ 1.32 ctx->scn = 0; 1.33 ctx->cur_time = 0; 1.34 ctx->cur_rect = INVALID_RECT; 1.35 + 1.36 + ctx->options[ERB_OPT_MAX_SAMPLES].x = (float)INF_SAMPLES; 1.37 return ctx; 1.38 } 1.39 1.40 @@ -94,12 +100,14 @@ 1.41 1.42 void erb_begin_frame(struct erebus *ctx, long ms) 1.43 { 1.44 + printf("starting new frame...\n"); 1.45 ctx->cur_time = ms; 1.46 1.47 int xsz = ctx->options[ERB_OPT_WIDTH].x; 1.48 int ysz = ctx->options[ERB_OPT_HEIGHT].x; 1.49 1.50 ctx->fbimg.create(xsz, ysz); 1.51 + ctx->accum.create(xsz, ysz); 1.52 } 1.53 1.54 int erb_render(struct erebus *ctx, long timeout) 1.55 @@ -113,31 +121,45 @@ 1.56 1.57 Rect rect{x, y, width, height}; 1.58 if(ctx->cur_rect != rect) { 1.59 + // starting a new rendering apparently 1.60 ctx->cur_rect = rect; 1.61 ctx->cur_pixel_x = x; 1.62 ctx->cur_pixel_y = y; 1.63 + ctx->cur_sample = 0; 1.64 } 1.65 1.66 ctx->scn->update(); 1.67 1.68 + int max_samples = ctx->options[ERB_OPT_MAX_SAMPLES].x; 1.69 + 1.70 if(timeout > 0) { 1.71 auto start_time = steady_clock::now(); 1.72 while(duration_cast<milliseconds>(steady_clock::now() - start_time).count() < timeout) { 1.73 - render_pixel(ctx, ctx->cur_pixel_x, ctx->cur_pixel_y); 1.74 + render_pixel(ctx, ctx->cur_pixel_x, ctx->cur_pixel_y, ctx->cur_sample); 1.75 1.76 if(++ctx->cur_pixel_x >= ctx->cur_rect.width) { 1.77 + ctx->cur_pixel_x = ctx->cur_rect.x; 1.78 if(++ctx->cur_pixel_y >= ctx->cur_rect.height) { 1.79 - ctx->cur_rect = INVALID_RECT; 1.80 - return 0; 1.81 + ctx->cur_pixel_y = ctx->cur_rect.y; 1.82 + if(++ctx->cur_sample >= max_samples) { 1.83 + ctx->cur_rect = INVALID_RECT; 1.84 + return 0; 1.85 + } 1.86 } 1.87 } 1.88 } 1.89 return 1; 1.90 } 1.91 1.92 + if(ctx->options[ERB_OPT_MAX_SAMPLES].x == (float)INF_SAMPLES) { 1.93 + max_samples = 128; 1.94 + } 1.95 + 1.96 for(int i=0; i<height; i++) { 1.97 for(int j=0; j<width; j++) { 1.98 - render_pixel(ctx, j, i); 1.99 + for(int k=0; k<max_samples; k++) { 1.100 + render_pixel(ctx, j, i, k); 1.101 + } 1.102 } 1.103 } 1.104 return 0; 1.105 @@ -155,11 +177,28 @@ 1.106 1.107 // XXX for now just create a test scene here 1.108 Sphere *sph = new Sphere; 1.109 + sph->mtl.set_attrib("albedo", Color(1.0, 0.3, 0.2)); 1.110 SceneNode *sph_node = new SceneNode(sph); 1.111 ctx->scn->add_object(sph); 1.112 ctx->scn->add_node(sph_node); 1.113 1.114 - TargetCamera *cam = new TargetCamera(Vector3(0, 0, -10), Vector3(0, 0, 0)); 1.115 + sph = new Sphere; 1.116 + sph->mtl.set_attrib("albedo", Color(0.3, 0.4, 1.0)); 1.117 + sph_node = new SceneNode(sph); 1.118 + sph_node->set_position(Vector3(0, -3.0, 0)); 1.119 + //sph_node->set_scaling(Vector3(4.0, 4.0, 4.0) * 0.3); 1.120 + ctx->scn->add_object(sph); 1.121 + ctx->scn->add_node(sph_node); 1.122 + 1.123 + Sphere *lt = new Sphere; 1.124 + lt->mtl.set_attrib("emissive", Color(10, 10, 10)); 1.125 + SceneNode *lt_node = new SceneNode(lt); 1.126 + lt_node->set_position(Vector3(-15, 15, -10)); 1.127 + lt_node->set_scaling(Vector3(5, 5, 5)); 1.128 + ctx->scn->add_object(lt); 1.129 + ctx->scn->add_node(lt_node); 1.130 + 1.131 + TargetCamera *cam = new TargetCamera(Vector3(0, 4, -8), Vector3(0, 0, 0)); 1.132 //ctx->scn->add_object(cam); 1.133 ctx->scn->use_camera(cam); 1.134 1.135 @@ -174,20 +213,28 @@ 1.136 return unirnd(rnd_gen); 1.137 } 1.138 1.139 -static void render_pixel(struct erebus *ctx, int x, int y) 1.140 +static void render_pixel(struct erebus *ctx, int x, int y, int sample) 1.141 { 1.142 Camera *cam = ctx->scn->get_active_camera(); 1.143 if(!cam) return; 1.144 1.145 int xsz = ctx->fbimg.get_width(); 1.146 int ysz = ctx->fbimg.get_height(); 1.147 - float *pix = ctx->fbimg.get_pixels() + (y * xsz + x) * 4; 1.148 + int offs = (y * xsz + x) * 4; 1.149 1.150 - Ray ray = cam->get_primary_ray(x, y, xsz, ysz, 0); 1.151 - //Color c = ray_trace(ray, ctx->scn, 0); 1.152 - Color c = ray.dir.normalized() * 0.5 + Vector3(0.5, 0.5, 0.5); 1.153 - pix[0] = 1.0;//c.x; 1.154 - pix[1] = c.y; 1.155 - pix[2] = c.z; 1.156 - pix[3] = c.w; 1.157 + float *pix = ctx->fbimg.get_pixels() + offs; 1.158 + float *accum = ctx->accum.get_pixels() + offs; 1.159 + 1.160 + Ray ray = cam->get_primary_ray(x, y, xsz, ysz, sample); 1.161 + Color c = ray_trace(ray, ctx->scn, 0); 1.162 + accum[0] += c.x; 1.163 + accum[1] += c.y; 1.164 + accum[2] += c.z; 1.165 + accum[3] += c.w; 1.166 + 1.167 + float inv_samples = 1.0f / (float)(sample + 1); 1.168 + pix[0] = accum[0] * inv_samples; 1.169 + pix[1] = accum[1] * inv_samples; 1.170 + pix[2] = accum[2] * inv_samples; 1.171 + pix[3] = accum[3] * inv_samples; 1.172 }