Skip to content

Commit

Permalink
Eyelight rendering with ambient occlusion (#1221)
Browse files Browse the repository at this point in the history
  • Loading branch information
xelatihy authored May 3, 2021
1 parent 45f2e3f commit f709b64
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 2 deletions.
21 changes: 21 additions & 0 deletions libs/yocto/yocto_sampling.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
74 changes: 74 additions & 0 deletions libs/yocto/yocto_trace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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");
Expand Down
5 changes: 3 additions & 2 deletions libs/yocto/yocto_trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -113,8 +114,8 @@ struct trace_params {
bool denoise = false;
};

inline const auto trace_sampler_names = std::vector<std::string>{
"path", "pathdirect", "pathmis", "naive", "eyelight", "falsecolor"};
inline const auto trace_sampler_names = std::vector<std::string>{"path",
"pathdirect", "pathmis", "naive", "eyelight", "eyelightao", "falsecolor"};

inline const auto trace_falsecolor_names = vector<string>{"position", "normal",
"frontfacing", "gnormal", "gfrontfacing", "texcoord", "mtype", "color",
Expand Down

0 comments on commit f709b64

Please sign in to comment.