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  }