Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Microfacet fix #1264

Merged
merged 4 commits into from
Jul 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions libs/yocto/yocto_bvh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1087,6 +1087,13 @@ void overlap_bvh_elems(const bvh_data& bvh1, const bvh_data& bvh2,
}
#endif

bvh_intersection intersect_bvh(const bvh_data& bvh, const shape_data& shape,
const ray3f& ray, bool find_any) {
auto intersection = bvh_intersection{};
intersection.hit = intersect_bvh(bvh, shape, ray, intersection.element,
intersection.uv, intersection.distance, find_any);
return intersection;
}
bvh_intersection intersect_bvh(const bvh_data& bvh, const scene_data& scene,
const ray3f& ray, bool find_any, bool non_rigid_frames) {
auto intersection = bvh_intersection{};
Expand Down
18 changes: 10 additions & 8 deletions libs/yocto/yocto_shading.h
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,7 @@ inline float microfacet_shadowing1(float roughness, const vec3f& normal,
const vec3f& halfway, const vec3f& direction, bool ggx) {
// https://google.github.io/filament/Filament.html#materialsystem/specularbrdf
// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html
// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#appendix-b-brdf-implementation
auto cosine = dot(normal, direction);
auto cosineh = dot(halfway, direction);
if (cosine * cosineh <= 0) return 0;
Expand All @@ -445,7 +446,7 @@ inline float microfacet_shadowing(float roughness, const vec3f& normal,
microfacet_shadowing1(roughness, normal, halfway, incoming, ggx);
}

// Sample a microfacet ditribution.
// Sample a microfacet distribution.
inline vec3f sample_microfacet(
float roughness, const vec3f& normal, const vec2f& rn, bool ggx) {
auto phi = 2 * pif * rn.x;
Expand Down Expand Up @@ -488,12 +489,10 @@ inline vec3f sample_microfacet(float roughness, const vec3f& normal,
: vec3f{1, 0, 0};
auto T2 = cross(Vh, T1);
// Section 4.2: parameterization of the projected area
auto r = sqrt(rn.y);
auto phi = 2 * pif * rn.x;
auto t1 = r * cos(phi);
auto t2 = r * sin(phi);
auto s = 0.5f * (1 + Vh.z);
t2 = (1 - s) * sqrt(1 - t1 * t1) + s * t2;
auto r = sqrt(rn.y), phi = 2 * pif * rn.x;
auto t1 = r * cos(phi), t2 = r * sin(phi);
auto s = 0.5f * (1 + Vh.z);
t2 = (1 - s) * sqrt(1 - t1 * t1) + s * t2;
// Section 4.3: reprojection onto hemisphere
auto Nh = t1 * T1 + t2 * T2 + sqrt(max(0.0f, 1 - t1 * t1 - t2 * t2)) * Vh;
// Section 3.4: transforming the normal back to the ellipsoid configuration
Expand Down Expand Up @@ -904,6 +903,7 @@ inline vec3f sample_refractive(const vec3f& color, float ior, float roughness,
auto entering = dot(normal, outgoing) >= 0;
auto up_normal = entering ? normal : -normal;
auto halfway = sample_microfacet(roughness, up_normal, rn);
// auto halfway = sample_microfacet(roughness, up_normal, outgoing, rn);
if (rnl < fresnel_dielectric(entering ? ior : (1 / ior), halfway, outgoing)) {
auto incoming = reflect(outgoing, halfway);
if (!same_hemisphere(up_normal, outgoing, incoming)) return {0, 0, 0};
Expand All @@ -926,14 +926,16 @@ inline float sample_refractive_pdf(const vec3f& color, float ior,
auto halfway = normalize(incoming + outgoing);
return fresnel_dielectric(rel_ior, halfway, outgoing) *
sample_microfacet_pdf(roughness, up_normal, halfway) /
// sample_microfacet_pdf(roughness, up_normal, halfway, outgoing) /
(4 * abs(dot(outgoing, halfway)));
} else {
auto halfway = -normalize(rel_ior * incoming + outgoing) *
(entering ? 1.0f : -1.0f);
// [Walter 2007] equation 17
return (1 - fresnel_dielectric(rel_ior, halfway, outgoing)) *
sample_microfacet_pdf(roughness, up_normal, halfway) *
abs(dot(halfway, outgoing)) /
// sample_microfacet_pdf(roughness, up_normal, halfway, outgoing) /
abs(dot(halfway, incoming)) / // here we use incoming as from pbrt
pow(rel_ior * dot(halfway, incoming) + dot(halfway, outgoing), 2);
}
}
Expand Down
14 changes: 12 additions & 2 deletions libs/yocto/yocto_trace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,7 @@ static trace_result trace_path(const scene_data& scene, const bvh_data& bvh,
incoming = sample_lights(
scene, lights, position, rand1f(rng), rand1f(rng), rand2f(rng));
}
if (incoming == vec3f{0, 0, 0}) break;
weight *=
eval_bsdfcos(material, normal, outgoing, incoming) /
(0.5f * sample_bsdfcos_pdf(material, normal, outgoing, incoming) +
Expand Down Expand Up @@ -512,6 +513,7 @@ static trace_result trace_path(const scene_data& scene, const bvh_data& bvh,
incoming = sample_lights(
scene, lights, position, rand1f(rng), rand1f(rng), rand2f(rng));
}
if (incoming == vec3f{0, 0, 0}) break;
weight *=
eval_scattering(vsdf, outgoing, incoming) /
(0.5f * sample_scattering_pdf(vsdf, outgoing, incoming) +
Expand Down Expand Up @@ -642,13 +644,15 @@ static trace_result trace_pathdirect(const scene_data& scene,
incoming = sample_lights(
scene, lights, position, rand1f(rng), rand1f(rng), rand2f(rng));
}
if (incoming == vec3f{0, 0, 0}) break;
weight *=
eval_bsdfcos(material, normal, outgoing, incoming) /
(0.5f * sample_bsdfcos_pdf(material, normal, outgoing, incoming) +
0.5f *
sample_lights_pdf(scene, bvh, lights, position, incoming));
} else {
incoming = sample_delta(material, normal, outgoing, rand1f(rng));
if (incoming == vec3f{0, 0, 0}) break;
weight *= eval_delta(material, normal, outgoing, incoming) /
sample_delta_pdf(material, normal, outgoing, incoming);
}
Expand Down Expand Up @@ -680,6 +684,7 @@ static trace_result trace_pathdirect(const scene_data& scene,
incoming = sample_lights(
scene, lights, position, rand1f(rng), rand1f(rng), rand2f(rng));
}
if (incoming == vec3f{0, 0, 0}) break;
weight *=
eval_scattering(vsdf, outgoing, incoming) /
(0.5f * sample_scattering_pdf(vsdf, outgoing, incoming) +
Expand Down Expand Up @@ -789,10 +794,11 @@ static trace_result trace_pathmis(const scene_data& scene, const bvh_data& bvh,
if (!is_delta(material)) {
// direct with MIS --- light
for (auto sample_light : {true, false}) {
incoming = sample_light ? sample_lights(scene, lights, position,
incoming = sample_light ? sample_lights(scene, lights, position,
rand1f(rng), rand1f(rng), rand2f(rng))
: sample_bsdfcos(material, normal, outgoing,
: sample_bsdfcos(material, normal, outgoing,
rand1f(rng), rand2f(rng));
if (incoming == vec3f{0, 0, 0}) break;
auto bsdfcos = eval_bsdfcos(material, normal, outgoing, incoming);
auto light_pdf = sample_lights_pdf(
scene, bvh, lights, position, incoming);
Expand Down Expand Up @@ -936,10 +942,12 @@ static trace_result trace_naive(const scene_data& scene, const bvh_data& bvh,
if (material.roughness != 0) {
incoming = sample_bsdfcos(
material, normal, outgoing, rand1f(rng), rand2f(rng));
if (incoming == vec3f{0, 0, 0}) break;
weight *= eval_bsdfcos(material, normal, outgoing, incoming) /
sample_bsdfcos_pdf(material, normal, outgoing, incoming);
} else {
incoming = sample_delta(material, normal, outgoing, rand1f(rng));
if (incoming == vec3f{0, 0, 0}) break;
weight *= eval_delta(material, normal, outgoing, incoming) /
sample_delta_pdf(material, normal, outgoing, incoming);
}
Expand Down Expand Up @@ -1016,6 +1024,7 @@ static trace_result trace_eyelight(const scene_data& scene, const bvh_data& bvh,
// continue path
if (!is_delta(material)) break;
incoming = sample_delta(material, normal, outgoing, rand1f(rng));
if (incoming == vec3f{0, 0, 0}) break;
weight *= eval_delta(material, normal, outgoing, incoming) /
sample_delta_pdf(material, normal, outgoing, incoming);
if (weight == vec3f{0, 0, 0} || !isfinite(weight)) break;
Expand Down Expand Up @@ -1086,6 +1095,7 @@ static trace_result trace_eyelightao(const scene_data& scene,
// continue path
if (!is_delta(material)) break;
incoming = sample_delta(material, normal, outgoing, rand1f(rng));
if (incoming == vec3f{0, 0, 0}) break;
weight *= eval_delta(material, normal, outgoing, incoming) /
sample_delta_pdf(material, normal, outgoing, incoming);
if (weight == vec3f{0, 0, 0} || !isfinite(weight)) break;
Expand Down