Page MenuHome
Paste P368

(An Untitled Masterwork)
ActivePublic

Authored by Brecht Van Lommel (brecht) on Jun 19 2016, 5:02 PM.
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h
index ba03b31..eb15547 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h
@@ -59,26 +59,20 @@ ccl_device float3 MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi, float3 wo, const boo
const float2 alpha = make_float2(alpha_x, alpha_y);
- float3 wr = -wi;
- float lambda_r = mf_lambda(wr, alpha);
- float hr = 1.0f;
- float C1_r = 1.0f;
- float G1_r = 0.0f;
- bool outside = true;
+ float lambda_r = mf_lambda(-wi, alpha);
float shadowing_lambda = mf_lambda(wo_outside? wo: -wo, alpha);
/* Analytically compute single scattering for lower noise. */
- float3 singleScatter;
/* TODO(lukas): Multiply with color here? */
#ifdef MF_MULTI_GLASS
- singleScatter = mf_eval_phase_glass(wr, lambda_r, wo, wo_outside, alpha, eta);
+ float3 eval = mf_eval_phase_glass(-wi, lambda_r, wo, wo_outside, alpha, eta);
if(wo_outside)
- singleScatter *= -lambda_r / (shadowing_lambda - lambda_r);
+ eval *= -lambda_r / (shadowing_lambda - lambda_r);
else
- singleScatter *= -lambda_r * beta(-lambda_r, shadowing_lambda+1.0f);
+ eval *= -lambda_r * beta(-lambda_r, shadowing_lambda+1.0f);
#elif defined(MF_MULTI_DIFFUSE)
/* Diffuse has no special closed form for the single scattering bounce */
- singleScatter = make_float3(0.0f, 0.0f, 0.0f);
+ float3 eval = make_float3(0.0f, 0.0f, 0.0f);
#else /* MF_MULTI_GLOSSY */
const float3 wh = normalize(wi+wo);
const float G2 = 1.0f / (1.0f - (lambda_r + 1.0f) + shadowing_lambda);
@@ -87,16 +81,30 @@ ccl_device float3 MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi, float3 wo, const boo
val *= D_ggx(wh, alpha.x);
else
val *= D_ggx_aniso(wh, alpha);
+
+ float3 eval;
if(n && k) {
- singleScatter = fresnel_conductor(dot(wh, wi), *n, *k) * val;
+ eval = fresnel_conductor(dot(wh, wi), *n, *k) * val;
}
else {
- singleScatter = make_float3(val, val, val);
+ eval = make_float3(val, val, val);
}
#endif
- float3 multiScatter = make_float3(0.0f, 0.0f, 0.0f);
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
+
+ if(swapped) {
+ const float fac = fabsf(wi.z / wo.z);
+ throughput = make_float3(fac, fac, fac);
+ eval *= fac;
+ }
+
+ float3 wr = -wi;
+ float hr = 1.0f;
+ float C1_r = 1.0f;
+ float G1_r = 0.0f;
+ bool outside = true;
+
for(int order = 0; order < 10; order++) {
/* Sample microfacet height and normal */
if(!mf_sample_height(wr, hr, C1_r, G1_r, lambda_r, lcg_step_float(lcg_state)))
@@ -107,23 +115,20 @@ ccl_device float3 MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi, float3 wo, const boo
if(order == 0) {
/* Compute single-scattering for diffuse. */
const float G2_G1 = -lambda_r / (shadowing_lambda - lambda_r);
- multiScatter += throughput * G2_G1 * mf_eval_phase_diffuse(wo, wm);
+ eval += throughput * G2_G1 * mf_eval_phase_diffuse(wo, wm);
}
#endif
if(order > 0) {
/* Evaluate amount of scattering towards wo on this microfacet. */
float3 phase;
#ifdef MF_MULTI_GLASS
- if(outside)
- phase = mf_eval_phase_glass(wr, lambda_r, wo, wo_outside, alpha, eta);
- else
- phase = mf_eval_phase_glass(wr, lambda_r, -wo, !wo_outside, alpha, 1.0f/eta);
+ phase = mf_eval_phase_glass(wr, lambda_r, (outside)? wo: -wo, (outside)? wo_outside: !wo_outside, alpha, (outside)? eta: 1.0f/eta);
#elif defined(MF_MULTI_DIFFUSE)
phase = mf_eval_phase_diffuse(wo, wm);
#else /* MF_MULTI_GLOSSY */
phase = mf_eval_phase_glossy(wr, lambda_r, wo, alpha, n, k) * throughput;
#endif
- multiScatter += throughput * phase * mf_G1(wo_outside? wo: -wo, mf_C1((outside == wo_outside)? hr: -hr), shadowing_lambda);
+ eval += throughput * phase * mf_G1(wo_outside? wo: -wo, mf_C1((outside == wo_outside)? hr: -hr), shadowing_lambda);
}
if(order+1 < 10) {
/* Bounce from the microfacet. */
@@ -150,9 +155,6 @@ ccl_device float3 MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi, float3 wo, const boo
}
}
- float3 eval = singleScatter + multiScatter;
- if(swapped)
- eval *= fabsf(wi.z / wo.z);
return eval;
}