nuclear@8: #include nuclear@6: #include "rt.h" nuclear@8: #include "erebus_impl.h" nuclear@8: nuclear@28: #define MAX_ITER 6 nuclear@6: nuclear@17: Color ray_trace(struct erebus *ctx, const Ray &ray, int iter) nuclear@6: { nuclear@17: const Scene *scn = ctx->scn; nuclear@17: if(!scn) { nuclear@17: return Color(1, 0, 0); nuclear@17: } nuclear@17: nuclear@6: RayHit hit; nuclear@6: if(!(scn->intersect(ray, &hit))) { nuclear@8: return scn->get_env_color(ray); nuclear@6: } nuclear@6: nuclear@17: return shade(ctx, hit, iter); nuclear@6: } nuclear@6: nuclear@17: Color shade(struct erebus *ctx, const RayHit &hit, int iter) nuclear@6: { nuclear@8: assert(hit.obj->get_type() == ObjType::geom); nuclear@17: int max_iter = erb_getopti(ctx, ERB_OPT_MAX_ITER); nuclear@17: const Scene *scn = ctx->scn; nuclear@8: const GeomObject *obj = (const GeomObject*)hit.obj; nuclear@8: const Material *mtl = &obj->mtl; nuclear@8: const Reflectance *brdf = obj->brdf; nuclear@8: const Ray &ray = hit.world_ray; nuclear@26: //bool entering = true; nuclear@8: nuclear@17: Vector3 norm = hit.calc_normal(); nuclear@23: if(dot_product(ray.dir, norm) > 0.0) { nuclear@26: //entering = false; nuclear@23: norm = -norm; nuclear@23: } nuclear@23: nuclear@18: //return norm * 0.5 + Vector3(0.5, 0.5, 0.5); nuclear@17: Vector2 texcoords = hit.calc_texcoords(); nuclear@8: nuclear@17: Color color = mtl->get_attrib_color("diffuse", texcoords.x, texcoords.y); nuclear@28: Color specular = mtl->get_attrib_color("specular", texcoords.x, texcoords.y); nuclear@28: Color res = mtl->get_attrib_color("emissive", texcoords.x, texcoords.y) + nuclear@28: color * scn->get_env().ambient; nuclear@28: float shininess = mtl->get_attrib_value("shininess"); nuclear@8: nuclear@8: Vector3 sample_dir; nuclear@31: float prob = brdf->sample(SurfaceGeometry(norm), -hit.world_ray.dir, &sample_dir); nuclear@28: if(iter < max_iter && randf() <= prob && ray.energy * prob > 0.001) { nuclear@8: Ray sample_ray; nuclear@8: sample_ray.origin = ray.origin + ray.dir * hit.dist; nuclear@8: sample_ray.dir = sample_dir; nuclear@28: sample_ray.energy = ray.energy * prob; nuclear@8: nuclear@17: res += ray_trace(ctx, sample_ray, iter + 1) * color; nuclear@8: } nuclear@29: nuclear@29: res.w = 1.0; nuclear@8: return res; nuclear@6: }