From c9d300e72f336e5c22a06a76116b71cba24bbc9b Mon Sep 17 00:00:00 2001 From: Fabio Pellacini Date: Mon, 3 May 2021 16:32:13 +0200 Subject: [PATCH] updated --- libs/yocto/yocto_sampling.h | 21 +++++++++++ libs/yocto/yocto_trace.cpp | 74 +++++++++++++++++++++++++++++++++++++ libs/yocto/yocto_trace.h | 5 ++- 3 files changed, 98 insertions(+), 2 deletions(-) diff --git a/libs/yocto/yocto_sampling.h b/libs/yocto/yocto_sampling.h index 474c96553..d897c1ad4 100644 --- a/libs/yocto/yocto_sampling.h +++ b/libs/yocto/yocto_sampling.h @@ -124,6 +124,12 @@ inline vec3f sample_hemisphere_cospower(float exponent, const vec2f& ruv); inline float sample_hemisphere_cospower_pdf( float exponent, const vec3f& direction); +// Sample an hemispherical direction with cosine power distribution. +inline vec3f sample_hemisphere_cospower( + float exponent, const vec3f& normal, const vec2f& ruv); +inline float sample_hemisphere_cospower_pdf( + float exponent, const vec3f& normal, const vec3f& direction); + // Sample a point uniformly on a disk. inline vec2f sample_disk(const vec2f& ruv); inline float sample_disk_pdf(const vec2f& point); @@ -311,6 +317,21 @@ inline float sample_hemisphere_cospower_pdf( : pow(direction.z, exponent) * (exponent + 1) / (2 * pif); } +// Sample an hemispherical direction with cosine power distribution. +inline vec3f sample_hemisphere_cospower( + float exponent, const vec3f& normal, const vec2f& ruv) { + auto z = pow(ruv.y, 1 / (exponent + 1)); + auto r = sqrt(1 - z * z); + auto phi = 2 * pif * ruv.x; + auto local_direction = vec3f{r * cos(phi), r * sin(phi), z}; + return transform_direction(basis_fromz(normal), local_direction); +} +inline float sample_hemisphere_cospower_pdf( + float exponent, const vec3f& normal, const vec3f& direction) { + auto cosw = dot(normal, direction); + return (cosw <= 0) ? 0 : pow(cosw, exponent) * (exponent + 1) / (2 * pif); +} + // Sample a point uniformly on a disk. inline vec2f sample_disk(const vec2f& ruv) { auto r = sqrt(ruv.y); diff --git a/libs/yocto/yocto_trace.cpp b/libs/yocto/yocto_trace.cpp index 848e678da..c7fc5ebe0 100644 --- a/libs/yocto/yocto_trace.cpp +++ b/libs/yocto/yocto_trace.cpp @@ -1002,6 +1002,79 @@ static trace_result trace_eyelight(const scene_model& scene, return {radiance, hit, hit_albedo, hit_normal}; } +// Eyelight with ambient occlusion for quick previewing. +static trace_result trace_eyelightao(const scene_model& scene, + const bvh_scene& bvh, const trace_lights& lights, const ray3f& ray_, + rng_state& rng, const trace_params& params) { + // initialize + auto radiance = zero3f; + auto weight = vec3f{1, 1, 1}; + auto ray = ray_; + auto hit = false; + auto hit_albedo = vec3f{0, 0, 0}; + auto hit_normal = vec3f{0, 0, 0}; + auto opbounce = 0; + + // trace path + for (auto bounce = 0; bounce < max(params.bounces, 4); bounce++) { + // intersect next point + auto intersection = intersect_bvh(bvh, scene, ray); + if (!intersection.hit) { + if (bounce > 0 || !params.envhidden) + radiance += weight * eval_environment(scene, ray.d); + break; + } + + // prepare shading point + auto outgoing = -ray.d; + auto instance = scene.instances[intersection.instance]; + auto element = intersection.element; + auto uv = intersection.uv; + auto position = eval_position(scene, instance, element, uv); + auto normal = eval_shading_normal(scene, instance, element, uv, outgoing); + auto material = eval_material(scene, instance, element, uv); + + // handle opacity + if (material.opacity < 1 && rand1f(rng) >= material.opacity) { + if (opbounce++ > 128) break; + ray = {position + ray.d * 1e-2f, ray.d}; + bounce -= 1; + continue; + } + + // set hit variables + if (bounce == 0) { + hit = true; + hit_albedo = material.color; + hit_normal = normal; + } + + // accumulate emission + auto incoming = outgoing; + radiance += weight * eval_emission(material, normal, outgoing); + + // occlusion + auto occluding = sample_hemisphere_cos(normal, rand2f(rng)); + if (intersect_bvh(bvh, scene, {position, occluding}).hit) break; + + // brdf * light + radiance += weight * pif * + eval_bsdfcos(material, normal, outgoing, incoming); + + // continue path + if (!is_delta(material)) break; + incoming = sample_delta(material, normal, outgoing, rand1f(rng)); + weight *= eval_delta(material, normal, outgoing, incoming) / + sample_delta_pdf(material, normal, outgoing, incoming); + if (weight == zero3f || !isfinite(weight)) break; + + // setup next iteration + ray = {position, incoming}; + } + + return {radiance, hit, hit_albedo, hit_normal}; +} + // False color rendering static trace_result trace_falsecolor(const scene_model& scene, const bvh_scene& bvh, const trace_lights& lights, const ray3f& ray, @@ -1096,6 +1169,7 @@ static sampler_func get_trace_sampler_func(const trace_params& params) { case trace_sampler_type::pathmis: return trace_pathmis; case trace_sampler_type::naive: return trace_naive; case trace_sampler_type::eyelight: return trace_eyelight; + case trace_sampler_type::eyelightao: return trace_eyelightao; case trace_sampler_type::falsecolor: return trace_falsecolor; default: { throw std::runtime_error("sampler unknown"); diff --git a/libs/yocto/yocto_trace.h b/libs/yocto/yocto_trace.h index 392d6a148..6638ae462 100644 --- a/libs/yocto/yocto_trace.h +++ b/libs/yocto/yocto_trace.h @@ -77,6 +77,7 @@ enum struct trace_sampler_type { pathmis, // path tracing with mis naive, // naive path tracing eyelight, // eyelight rendering + eyelightao, // eyelight with ambient occlusion falsecolor, // false color rendering }; // Type of false color visualization @@ -113,8 +114,8 @@ struct trace_params { bool denoise = false; }; -inline const auto trace_sampler_names = std::vector{ - "path", "pathdirect", "pathmis", "naive", "eyelight", "falsecolor"}; +inline const auto trace_sampler_names = std::vector{"path", + "pathdirect", "pathmis", "naive", "eyelight", "eyelightao", "falsecolor"}; inline const auto trace_falsecolor_names = vector{"position", "normal", "frontfacing", "gnormal", "gfrontfacing", "texcoord", "mtype", "color",