erebus

diff liberebus/src/erebus.cc @ 17:e9da2916bc79

fixed the normal bug
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 26 May 2014 05:41:28 +0300
parents 20d6c05529f1
children 09028848f276
line diff
     1.1 --- a/liberebus/src/erebus.cc	Sun May 25 02:23:39 2014 +0300
     1.2 +++ b/liberebus/src/erebus.cc	Mon May 26 05:41:28 2014 +0300
     1.3 @@ -3,8 +3,7 @@
     1.4  #include <chrono>
     1.5  #include <random>
     1.6  #include "erebus.h"
     1.7 -#include "vmath/vector.h"
     1.8 -#include "image.h"
     1.9 +#include "erebus_impl.h"
    1.10  #include "scene.h"
    1.11  #include "geomobj.h"
    1.12  #include "rt.h"
    1.13 @@ -13,37 +12,8 @@
    1.14  
    1.15  using namespace std::chrono;
    1.16  
    1.17 -struct Rect {
    1.18 -	int x, y, width, height;
    1.19 -
    1.20 -	bool operator ==(const Rect &r) { return memcmp(this, &r, sizeof r) == 0; }
    1.21 -	bool operator !=(const Rect &r) { return memcmp(this, &r, sizeof r) != 0; }
    1.22 -};
    1.23 -
    1.24  #define INVALID_RECT	Rect{0, 0, 0, 0}
    1.25  
    1.26 -struct erebus {
    1.27 -	Scene *scn;
    1.28 -
    1.29 -	Image<float> fbimg;
    1.30 -	Image<float> accum;	// sample accumulator per pixel
    1.31 -	Vector4 options[ERB_NUM_OPTIONS];
    1.32 -
    1.33 -	// render state
    1.34 -	long cur_time;
    1.35 -	int cur_pixel_x, cur_pixel_y;
    1.36 -	Rect cur_rect;
    1.37 -	int cur_sample;
    1.38 -
    1.39 -	// interactive input
    1.40 -	std::vector<bool> keystate;
    1.41 -	std::vector<bool> bnstate;
    1.42 -	int mouse_pos[2];
    1.43 -
    1.44 -	// debugging stuff
    1.45 -	int dbg_nodesel;
    1.46 -};
    1.47 -
    1.48  static void render_pixel(struct erebus *ctx, int x, int y, int sample);
    1.49  
    1.50  static std::mt19937 rnd_gen;
    1.51 @@ -66,7 +36,10 @@
    1.52  	ctx->cur_time = 0;
    1.53  	ctx->cur_rect = INVALID_RECT;
    1.54  
    1.55 -	ctx->options[ERB_OPT_MAX_SAMPLES].x = (float)INF_SAMPLES;
    1.56 +	erb_setoptf(ctx, ERB_OPT_GAMMA, 2.2);
    1.57 +	erb_setopti(ctx, ERB_OPT_MAX_ITER, 6);
    1.58 +	erb_setopti(ctx, ERB_OPT_MAX_SAMPLES, INF_SAMPLES);
    1.59 +	erb_setopti(ctx, ERB_OPT_NUM_THREADS, -1);
    1.60  
    1.61  	ctx->dbg_nodesel = -1;
    1.62  	return ctx;
    1.63 @@ -79,30 +52,69 @@
    1.64  
    1.65  void erb_setopti(struct erebus *ctx, enum erb_option opt, int val)
    1.66  {
    1.67 -	ctx->options[opt].x = val;
    1.68 +	ctx->options[opt].ival = val;
    1.69 +	ctx->options[opt].type = Option::Type::INT;
    1.70  }
    1.71 +
    1.72  void erb_setoptf(struct erebus *ctx, enum erb_option opt, float val)
    1.73  {
    1.74 -	ctx->options[opt].x = val;
    1.75 +	ctx->options[opt].fval = val;
    1.76 +	ctx->options[opt].type = Option::Type::FLOAT;
    1.77  }
    1.78 +
    1.79  void erb_setoptfv(struct erebus *ctx, enum erb_option opt, float *vec)
    1.80  {
    1.81  	for(int i=0; i<4; i++) {
    1.82 -		ctx->options[opt][i] = vec[i];
    1.83 +		ctx->options[opt].vval[i] = vec[i];
    1.84  	}
    1.85 +	ctx->options[opt].type = Option::Type::VEC;
    1.86  }
    1.87  
    1.88  int erb_getopti(struct erebus *ctx, enum erb_option opt)
    1.89  {
    1.90 -	return ctx->options[opt].x;
    1.91 +	switch(ctx->options[opt].type) {
    1.92 +	case Option::Type::INT:
    1.93 +		return ctx->options[opt].ival;
    1.94 +	case Option::Type::FLOAT:
    1.95 +		return (int)ctx->options[opt].fval;
    1.96 +	case Option::Type::VEC:
    1.97 +		return (int)ctx->options[opt].vval.x;
    1.98 +	}
    1.99 +	return 0;	// can't happen
   1.100  }
   1.101 +
   1.102  float erb_getoptf(struct erebus *ctx, enum erb_option opt)
   1.103  {
   1.104 -	return ctx->options[opt].x;
   1.105 +	switch(ctx->options[opt].type) {
   1.106 +	case Option::Type::INT:
   1.107 +		return (float)ctx->options[opt].ival;
   1.108 +	case Option::Type::FLOAT:
   1.109 +		return ctx->options[opt].fval;
   1.110 +	case Option::Type::VEC:
   1.111 +		return ctx->options[opt].vval.x;
   1.112 +	}
   1.113 +	return 0.0f;	// can't happen
   1.114  }
   1.115 +
   1.116  float *erb_getoptfv(struct erebus *ctx, enum erb_option opt)
   1.117  {
   1.118 -	return &ctx->options[opt].x;
   1.119 +	switch(ctx->options[opt].type) {
   1.120 +	case Option::Type::INT:
   1.121 +		{
   1.122 +			int ival = ctx->options[opt].ival;
   1.123 +			ctx->options[opt].vval = Vector4(ival, ival, ival, ival);
   1.124 +		}
   1.125 +		break;
   1.126 +	case Option::Type::FLOAT:
   1.127 +		{
   1.128 +			float fval = ctx->options[opt].fval;
   1.129 +			ctx->options[opt].vval = Vector4(fval, fval, fval, fval);
   1.130 +		}
   1.131 +	default:
   1.132 +		break;
   1.133 +	}
   1.134 +
   1.135 +	return &ctx->options[opt].vval.x;
   1.136  }
   1.137  
   1.138  float *erb_get_framebuffer(struct erebus *ctx)
   1.139 @@ -115,13 +127,14 @@
   1.140  	printf("starting new frame...\n");
   1.141  	ctx->cur_time = ms;
   1.142  
   1.143 -	int xsz = ctx->options[ERB_OPT_WIDTH].x;
   1.144 -	int ysz = ctx->options[ERB_OPT_HEIGHT].x;
   1.145 +	int xsz = erb_getopti(ctx, ERB_OPT_WIDTH);
   1.146 +	int ysz = erb_getopti(ctx, ERB_OPT_HEIGHT);
   1.147  
   1.148  	ctx->fbimg.create(xsz, ysz);
   1.149  	ctx->accum.create(xsz, ysz);
   1.150  
   1.151  	ctx->cur_rect = INVALID_RECT;
   1.152 +	ctx->inv_gamma = 1.0f / erb_getoptf(ctx, ERB_OPT_GAMMA);
   1.153  }
   1.154  
   1.155  int erb_render(struct erebus *ctx, long timeout)
   1.156 @@ -144,7 +157,7 @@
   1.157  
   1.158  	ctx->scn->update();
   1.159  
   1.160 -	int max_samples = ctx->options[ERB_OPT_MAX_SAMPLES].x;
   1.161 +	int max_samples = erb_getopti(ctx, ERB_OPT_MAX_SAMPLES);
   1.162  
   1.163  	if(timeout > 0) {
   1.164  		auto start_time = steady_clock::now();
   1.165 @@ -165,7 +178,8 @@
   1.166  		return 1;
   1.167  	}
   1.168  
   1.169 -	if(ctx->options[ERB_OPT_MAX_SAMPLES].x == (float)INF_SAMPLES) {
   1.170 +	if(max_samples == INF_SAMPLES) {
   1.171 +		// don't allow infinite samples when rendering non-progressively
   1.172  		max_samples = 128;
   1.173  	}
   1.174  
   1.175 @@ -191,16 +205,16 @@
   1.176  
   1.177  	// XXX for now just create a test scene here
   1.178  	Sphere *sph = new Sphere;
   1.179 -	sph->mtl.set_attrib("albedo", Color(1.0, 0.3, 0.2));
   1.180 +	sph->mtl.set_attrib("diffuse", Color(1.0, 0.3, 0.2));
   1.181  	SceneNode *sph_node = new SceneNode(sph);
   1.182  	ctx->scn->add_object(sph);
   1.183  	ctx->scn->add_node(sph_node);
   1.184  
   1.185  	sph = new Sphere;
   1.186 -	sph->mtl.set_attrib("albedo", Color(0.3, 0.4, 1.0));
   1.187 +	sph->mtl.set_attrib("diffuse", Color(0.3, 0.4, 1.0));
   1.188  	sph_node = new SceneNode(sph);
   1.189 -	sph_node->set_position(Vector3(0, -3.0, 0));
   1.190 -	//sph_node->set_scaling(Vector3(4.0, 4.0, 4.0) * 0.3);
   1.191 +	sph_node->set_position(Vector3(0, -251.0, 0));
   1.192 +	sph_node->set_scaling(Vector3(250.0, 250.0, 250.0));
   1.193  	ctx->scn->add_object(sph);
   1.194  	ctx->scn->add_node(sph_node);
   1.195  
   1.196 @@ -208,7 +222,7 @@
   1.197  	lt->mtl.set_attrib("emissive", Color(10, 10, 10));
   1.198  	SceneNode *lt_node = new SceneNode(lt);
   1.199  	lt_node->set_position(Vector3(-15, 15, -10));
   1.200 -	lt_node->set_scaling(Vector3(5, 5, 5));
   1.201 +	lt_node->set_scaling(Vector3(8, 8, 8));
   1.202  	ctx->scn->add_object(lt);
   1.203  	ctx->scn->add_node(lt_node);
   1.204  
   1.205 @@ -331,15 +345,26 @@
   1.206  	float *accum = ctx->accum.get_pixels() + offs;
   1.207  
   1.208  	Ray ray = cam->get_primary_ray(x, y, xsz, ysz, sample);
   1.209 -	Color c = ray_trace(ray, ctx->scn, 0);
   1.210 +	Color c = ray_trace(ctx, ray, 0);
   1.211  	accum[0] += c.x;
   1.212  	accum[1] += c.y;
   1.213  	accum[2] += c.z;
   1.214  	accum[3] += c.w;
   1.215  
   1.216  	float inv_samples = 1.0f / (float)(sample + 1);
   1.217 -	pix[0] = accum[0] * inv_samples;
   1.218 -	pix[1] = accum[1] * inv_samples;
   1.219 -	pix[2] = accum[2] * inv_samples;
   1.220 +	pix[0] = pow(accum[0] * inv_samples, ctx->inv_gamma);
   1.221 +	pix[1] = pow(accum[1] * inv_samples, ctx->inv_gamma);
   1.222 +	pix[2] = pow(accum[2] * inv_samples, ctx->inv_gamma);
   1.223  	pix[3] = accum[3] * inv_samples;
   1.224  }
   1.225 +
   1.226 +bool Rect::operator ==(const Rect &r) const
   1.227 +{
   1.228 +	return memcmp(this, &r, sizeof r) == 0;
   1.229 +}
   1.230 +
   1.231 +bool Rect::operator !=(const Rect &r) const
   1.232 +{
   1.233 +	return memcmp(this, &r, sizeof r) != 0;
   1.234 +}
   1.235 +