erebus

view liberebus/src/rt.cc @ 44:a2afaf8af09b

helpful comment
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 18 Sep 2015 06:47:41 +0300
parents 5e27c85e79ca
children c4d48a21bc4a
line source
1 #include <assert.h>
2 #include "rt.h"
3 #include "erebus_impl.h"
5 Color ray_trace(struct erebus *ctx, const Ray &ray, int iter)
6 {
7 const Scene *scn = ctx->scn;
8 if(!scn) {
9 return Color(1, 0, 0);
10 }
12 if(iter > erb_getopti(ctx, ERB_OPT_MAX_ITER) || ray.energy < 0.0001) {
13 //return Color(1, 0, 1);
14 return Color(0, 0, 0);
15 }
17 RayHit hit;
18 if(!(scn->intersect(ray, &hit))) {
19 return scn->get_env_color(ray);
20 }
22 return shade(ctx, hit, iter);
23 }
25 Color shade(struct erebus *ctx, const RayHit &hit, int iter)
26 {
27 assert(hit.obj->get_type() == ObjType::geom);
28 const Scene *scn = ctx->scn;
29 const GeomObject *obj = (const GeomObject*)hit.obj;
30 const Material *mtl = &obj->mtl;
31 const Reflectance *brdf = obj->brdf;
32 const Ray &ray = hit.world_ray;
33 //bool entering = true;
35 Vector3 pos = ray.origin + ray.dir * hit.dist;
37 Vector3 norm = hit.calc_normal();
38 if(dot_product(ray.dir, norm) > 0.0) {
39 //entering = false;
40 norm = -norm;
41 }
43 //return norm * 0.5 + Vector3(0.5, 0.5, 0.5);
44 Vector2 texcoords = hit.calc_texcoords();
46 Color color = mtl->get_attrib_color("diffuse", texcoords.x, texcoords.y);
47 Color specular = mtl->get_attrib_color("specular", texcoords.x, texcoords.y);
48 Color res = color * scn->get_env().ambient;
49 float shininess = mtl->get_attrib_value("shininess");
51 res += mtl->get_attrib_color("emissive", texcoords.x, texcoords.y);
53 /*
54 // calculate direct illumination
55 Vector3 vdir = -ray.dir.normalized();
56 std::list<ObjectInstance> lights = scn->gen_light_list();
57 auto it = lights.cbegin();
58 while(it != lights.cend()) {
59 const ObjectInstance &inst = *it++;
60 GeomObject *light = (GeomObject*)inst.obj;
61 SceneNode *light_node = inst.node;
63 if(obj == light) {
64 // don't try to get illumination from ourselves
65 continue;
66 }
68 const Matrix4x4 &xform = light_node->get_matrix();
69 const Matrix4x4 &inv_xform = light_node->get_inv_matrix();
70 Vector3 spt = light->gen_surface_point().transformed(xform);
72 Vector3 ldir = spt - pos;
73 if(dot_product(ldir, norm) < 0.0) {
74 continue;
75 }
76 Ray shadow_ray{pos, ldir};
78 RayHit shadow_hit;
79 shadow_hit.obj = 0;
80 if(scn->intersect(shadow_ray, &shadow_hit) && shadow_hit.obj != light &&
81 shadow_hit.dist < 0.99999 && shadow_hit.dist > 1e-5) {
82 // we're in shadow, skip
83 continue;
84 }
86 if(!shadow_hit.obj) {
87 shadow_hit.obj = light;
88 shadow_hit.dist = 1.0;
89 shadow_hit.world_ray = shadow_ray;
90 shadow_hit.local_ray = shadow_ray.transformed(inv_xform);
91 shadow_hit.node = inst.node;
92 }
94 Vector2 tc = shadow_hit.calc_texcoords();
95 Color lcol = light->mtl.get_attrib_color("emissive", tc.x, tc.y);
97 ldir.normalize();
98 norm.normalize();
99 float ndotl = dot_product(ldir, norm);
101 Vector3 refl = ldir.reflection(norm);
102 float vdotr = dot_product(vdir, refl);
104 Color direct = ray.energy * lcol * (color * ndotl);// + specular * pow(vdotr, shininess));
105 assert(direct.x >= 0.0 && direct.y >= 0.0 && direct.z >= 0.0);
106 res += direct;
107 }
108 */
110 Vector3 sample_dir;
111 float prob = brdf->sample(SurfaceGeometry(norm), -ray.dir, &sample_dir);
112 if(randf() <= prob) {
113 Ray sample_ray;
114 sample_ray.origin = pos;
115 sample_ray.dir = sample_dir;
116 sample_ray.energy = ray.energy * prob;
118 res += ray_trace(ctx, sample_ray, iter + 1) * color;
119 }
121 res.w = 1.0;
122 return res;
123 }