rev |
line source |
nuclear@8
|
1 #include <assert.h>
|
nuclear@6
|
2 #include "rt.h"
|
nuclear@8
|
3 #include "erebus_impl.h"
|
nuclear@8
|
4
|
nuclear@28
|
5 #define MAX_ITER 6
|
nuclear@6
|
6
|
nuclear@17
|
7 Color ray_trace(struct erebus *ctx, const Ray &ray, int iter)
|
nuclear@6
|
8 {
|
nuclear@17
|
9 const Scene *scn = ctx->scn;
|
nuclear@17
|
10 if(!scn) {
|
nuclear@17
|
11 return Color(1, 0, 0);
|
nuclear@17
|
12 }
|
nuclear@17
|
13
|
nuclear@6
|
14 RayHit hit;
|
nuclear@6
|
15 if(!(scn->intersect(ray, &hit))) {
|
nuclear@8
|
16 return scn->get_env_color(ray);
|
nuclear@6
|
17 }
|
nuclear@6
|
18
|
nuclear@17
|
19 return shade(ctx, hit, iter);
|
nuclear@6
|
20 }
|
nuclear@6
|
21
|
nuclear@17
|
22 Color shade(struct erebus *ctx, const RayHit &hit, int iter)
|
nuclear@6
|
23 {
|
nuclear@8
|
24 assert(hit.obj->get_type() == ObjType::geom);
|
nuclear@17
|
25 int max_iter = erb_getopti(ctx, ERB_OPT_MAX_ITER);
|
nuclear@17
|
26 const Scene *scn = ctx->scn;
|
nuclear@8
|
27 const GeomObject *obj = (const GeomObject*)hit.obj;
|
nuclear@8
|
28 const Material *mtl = &obj->mtl;
|
nuclear@8
|
29 const Reflectance *brdf = obj->brdf;
|
nuclear@8
|
30 const Ray &ray = hit.world_ray;
|
nuclear@26
|
31 //bool entering = true;
|
nuclear@8
|
32
|
nuclear@17
|
33 Vector3 norm = hit.calc_normal();
|
nuclear@23
|
34 if(dot_product(ray.dir, norm) > 0.0) {
|
nuclear@26
|
35 //entering = false;
|
nuclear@23
|
36 norm = -norm;
|
nuclear@23
|
37 }
|
nuclear@23
|
38
|
nuclear@18
|
39 //return norm * 0.5 + Vector3(0.5, 0.5, 0.5);
|
nuclear@17
|
40 Vector2 texcoords = hit.calc_texcoords();
|
nuclear@8
|
41
|
nuclear@17
|
42 Color color = mtl->get_attrib_color("diffuse", texcoords.x, texcoords.y);
|
nuclear@28
|
43 Color specular = mtl->get_attrib_color("specular", texcoords.x, texcoords.y);
|
nuclear@28
|
44 Color res = mtl->get_attrib_color("emissive", texcoords.x, texcoords.y) +
|
nuclear@28
|
45 color * scn->get_env().ambient;
|
nuclear@28
|
46 float shininess = mtl->get_attrib_value("shininess");
|
nuclear@8
|
47
|
nuclear@8
|
48 Vector3 sample_dir;
|
nuclear@31
|
49 float prob = brdf->sample(SurfaceGeometry(norm), -hit.world_ray.dir, &sample_dir);
|
nuclear@28
|
50 if(iter < max_iter && randf() <= prob && ray.energy * prob > 0.001) {
|
nuclear@8
|
51 Ray sample_ray;
|
nuclear@8
|
52 sample_ray.origin = ray.origin + ray.dir * hit.dist;
|
nuclear@8
|
53 sample_ray.dir = sample_dir;
|
nuclear@28
|
54 sample_ray.energy = ray.energy * prob;
|
nuclear@8
|
55
|
nuclear@17
|
56 res += ray_trace(ctx, sample_ray, iter + 1) * color;
|
nuclear@8
|
57 }
|
nuclear@29
|
58
|
nuclear@29
|
59 res.w = 1.0;
|
nuclear@8
|
60 return res;
|
nuclear@6
|
61 }
|