erebus

changeset 8:e2d9bf168a41

semi-works ...
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 24 May 2014 06:12:57 +0300
parents f067148b3494
children d38e13d6063c
files liberebus/src/camera.cc liberebus/src/camera.h liberebus/src/erebus.cc liberebus/src/erebus.h liberebus/src/geomobj.cc liberebus/src/geomobj.h liberebus/src/material.cc liberebus/src/rt.cc liberebus/src/rt.h liberebus/src/scene.cc liberebus/src/scene.h liberebus/src/snode.cc src/main.cc
diffstat 13 files changed, 229 insertions(+), 78 deletions(-) [+]
line diff
     1.1 --- a/liberebus/src/camera.cc	Sat May 24 02:27:08 2014 +0300
     1.2 +++ b/liberebus/src/camera.cc	Sat May 24 06:12:57 2014 +0300
     1.3 @@ -2,32 +2,25 @@
     1.4  #include <math.h>
     1.5  #include "camera.h"
     1.6  
     1.7 +#define DEFAULT_FOV		DEG_TO_RAD(50)
     1.8 +
     1.9  static void calc_sample_pos_rec(int sidx, float xsz, float ysz, float *pos);
    1.10  
    1.11  Camera::Camera()
    1.12  {
    1.13 -	vfov = M_PI / 4.0;
    1.14 +	vfov = DEFAULT_FOV;
    1.15  	cached_matrix_valid = false;
    1.16 -
    1.17 -	rdir_cache_width = rdir_cache_height = 0;
    1.18 -	rdir_cache_fov = 0;
    1.19 -	rdir_cache = 0;
    1.20  }
    1.21  
    1.22  Camera::Camera(const Vector3 &p)
    1.23  	: pos(p)
    1.24  {
    1.25 -	vfov = M_PI / 4.0;
    1.26 +	vfov = DEFAULT_FOV;
    1.27  	cached_matrix_valid = false;
    1.28 -
    1.29 -	rdir_cache_width = rdir_cache_height = 0;
    1.30 -	rdir_cache_fov = 0;
    1.31 -	rdir_cache = 0;
    1.32  }
    1.33  
    1.34  Camera::~Camera()
    1.35  {
    1.36 -	delete [] rdir_cache;
    1.37  }
    1.38  
    1.39  void Camera::set_fov(float vfov)
    1.40 @@ -77,38 +70,14 @@
    1.41  
    1.42  Ray Camera::get_primary_ray(int x, int y, int xsz, int ysz, int sample) const
    1.43  {
    1.44 -#pragma omp single
    1.45 -	{
    1.46 -		if(!rdir_cache || rdir_cache_width != xsz || rdir_cache_height != ysz ||
    1.47 -				fabs(rdir_cache_fov - vfov) > 1e-4) {
    1.48 -			printf("calculating primary ray direction cache (%dx%d)\n", xsz, ysz);
    1.49 -
    1.50 -			delete [] rdir_cache;
    1.51 -			rdir_cache = new Vector3[xsz * ysz];
    1.52 -
    1.53 -#pragma omp parallel for
    1.54 -			for(int i=0; i<ysz; i++) {
    1.55 -				Vector3 *rdir = rdir_cache + i * xsz;
    1.56 -				for(int j=0; j<xsz; j++) {
    1.57 -					Vector2 ppos = calc_sample_pos(j, i, xsz, ysz, 0);
    1.58 -
    1.59 -					rdir->x = ppos.x;
    1.60 -					rdir->y = ppos.y;
    1.61 -					rdir->z = 1.0 / tan(vfov / 2.0);
    1.62 -					rdir->normalize();
    1.63 -
    1.64 -					rdir++;
    1.65 -				}
    1.66 -			}
    1.67 -			rdir_cache_width = xsz;
    1.68 -			rdir_cache_height = ysz;
    1.69 -			rdir_cache_fov = vfov;
    1.70 -		}
    1.71 -	}
    1.72 +	Vector2 ppos = calc_sample_pos(x, y, xsz, ysz, sample);
    1.73  
    1.74  	Ray ray;
    1.75  	ray.origin = pos;
    1.76 -	ray.dir = rdir_cache[y * xsz + x];
    1.77 +	ray.dir.x = ppos.x;
    1.78 +	ray.dir.y = ppos.y;
    1.79 +	ray.dir.z = 1.0 / tan(vfov / 2.0);
    1.80 +	ray.dir.normalize();
    1.81  
    1.82  	// transform the ray direction with the camera matrix
    1.83  	Matrix4x4 mat = get_matrix();
     2.1 --- a/liberebus/src/camera.h	Sat May 24 02:27:08 2014 +0300
     2.2 +++ b/liberebus/src/camera.h	Sat May 24 06:12:57 2014 +0300
     2.3 @@ -11,10 +11,6 @@
     2.4  	mutable Matrix4x4 cached_matrix;
     2.5  	mutable bool cached_matrix_valid;
     2.6  
     2.7 -	mutable Vector3 *rdir_cache;
     2.8 -	mutable int rdir_cache_width, rdir_cache_height;
     2.9 -	mutable float rdir_cache_fov;
    2.10 -
    2.11  	virtual void calc_matrix(Matrix4x4 *mat) const = 0;
    2.12  
    2.13  	Vector2 calc_sample_pos(int x, int y, int xsz, int ysz, int sample) const;
     3.1 --- a/liberebus/src/erebus.cc	Sat May 24 02:27:08 2014 +0300
     3.2 +++ b/liberebus/src/erebus.cc	Sat May 24 06:12:57 2014 +0300
     3.3 @@ -9,6 +9,8 @@
     3.4  #include "geomobj.h"
     3.5  #include "rt.h"
     3.6  
     3.7 +#define INF_SAMPLES		(INT_MAX / 2)
     3.8 +
     3.9  using namespace std::chrono;
    3.10  
    3.11  struct Rect {
    3.12 @@ -24,15 +26,17 @@
    3.13  	Scene *scn;
    3.14  
    3.15  	Image<float> fbimg;
    3.16 +	Image<float> accum;	// sample accumulator per pixel
    3.17  	Vector4 options[ERB_NUM_OPTIONS];
    3.18  
    3.19  	// render state
    3.20  	long cur_time;
    3.21  	int cur_pixel_x, cur_pixel_y;
    3.22  	Rect cur_rect;
    3.23 +	int cur_sample;
    3.24  };
    3.25  
    3.26 -static void render_pixel(struct erebus *ctx, int x, int y);
    3.27 +static void render_pixel(struct erebus *ctx, int x, int y, int sample);
    3.28  
    3.29  static std::mt19937 rnd_gen;
    3.30  
    3.31 @@ -51,6 +55,8 @@
    3.32  	ctx->scn = 0;
    3.33  	ctx->cur_time = 0;
    3.34  	ctx->cur_rect = INVALID_RECT;
    3.35 +
    3.36 +	ctx->options[ERB_OPT_MAX_SAMPLES].x = (float)INF_SAMPLES;
    3.37  	return ctx;
    3.38  }
    3.39  
    3.40 @@ -94,12 +100,14 @@
    3.41  
    3.42  void erb_begin_frame(struct erebus *ctx, long ms)
    3.43  {
    3.44 +	printf("starting new frame...\n");
    3.45  	ctx->cur_time = ms;
    3.46  
    3.47  	int xsz = ctx->options[ERB_OPT_WIDTH].x;
    3.48  	int ysz = ctx->options[ERB_OPT_HEIGHT].x;
    3.49  
    3.50  	ctx->fbimg.create(xsz, ysz);
    3.51 +	ctx->accum.create(xsz, ysz);
    3.52  }
    3.53  
    3.54  int erb_render(struct erebus *ctx, long timeout)
    3.55 @@ -113,31 +121,45 @@
    3.56  
    3.57  	Rect rect{x, y, width, height};
    3.58  	if(ctx->cur_rect != rect) {
    3.59 +		// starting a new rendering apparently
    3.60  		ctx->cur_rect = rect;
    3.61  		ctx->cur_pixel_x = x;
    3.62  		ctx->cur_pixel_y = y;
    3.63 +		ctx->cur_sample = 0;
    3.64  	}
    3.65  
    3.66  	ctx->scn->update();
    3.67  
    3.68 +	int max_samples = ctx->options[ERB_OPT_MAX_SAMPLES].x;
    3.69 +
    3.70  	if(timeout > 0) {
    3.71  		auto start_time = steady_clock::now();
    3.72  		while(duration_cast<milliseconds>(steady_clock::now() - start_time).count() < timeout) {
    3.73 -			render_pixel(ctx, ctx->cur_pixel_x, ctx->cur_pixel_y);
    3.74 +			render_pixel(ctx, ctx->cur_pixel_x, ctx->cur_pixel_y, ctx->cur_sample);
    3.75  
    3.76  			if(++ctx->cur_pixel_x >= ctx->cur_rect.width) {
    3.77 +				ctx->cur_pixel_x = ctx->cur_rect.x;
    3.78  				if(++ctx->cur_pixel_y >= ctx->cur_rect.height) {
    3.79 -					ctx->cur_rect = INVALID_RECT;
    3.80 -					return 0;
    3.81 +					ctx->cur_pixel_y = ctx->cur_rect.y;
    3.82 +					if(++ctx->cur_sample >= max_samples) {
    3.83 +						ctx->cur_rect = INVALID_RECT;
    3.84 +						return 0;
    3.85 +					}
    3.86  				}
    3.87  			}
    3.88  		}
    3.89  		return 1;
    3.90  	}
    3.91  
    3.92 +	if(ctx->options[ERB_OPT_MAX_SAMPLES].x == (float)INF_SAMPLES) {
    3.93 +		max_samples = 128;
    3.94 +	}
    3.95 +
    3.96  	for(int i=0; i<height; i++) {
    3.97  		for(int j=0; j<width; j++) {
    3.98 -			render_pixel(ctx, j, i);
    3.99 +			for(int k=0; k<max_samples; k++) {
   3.100 +				render_pixel(ctx, j, i, k);
   3.101 +			}
   3.102  		}
   3.103  	}
   3.104  	return 0;
   3.105 @@ -155,11 +177,28 @@
   3.106  
   3.107  	// XXX for now just create a test scene here
   3.108  	Sphere *sph = new Sphere;
   3.109 +	sph->mtl.set_attrib("albedo", Color(1.0, 0.3, 0.2));
   3.110  	SceneNode *sph_node = new SceneNode(sph);
   3.111  	ctx->scn->add_object(sph);
   3.112  	ctx->scn->add_node(sph_node);
   3.113  
   3.114 -	TargetCamera *cam = new TargetCamera(Vector3(0, 0, -10), Vector3(0, 0, 0));
   3.115 +	sph = new Sphere;
   3.116 +	sph->mtl.set_attrib("albedo", Color(0.3, 0.4, 1.0));
   3.117 +	sph_node = new SceneNode(sph);
   3.118 +	sph_node->set_position(Vector3(0, -3.0, 0));
   3.119 +	//sph_node->set_scaling(Vector3(4.0, 4.0, 4.0) * 0.3);
   3.120 +	ctx->scn->add_object(sph);
   3.121 +	ctx->scn->add_node(sph_node);
   3.122 +
   3.123 +	Sphere *lt = new Sphere;
   3.124 +	lt->mtl.set_attrib("emissive", Color(10, 10, 10));
   3.125 +	SceneNode *lt_node = new SceneNode(lt);
   3.126 +	lt_node->set_position(Vector3(-15, 15, -10));
   3.127 +	lt_node->set_scaling(Vector3(5, 5, 5));
   3.128 +	ctx->scn->add_object(lt);
   3.129 +	ctx->scn->add_node(lt_node);
   3.130 +
   3.131 +	TargetCamera *cam = new TargetCamera(Vector3(0, 4, -8), Vector3(0, 0, 0));
   3.132  	//ctx->scn->add_object(cam);
   3.133  	ctx->scn->use_camera(cam);
   3.134  
   3.135 @@ -174,20 +213,28 @@
   3.136  	return unirnd(rnd_gen);
   3.137  }
   3.138  
   3.139 -static void render_pixel(struct erebus *ctx, int x, int y)
   3.140 +static void render_pixel(struct erebus *ctx, int x, int y, int sample)
   3.141  {
   3.142  	Camera *cam = ctx->scn->get_active_camera();
   3.143  	if(!cam) return;
   3.144  
   3.145  	int xsz = ctx->fbimg.get_width();
   3.146  	int ysz = ctx->fbimg.get_height();
   3.147 -	float *pix = ctx->fbimg.get_pixels() + (y * xsz + x) * 4;
   3.148 +	int offs = (y * xsz + x) * 4;
   3.149  
   3.150 -	Ray ray = cam->get_primary_ray(x, y, xsz, ysz, 0);
   3.151 -	//Color c = ray_trace(ray, ctx->scn, 0);
   3.152 -	Color c = ray.dir.normalized() * 0.5 + Vector3(0.5, 0.5, 0.5);
   3.153 -	pix[0] = 1.0;//c.x;
   3.154 -	pix[1] = c.y;
   3.155 -	pix[2] = c.z;
   3.156 -	pix[3] = c.w;
   3.157 +	float *pix = ctx->fbimg.get_pixels() + offs;
   3.158 +	float *accum = ctx->accum.get_pixels() + offs;
   3.159 +
   3.160 +	Ray ray = cam->get_primary_ray(x, y, xsz, ysz, sample);
   3.161 +	Color c = ray_trace(ray, ctx->scn, 0);
   3.162 +	accum[0] += c.x;
   3.163 +	accum[1] += c.y;
   3.164 +	accum[2] += c.z;
   3.165 +	accum[3] += c.w;
   3.166 +
   3.167 +	float inv_samples = 1.0f / (float)(sample + 1);
   3.168 +	pix[0] = accum[0] * inv_samples;
   3.169 +	pix[1] = accum[1] * inv_samples;
   3.170 +	pix[2] = accum[2] * inv_samples;
   3.171 +	pix[3] = accum[3] * inv_samples;
   3.172  }
     4.1 --- a/liberebus/src/erebus.h	Sat May 24 02:27:08 2014 +0300
     4.2 +++ b/liberebus/src/erebus.h	Sat May 24 06:12:57 2014 +0300
     4.3 @@ -7,6 +7,7 @@
     4.4  	ERB_OPT_WIDTH,
     4.5  	ERB_OPT_HEIGHT,
     4.6  	ERB_OPT_MAX_ITER,
     4.7 +	ERB_OPT_MAX_SAMPLES,
     4.8  	ERB_OPT_NUM_THREADS,
     4.9  	ERB_OPT_GAMMA,
    4.10  
     5.1 --- a/liberebus/src/geomobj.cc	Sat May 24 02:27:08 2014 +0300
     5.2 +++ b/liberebus/src/geomobj.cc	Sat May 24 06:12:57 2014 +0300
     5.3 @@ -18,6 +18,22 @@
     5.4  	return false;
     5.5  }
     5.6  
     5.7 +Vector3 GeomObject::calc_normal(const RayHit &hit) const
     5.8 +{
     5.9 +	// when you look at singularities, the singularities always look back at you :)
    5.10 +	return -(hit.world_ray.dir).normalized();
    5.11 +}
    5.12 +
    5.13 +Vector3 GeomObject::calc_tangent(const RayHit &hit) const
    5.14 +{
    5.15 +	return Vector3(1, 0, 0);	// whatever...
    5.16 +}
    5.17 +
    5.18 +Vector2 GeomObject::calc_texcoords(const RayHit &hit) const
    5.19 +{
    5.20 +	return Vector2();
    5.21 +}
    5.22 +
    5.23  // --- class Sphere ---
    5.24  
    5.25  bool Sphere::intersect(const Ray &ray, RayHit *hit) const
    5.26 @@ -47,6 +63,40 @@
    5.27  	return true;
    5.28  }
    5.29  
    5.30 +Vector3 Sphere::calc_normal(const RayHit &hit) const
    5.31 +{
    5.32 +	Vector3 pt = hit.world_ray.origin + hit.world_ray.dir * hit.dist;
    5.33 +	return pt.normalized();
    5.34 +}
    5.35 +
    5.36 +static inline Vector3 sphvec(float u, float v)
    5.37 +{
    5.38 +	float theta = u * M_PI * 2.0;
    5.39 +	float phi = v * M_PI;
    5.40 +
    5.41 +	return Vector3(sin(theta) * sin(phi), cos(phi), cos(theta) * sin(phi));
    5.42 +}
    5.43 +
    5.44 +Vector3 Sphere::calc_tangent(const RayHit &hit) const
    5.45 +{
    5.46 +	Vector2 uv = calc_texcoords(hit);
    5.47 +	Vector3 pnext = sphvec(uv.x + 0.05, 0.5);
    5.48 +	Vector3 pprev = sphvec(uv.y - 0.05, 0.5);
    5.49 +	return (pnext - pprev).normalized();
    5.50 +}
    5.51 +
    5.52 +Vector2 Sphere::calc_texcoords(const RayHit &hit) const
    5.53 +{
    5.54 +	Vector3 pt = hit.world_ray.origin + hit.world_ray.dir * hit.dist;
    5.55 +	pt.normalize();
    5.56 +
    5.57 +	float theta = atan2(pt.z, pt.x);
    5.58 +	float phi = acos(pt.y);
    5.59 +
    5.60 +	return Vector2(theta / M_PI + 0.5, phi / M_PI);
    5.61 +}
    5.62 +
    5.63 +
    5.64  // --- class Box ---
    5.65  
    5.66  bool Box::intersect(const Ray &ray, RayHit *hit) const
     6.1 --- a/liberebus/src/geomobj.h	Sat May 24 02:27:08 2014 +0300
     6.2 +++ b/liberebus/src/geomobj.h	Sat May 24 06:12:57 2014 +0300
     6.3 @@ -16,11 +16,19 @@
     6.4  	ObjType get_type() const override;
     6.5  
     6.6  	bool intersect(const Ray &ray, RayHit *hit = 0) const override;
     6.7 +
     6.8 +	virtual Vector3 calc_normal(const RayHit &hit) const;
     6.9 +	virtual Vector3 calc_tangent(const RayHit &hit) const;
    6.10 +	virtual Vector2 calc_texcoords(const RayHit &hit) const;
    6.11  };
    6.12  
    6.13  class Sphere : public GeomObject {
    6.14  public:
    6.15  	bool intersect(const Ray &ray, RayHit *hit = 0) const override;
    6.16 +
    6.17 +	Vector3 calc_normal(const RayHit &hit) const override;
    6.18 +	Vector3 calc_tangent(const RayHit &hit) const override;
    6.19 +	Vector2 calc_texcoords(const RayHit &hit) const override;
    6.20  };
    6.21  
    6.22  class Box : public GeomObject {
     7.1 --- a/liberebus/src/material.cc	Sat May 24 02:27:08 2014 +0300
     7.2 +++ b/liberebus/src/material.cc	Sat May 24 06:12:57 2014 +0300
     7.3 @@ -1,7 +1,7 @@
     7.4  #include "material.h"
     7.5  
     7.6  MatAttrib::MatAttrib()
     7.7 -	: value(1), color(1, 1, 1), map(0)
     7.8 +	: value(0), color(0, 0, 0), map(0)
     7.9  {
    7.10  }
    7.11  
     8.1 --- a/liberebus/src/rt.cc	Sat May 24 02:27:08 2014 +0300
     8.2 +++ b/liberebus/src/rt.cc	Sat May 24 06:12:57 2014 +0300
     8.3 @@ -1,16 +1,41 @@
     8.4 +#include <assert.h>
     8.5  #include "rt.h"
     8.6 +#include "erebus_impl.h"
     8.7 +
     8.8 +#define MAX_ITER	8
     8.9  
    8.10  Color ray_trace(const Ray &ray, const Scene *scn, int iter)
    8.11  {
    8.12  	RayHit hit;
    8.13  	if(!(scn->intersect(ray, &hit))) {
    8.14 -		return Color(0, 0, 0, 0);
    8.15 +		return scn->get_env_color(ray);
    8.16  	}
    8.17  
    8.18 -	return shade(hit, iter);
    8.19 +	return shade(hit, scn, iter);
    8.20  }
    8.21  
    8.22 -Color shade(const RayHit &hit, int iter)
    8.23 +Color shade(const RayHit &hit, const Scene *scn, int iter)
    8.24  {
    8.25 -	return Color(1, 0, 0, 1);
    8.26 +	assert(hit.obj->get_type() == ObjType::geom);
    8.27 +	const GeomObject *obj = (const GeomObject*)hit.obj;
    8.28 +	const Material *mtl = &obj->mtl;
    8.29 +	const Reflectance *brdf = obj->brdf;
    8.30 +	const Ray &ray = hit.world_ray;
    8.31 +
    8.32 +	Vector3 norm = obj->calc_normal(hit);
    8.33 +	Vector2 texcoords = obj->calc_texcoords(hit);
    8.34 +
    8.35 +	Color color = mtl->get_attrib_color("albedo", texcoords.x, texcoords.y);
    8.36 +	Color res = mtl->get_attrib_color("emissive") + color * scn->get_env().ambient;
    8.37 +
    8.38 +	Vector3 sample_dir;
    8.39 +	float prob = brdf->sample(norm, -hit.world_ray.dir, &sample_dir);
    8.40 +	if(iter < MAX_ITER && randf() <= prob) {
    8.41 +		Ray sample_ray;
    8.42 +		sample_ray.origin = ray.origin + ray.dir * hit.dist;
    8.43 +		sample_ray.dir = sample_dir;
    8.44 +
    8.45 +		res += ray_trace(sample_ray, scn, iter + 1) * color;
    8.46 +	}
    8.47 +	return res;
    8.48  }
     9.1 --- a/liberebus/src/rt.h	Sat May 24 02:27:08 2014 +0300
     9.2 +++ b/liberebus/src/rt.h	Sat May 24 06:12:57 2014 +0300
     9.3 @@ -6,6 +6,6 @@
     9.4  #include "scene.h"
     9.5  
     9.6  Color ray_trace(const Ray &ray, const Scene *scn, int iter);
     9.7 -Color shade(const RayHit &hit, int iter);
     9.8 +Color shade(const RayHit &hit, const Scene *scn, int iter);
     9.9  
    9.10  #endif	// RT_H_
    10.1 --- a/liberebus/src/scene.cc	Sat May 24 02:27:08 2014 +0300
    10.2 +++ b/liberebus/src/scene.cc	Sat May 24 06:12:57 2014 +0300
    10.3 @@ -1,5 +1,11 @@
    10.4  #include "scene.h"
    10.5  
    10.6 +// default enviromental parameters
    10.7 +Environment::Environment()
    10.8 +	: bgcolor(0.05, 0.05, 0.05), ambient(0.05, 0.05, 0.05)
    10.9 +{
   10.10 +}
   10.11 +
   10.12  Scene::Scene()
   10.13  {
   10.14  	active_cam = 0;
   10.15 @@ -17,6 +23,32 @@
   10.16  	delete root;
   10.17  }
   10.18  
   10.19 +void Scene::set_env(const Environment &env)
   10.20 +{
   10.21 +	this->env = env;
   10.22 +}
   10.23 +
   10.24 +Environment &Scene::get_env()
   10.25 +{
   10.26 +	return env;
   10.27 +}
   10.28 +
   10.29 +const Environment &Scene::get_env() const
   10.30 +{
   10.31 +	return env;
   10.32 +}
   10.33 +
   10.34 +Color Scene::get_env_color() const
   10.35 +{
   10.36 +	return env.bgcolor;
   10.37 +}
   10.38 +
   10.39 +Color Scene::get_env_color(const Ray &ray) const
   10.40 +{
   10.41 +	// TODO
   10.42 +	return get_env_color();
   10.43 +}
   10.44 +
   10.45  void Scene::add_object(Object *obj)
   10.46  {
   10.47  	objects.push_back(obj);
    11.1 --- a/liberebus/src/scene.h	Sat May 24 02:27:08 2014 +0300
    11.2 +++ b/liberebus/src/scene.h	Sat May 24 06:12:57 2014 +0300
    11.3 @@ -4,9 +4,20 @@
    11.4  #include <vector>
    11.5  #include "snode.h"
    11.6  #include "camera.h"
    11.7 +#include "color.h"
    11.8 +
    11.9 +struct Environment {
   11.10 +	Color bgcolor;
   11.11 +	Color ambient;
   11.12 +	// TODO map & image-based lighting
   11.13 +
   11.14 +	Environment();
   11.15 +};
   11.16  
   11.17  class Scene {
   11.18  private:
   11.19 +	Environment env;
   11.20 +
   11.21  	std::vector<Object*> objects;
   11.22  	std::vector<SceneNode*> nodes;
   11.23  
   11.24 @@ -18,6 +29,13 @@
   11.25  	Scene();
   11.26  	~Scene();
   11.27  
   11.28 +	void set_env(const Environment &env);
   11.29 +	Environment &get_env();
   11.30 +	const Environment &get_env() const;
   11.31 +
   11.32 +	Color get_env_color() const;
   11.33 +	Color get_env_color(const Ray &ray) const;
   11.34 +
   11.35  	void add_object(Object *obj);
   11.36  	int get_object_count() const;
   11.37  	Object *get_object(int idx) const;
    12.1 --- a/liberebus/src/snode.cc	Sat May 24 02:27:08 2014 +0300
    12.2 +++ b/liberebus/src/snode.cc	Sat May 24 06:12:57 2014 +0300
    12.3 @@ -158,6 +158,15 @@
    12.4  		}
    12.5  	}
    12.6  
    12.7 +	for(size_t i=0; i<children.size(); i++) {
    12.8 +		if(children[i]->intersect(ray, hit)) {
    12.9 +			if(!hit) return true;
   12.10 +			if(hit->dist < nearest.dist) {
   12.11 +				nearest = *hit;
   12.12 +			}
   12.13 +		}
   12.14 +	}
   12.15 +
   12.16  	if(nearest.dist < FLT_MAX) {
   12.17  		*hit = nearest;
   12.18  		hit->local_ray = local_ray;
    13.1 --- a/src/main.cc	Sat May 24 02:27:08 2014 +0300
    13.2 +++ b/src/main.cc	Sat May 24 06:12:57 2014 +0300
    13.3 @@ -44,8 +44,8 @@
    13.4  
    13.5  static bool init()
    13.6  {
    13.7 -	width = glutGet(GLUT_WINDOW_WIDTH);
    13.8 -	height = glutGet(GLUT_WINDOW_HEIGHT);
    13.9 +	width = glutGet(GLUT_WINDOW_WIDTH) / 2;
   13.10 +	height = glutGet(GLUT_WINDOW_HEIGHT) / 2;
   13.11  
   13.12  	if(!(erb = erb_init())) {
   13.13  		return false;
   13.14 @@ -62,6 +62,7 @@
   13.15  	glutIdleFunc(idle);
   13.16  	erb_begin_frame(erb, 0);
   13.17  
   13.18 +	glEnable(GL_TEXTURE_2D);
   13.19  	return true;
   13.20  }
   13.21  
   13.22 @@ -74,14 +75,14 @@
   13.23  {
   13.24  	static unsigned char *defpix;
   13.25  
   13.26 -	width = xsz;
   13.27 -	height = ysz;
   13.28 +	width = xsz / 2;
   13.29 +	height = ysz / 2;
   13.30  
   13.31 -	if(xsz <= rtex_width && ysz <= rtex_height) {
   13.32 +	if(width <= rtex_width && height <= rtex_height) {
   13.33  		return;
   13.34  	}
   13.35 -	rtex_width = next_pow2(xsz);
   13.36 -	rtex_height = next_pow2(ysz);
   13.37 +	rtex_width = next_pow2(width);
   13.38 +	rtex_height = next_pow2(height);
   13.39  
   13.40  	printf("resizing framebuffer texture: %dx%d\n", rtex_width, rtex_height);
   13.41  
   13.42 @@ -125,16 +126,13 @@
   13.43  static void display()
   13.44  {
   13.45  	if(render_pending) {
   13.46 -		if(erb_render(erb, 128) == 0) {
   13.47 +		if(erb_render(erb, 64) == 0) {
   13.48  			render_pending = false;
   13.49  			glutIdleFunc(0);
   13.50  		}
   13.51  		update_rect(0, 0, width, height, erb_get_framebuffer(erb));
   13.52  	}
   13.53  
   13.54 -	glBindTexture(GL_TEXTURE_2D, rtex);
   13.55 -	glEnable(GL_TEXTURE_2D);
   13.56 -
   13.57  	float maxu = (float)width / (float)rtex_width;
   13.58  	float maxv = (float)height / (float)rtex_height;
   13.59  
   13.60 @@ -145,8 +143,6 @@
   13.61  	glTexCoord2f(0, 0); glVertex2f(-1, 1);
   13.62  	glEnd();
   13.63  
   13.64 -	glDisable(GL_TEXTURE_2D);
   13.65 -
   13.66  	glutSwapBuffers();
   13.67  	assert(glGetError() == GL_NO_ERROR);
   13.68  }