Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h')
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h398
1 files changed, 201 insertions, 197 deletions
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h
index 5d300ef6db5..79247ee8057 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h
@@ -25,247 +25,251 @@
* energy is used. In combination with MIS, that is enough to produce an unbiased result, although
* the balance heuristic isn't necessarily optimal anymore.
*/
-ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
- float3 wi,
- float3 wo,
- const bool wo_outside,
- const float3 color,
- const float alpha_x,
- const float alpha_y,
- ccl_addr_space uint *lcg_state,
- const float eta,
- bool use_fresnel,
- const float3 cspec0)
+ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi,
+ float3 wo,
+ const bool wo_outside,
+ const float3 color,
+ const float alpha_x,
+ const float alpha_y,
+ ccl_addr_space uint *lcg_state,
+ const float eta,
+ bool use_fresnel,
+ const float3 cspec0)
{
- /* Evaluating for a shallower incoming direction produces less noise, and the properties of the BSDF guarantee reciprocity. */
- bool swapped = false;
+ /* Evaluating for a shallower incoming direction produces less noise, and the properties of the BSDF guarantee reciprocity. */
+ bool swapped = false;
#ifdef MF_MULTI_GLASS
- if(wi.z*wo.z < 0.0f) {
- /* Glass transmission is a special case and requires the directions to change hemisphere. */
- if(-wo.z < wi.z) {
- swapped = true;
- float3 tmp = -wo;
- wo = -wi;
- wi = tmp;
- }
- }
- else
+ if (wi.z * wo.z < 0.0f) {
+ /* Glass transmission is a special case and requires the directions to change hemisphere. */
+ if (-wo.z < wi.z) {
+ swapped = true;
+ float3 tmp = -wo;
+ wo = -wi;
+ wi = tmp;
+ }
+ }
+ else
#endif
- if(wo.z < wi.z) {
- swapped = true;
- float3 tmp = wo;
- wo = wi;
- wi = tmp;
- }
+ if (wo.z < wi.z) {
+ swapped = true;
+ float3 tmp = wo;
+ wo = wi;
+ wi = tmp;
+ }
- if(wi.z < 1e-5f || (wo.z < 1e-5f && wo_outside) || (wo.z > -1e-5f && !wo_outside))
- return make_float3(0.0f, 0.0f, 0.0f);
+ if (wi.z < 1e-5f || (wo.z < 1e-5f && wo_outside) || (wo.z > -1e-5f && !wo_outside))
+ return make_float3(0.0f, 0.0f, 0.0f);
- const float2 alpha = make_float2(alpha_x, alpha_y);
+ const float2 alpha = make_float2(alpha_x, alpha_y);
- float lambda_r = mf_lambda(-wi, alpha);
- float shadowing_lambda = mf_lambda(wo_outside? wo: -wo, alpha);
+ 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 eval;
- float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
- const float3 wh = normalize(wi+wo);
+ /* Analytically compute single scattering for lower noise. */
+ float3 eval;
+ float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
+ const float3 wh = normalize(wi + wo);
#ifdef MF_MULTI_GLASS
- eval = mf_eval_phase_glass(-wi, lambda_r, wo, wo_outside, alpha, eta);
- if(wo_outside)
- eval *= -lambda_r / (shadowing_lambda - lambda_r);
- else
- eval *= -lambda_r * beta(-lambda_r, shadowing_lambda+1.0f);
-#else /* MF_MULTI_GLOSSY */
- const float G2 = 1.0f / (1.0f - (lambda_r + 1.0f) + shadowing_lambda);
- float val = G2 * 0.25f / wi.z;
- if(alpha.x == alpha.y)
- val *= D_ggx(wh, alpha.x);
- else
- val *= D_ggx_aniso(wh, alpha);
- eval = make_float3(val, val, val);
+ eval = mf_eval_phase_glass(-wi, lambda_r, wo, wo_outside, alpha, eta);
+ if (wo_outside)
+ eval *= -lambda_r / (shadowing_lambda - lambda_r);
+ else
+ eval *= -lambda_r * beta(-lambda_r, shadowing_lambda + 1.0f);
+#else /* MF_MULTI_GLOSSY */
+ const float G2 = 1.0f / (1.0f - (lambda_r + 1.0f) + shadowing_lambda);
+ float val = G2 * 0.25f / wi.z;
+ if (alpha.x == alpha.y)
+ val *= D_ggx(wh, alpha.x);
+ else
+ val *= D_ggx_aniso(wh, alpha);
+ eval = make_float3(val, val, val);
#endif
- float F0 = fresnel_dielectric_cos(1.0f, eta);
- if(use_fresnel) {
- throughput = interpolate_fresnel_color(wi, wh, eta, F0, cspec0);
+ float F0 = fresnel_dielectric_cos(1.0f, eta);
+ if (use_fresnel) {
+ throughput = interpolate_fresnel_color(wi, wh, eta, F0, cspec0);
- eval *= throughput;
- }
+ eval *= throughput;
+ }
- float3 wr = -wi;
- float hr = 1.0f;
- float C1_r = 1.0f;
- float G1_r = 0.0f;
- bool outside = true;
+ 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. */
- float height_rand = lcg_step_float_addrspace(lcg_state);
- if(!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, height_rand))
- break;
- /* Sample microfacet normal. */
- float vndf_rand_y = lcg_step_float_addrspace(lcg_state);
- float vndf_rand_x = lcg_step_float_addrspace(lcg_state);
- float3 wm = mf_sample_vndf(-wr, alpha, vndf_rand_x, vndf_rand_y);
+ for (int order = 0; order < 10; order++) {
+ /* Sample microfacet height. */
+ float height_rand = lcg_step_float_addrspace(lcg_state);
+ if (!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, height_rand))
+ break;
+ /* Sample microfacet normal. */
+ float vndf_rand_y = lcg_step_float_addrspace(lcg_state);
+ float vndf_rand_x = lcg_step_float_addrspace(lcg_state);
+ float3 wm = mf_sample_vndf(-wr, alpha, vndf_rand_x, vndf_rand_y);
#ifdef MF_MULTI_GLASS
- if(order == 0 && use_fresnel) {
- /* Evaluate amount of scattering towards wo on this microfacet. */
- float3 phase;
- 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);
+ if (order == 0 && use_fresnel) {
+ /* Evaluate amount of scattering towards wo on this microfacet. */
+ float3 phase;
+ 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);
- eval = 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);
+ }
#endif
- if(order > 0) {
- /* Evaluate amount of scattering towards wo on this microfacet. */
- float3 phase;
+ 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);
-#else /* MF_MULTI_GLOSSY */
- phase = mf_eval_phase_glossy(wr, lambda_r, wo, alpha) * throughput;
+ 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);
+#else /* MF_MULTI_GLOSSY */
+ phase = mf_eval_phase_glossy(wr, lambda_r, wo, alpha) * throughput;
#endif
- 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. */
+ 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. */
#ifdef MF_MULTI_GLASS
- bool next_outside;
- float3 wi_prev = -wr;
- float phase_rand = lcg_step_float_addrspace(lcg_state);
- wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, phase_rand, &next_outside);
- if(!next_outside) {
- outside = !outside;
- wr = -wr;
- hr = -hr;
- }
+ bool next_outside;
+ float3 wi_prev = -wr;
+ float phase_rand = lcg_step_float_addrspace(lcg_state);
+ wr = mf_sample_phase_glass(-wr, outside ? eta : 1.0f / eta, wm, phase_rand, &next_outside);
+ if (!next_outside) {
+ outside = !outside;
+ wr = -wr;
+ hr = -hr;
+ }
- if(use_fresnel && !next_outside) {
- throughput *= color;
- }
- else if(use_fresnel && order > 0) {
- throughput *= interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0);
- }
-#else /* MF_MULTI_GLOSSY */
- if(use_fresnel && order > 0) {
- throughput *= interpolate_fresnel_color(-wr, wm, eta, F0, cspec0);
- }
- wr = mf_sample_phase_glossy(-wr, &throughput, wm);
+ if (use_fresnel && !next_outside) {
+ throughput *= color;
+ }
+ else if (use_fresnel && order > 0) {
+ throughput *= interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0);
+ }
+#else /* MF_MULTI_GLOSSY */
+ if (use_fresnel && order > 0) {
+ throughput *= interpolate_fresnel_color(-wr, wm, eta, F0, cspec0);
+ }
+ wr = mf_sample_phase_glossy(-wr, &throughput, wm);
#endif
- lambda_r = mf_lambda(wr, alpha);
+ lambda_r = mf_lambda(wr, alpha);
- if(!use_fresnel)
- throughput *= color;
+ if (!use_fresnel)
+ throughput *= color;
- C1_r = mf_C1(hr);
- G1_r = mf_G1(wr, C1_r, lambda_r);
- }
- }
+ C1_r = mf_C1(hr);
+ G1_r = mf_G1(wr, C1_r, lambda_r);
+ }
+ }
- if(swapped)
- eval *= fabsf(wi.z / wo.z);
- return eval;
+ if (swapped)
+ eval *= fabsf(wi.z / wo.z);
+ return eval;
}
/* Perform a random walk on the microsurface starting from wi, returning the direction in which the walk
* escaped the surface in wo. The function returns the throughput between wi and wo.
* Without reflection losses due to coloring or fresnel absorption in conductors, the sampling is optimal.
*/
-ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(
- float3 wi,
- float3 *wo,
- const float3 color,
- const float alpha_x,
- const float alpha_y,
- ccl_addr_space uint *lcg_state,
- const float eta,
- bool use_fresnel,
- const float3 cspec0)
+ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi,
+ float3 *wo,
+ const float3 color,
+ const float alpha_x,
+ const float alpha_y,
+ ccl_addr_space uint *lcg_state,
+ const float eta,
+ bool use_fresnel,
+ const float3 cspec0)
{
- const float2 alpha = make_float2(alpha_x, alpha_y);
+ const float2 alpha = make_float2(alpha_x, alpha_y);
- float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
- 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;
+ float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
+ 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 F0 = fresnel_dielectric_cos(1.0f, eta);
- if(use_fresnel) {
- throughput = interpolate_fresnel_color(wi, normalize(wi + wr), eta, F0, cspec0);
- }
+ float F0 = fresnel_dielectric_cos(1.0f, eta);
+ if (use_fresnel) {
+ throughput = interpolate_fresnel_color(wi, normalize(wi + wr), eta, F0, cspec0);
+ }
- int order;
- for(order = 0; order < 10; order++) {
- /* Sample microfacet height. */
- float height_rand = lcg_step_float_addrspace(lcg_state);
- if(!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, height_rand)) {
- /* The random walk has left the surface. */
- *wo = outside? wr: -wr;
- return throughput;
- }
- /* Sample microfacet normal. */
- float vndf_rand_y = lcg_step_float_addrspace(lcg_state);
- float vndf_rand_x = lcg_step_float_addrspace(lcg_state);
- float3 wm = mf_sample_vndf(-wr, alpha, vndf_rand_x, vndf_rand_y);
+ int order;
+ for (order = 0; order < 10; order++) {
+ /* Sample microfacet height. */
+ float height_rand = lcg_step_float_addrspace(lcg_state);
+ if (!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, height_rand)) {
+ /* The random walk has left the surface. */
+ *wo = outside ? wr : -wr;
+ return throughput;
+ }
+ /* Sample microfacet normal. */
+ float vndf_rand_y = lcg_step_float_addrspace(lcg_state);
+ float vndf_rand_x = lcg_step_float_addrspace(lcg_state);
+ float3 wm = mf_sample_vndf(-wr, alpha, vndf_rand_x, vndf_rand_y);
- /* First-bounce color is already accounted for in mix weight. */
- if(!use_fresnel && order > 0)
- throughput *= color;
+ /* First-bounce color is already accounted for in mix weight. */
+ if (!use_fresnel && order > 0)
+ throughput *= color;
- /* Bounce from the microfacet. */
+ /* Bounce from the microfacet. */
#ifdef MF_MULTI_GLASS
- bool next_outside;
- float3 wi_prev = -wr;
- float phase_rand = lcg_step_float_addrspace(lcg_state);
- wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, phase_rand, &next_outside);
- if(!next_outside) {
- hr = -hr;
- wr = -wr;
- outside = !outside;
- }
+ bool next_outside;
+ float3 wi_prev = -wr;
+ float phase_rand = lcg_step_float_addrspace(lcg_state);
+ wr = mf_sample_phase_glass(-wr, outside ? eta : 1.0f / eta, wm, phase_rand, &next_outside);
+ if (!next_outside) {
+ hr = -hr;
+ wr = -wr;
+ outside = !outside;
+ }
- if(use_fresnel) {
- if(!next_outside) {
- throughput *= color;
- }
- else {
- float3 t_color = interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0);
+ if (use_fresnel) {
+ if (!next_outside) {
+ throughput *= color;
+ }
+ else {
+ float3 t_color = interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0);
- if(order == 0)
- throughput = t_color;
- else
- throughput *= t_color;
- }
- }
-#else /* MF_MULTI_GLOSSY */
- if(use_fresnel) {
- float3 t_color = interpolate_fresnel_color(-wr, wm, eta, F0, cspec0);
+ if (order == 0)
+ throughput = t_color;
+ else
+ throughput *= t_color;
+ }
+ }
+#else /* MF_MULTI_GLOSSY */
+ if (use_fresnel) {
+ float3 t_color = interpolate_fresnel_color(-wr, wm, eta, F0, cspec0);
- if(order == 0)
- throughput = t_color;
- else
- throughput *= t_color;
- }
- wr = mf_sample_phase_glossy(-wr, &throughput, wm);
+ if (order == 0)
+ throughput = t_color;
+ else
+ throughput *= t_color;
+ }
+ wr = mf_sample_phase_glossy(-wr, &throughput, wm);
#endif
- /* Update random walk parameters. */
- lambda_r = mf_lambda(wr, alpha);
- G1_r = mf_G1(wr, C1_r, lambda_r);
- }
- *wo = make_float3(0.0f, 0.0f, 1.0f);
- return make_float3(0.0f, 0.0f, 0.0f);
+ /* Update random walk parameters. */
+ lambda_r = mf_lambda(wr, alpha);
+ G1_r = mf_G1(wr, C1_r, lambda_r);
+ }
+ *wo = make_float3(0.0f, 0.0f, 1.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
#undef MF_MULTI_GLASS