# HG changeset patch # User John Tsiombikas # Date 1402054780 -10800 # Node ID 4a0a288ffb278110448f652591ad131f0f692ace # Parent 0ced900e15a76a57c3afb4d40b5427b1c18fed2e phong/lafortune BRDF diff -r 0ced900e15a7 -r 4a0a288ffb27 liberebus/src/brdf.cc --- a/liberebus/src/brdf.cc Mon Jun 02 00:53:01 2014 +0300 +++ b/liberebus/src/brdf.cc Fri Jun 06 14:39:40 2014 +0300 @@ -130,3 +130,45 @@ { return 1.0f; } + +// --- class PhongRefl --- +PhongRefl::PhongRefl() +{ + shininess = 42.0; +} + +Vector3 PhongRefl::sample_dir(const Vector3 &norm, const Vector3 &outdir) const +{ + // construct orthonormal basis with k being the reflection dir + Vector3 refl = outdir.reflection(norm).normalized(); + Vector3 up = Vector3(0, 0, 1); + if(fabs(dot_product(refl, up)) - 1.0 < 0.001) { + up = Vector3(0, 1, 0); + } + Vector3 right = cross_product(up, refl); + up = cross_product(refl, right); + + // construct the matrix transposed to move the sample from reflection + // space to world space + Matrix3x3 xform; + xform.set_column_vector(right, 0); + xform.set_column_vector(up, 1); + xform.set_column_vector(refl, 2); + + float phi = acos(pow(randf(), 1.0 / (shininess + 1))); + float theta = 2.0 * M_PI * randf(); + + Vector3 v; + v.x = cos(theta) * sin(phi); + v.y = sin(theta) * sin(phi); + v.z = cos(phi); + v.transform(xform); + return v; +} + +float PhongRefl::eval(const Vector3 &norm, const Vector3 &outdir, const Vector3 &indir) const +{ + Vector3 refl = outdir.reflection(norm); + float dot = std::max(dot_product(indir, refl), 0.0f); + return pow(dot, shininess); +} diff -r 0ced900e15a7 -r 4a0a288ffb27 liberebus/src/brdf.h --- a/liberebus/src/brdf.h Mon Jun 02 00:53:01 2014 +0300 +++ b/liberebus/src/brdf.h Fri Jun 06 14:39:40 2014 +0300 @@ -53,4 +53,14 @@ float eval(const Vector3 &norm, const Vector3 &outdir, const Vector3 &indir) const override; }; +class PhongRefl : public Reflectance { +public: + float shininess; + + PhongRefl(); + + Vector3 sample_dir(const Vector3 &norm, const Vector3 &outdir) const override; + float eval(const Vector3 &norm, const Vector3 &outdir, const Vector3 &indir) const override; +}; + #endif // BRDF_H_ diff -r 0ced900e15a7 -r 4a0a288ffb27 liberebus/src/rt.cc --- a/liberebus/src/rt.cc Mon Jun 02 00:53:01 2014 +0300 +++ b/liberebus/src/rt.cc Fri Jun 06 14:39:40 2014 +0300 @@ -2,7 +2,7 @@ #include "rt.h" #include "erebus_impl.h" -#define MAX_ITER 8 +#define MAX_ITER 6 Color ray_trace(struct erebus *ctx, const Ray &ray, int iter) { @@ -40,14 +40,18 @@ Vector2 texcoords = hit.calc_texcoords(); Color color = mtl->get_attrib_color("diffuse", texcoords.x, texcoords.y); - Color res = mtl->get_attrib_color("emissive") + color * scn->get_env().ambient; + Color specular = mtl->get_attrib_color("specular", texcoords.x, texcoords.y); + Color res = mtl->get_attrib_color("emissive", texcoords.x, texcoords.y) + + color * scn->get_env().ambient; + float shininess = mtl->get_attrib_value("shininess"); Vector3 sample_dir; float prob = brdf->sample(norm, -hit.world_ray.dir, &sample_dir); - if(iter < max_iter && randf() <= prob) { + if(iter < max_iter && randf() <= prob && ray.energy * prob > 0.001) { Ray sample_ray; sample_ray.origin = ray.origin + ray.dir * hit.dist; sample_ray.dir = sample_dir; + sample_ray.energy = ray.energy * prob; res += ray_trace(ctx, sample_ray, iter + 1) * color; } diff -r 0ced900e15a7 -r 4a0a288ffb27 liberebus/src/scene.cc --- a/liberebus/src/scene.cc Mon Jun 02 00:53:01 2014 +0300 +++ b/liberebus/src/scene.cc Fri Jun 06 14:39:40 2014 +0300 @@ -140,9 +140,22 @@ bool Scene::load(FILE *fp) { - static char buf[256]; + static char buf[4096]; + int offset = 0; - while(fgets(buf, sizeof buf, fp)) { + while(fgets(buf + offset, sizeof buf - offset, fp)) { + // handle line continuations + int len = strlen(buf); + if(strcmp(buf + len - 2, "\\\n") == 0 || strcmp(buf + len - 2, "\\\r") == 0) { + offset = len - 2; + continue; + } + if(strcmp(buf + len - 3, "\\\r\n") == 0) { + offset = len - 3; + continue; + } + offset = 0; + char *line = strip_wspace(buf); if(!line || !*line || *line == '#') { continue; @@ -198,6 +211,13 @@ brdf = new LambertRefl; if(!composite) break; + } else if(strcmp(argv[i], "phong") == 0) { + if(composite && brdf) { + composite->add_brdf(brdf, weight); + } + brdf = new PhongRefl; + if(!composite) break; + } else if(strcmp(argv[i], "mirror") == 0) { if(composite && brdf) { composite->add_brdf(brdf, weight); diff -r 0ced900e15a7 -r 4a0a288ffb27 test/scene --- a/test/scene Mon Jun 02 00:53:01 2014 +0300 +++ b/test/scene Fri Jun 06 14:39:40 2014 +0300 @@ -1,8 +1,12 @@ # test scene -sphere -position 0 0 0 -scaling 1 1 1 -diffuse 1 0.6 0.5 +sphere -position 0 0 0 -scaling 1 1 1 -diffuse 1 0.6 0.5 -brdf composite \ + -brdf lambert -brdf-weight 0.5 \ + -brdf phong -brdf-weight 0.5 -box -position 0 -1.25 0 -scaling 4 0.5 4 -diffuse 0.3 0.4 1.0 -brdf composite -brdf lambert -brdf-weight 0.3 -brdf mirror -brdf-weight 0.7 +box -position 0 -1.25 0 -scaling 4 0.5 4 -diffuse 0.3 0.4 1.0 -brdf composite \ + -brdf lambert -brdf-weight 0.3 \ + -brdf mirror -brdf-weight 0.7 box -position 0 3.75 0 -scaling 20 10 20 -diffuse 1.0 1.0 1.0 -brdf lambert box -position 0 4 0 -scaling 3 0.1 3 -emissive 6 6 6