diff options
Diffstat (limited to 'intern/cycles/kernel/closure')
-rw-r--r-- | intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h | 2 | ||||
-rw-r--r-- | intern/cycles/kernel/closure/bsdf_diffuse.h | 2 | ||||
-rw-r--r-- | intern/cycles/kernel/closure/bsdf_diffuse_ramp.h | 2 | ||||
-rw-r--r-- | intern/cycles/kernel/closure/bsdf_hair_principled.h | 2 | ||||
-rw-r--r-- | intern/cycles/kernel/closure/bsdf_microfacet.h | 25 | ||||
-rw-r--r-- | intern/cycles/kernel/closure/bsdf_microfacet_multi.h | 13 | ||||
-rw-r--r-- | intern/cycles/kernel/closure/bsdf_oren_nayar.h | 2 | ||||
-rw-r--r-- | intern/cycles/kernel/closure/bsdf_principled_diffuse.h | 2 | ||||
-rw-r--r-- | intern/cycles/kernel/closure/bsdf_toon.h | 8 | ||||
-rw-r--r-- | intern/cycles/kernel/closure/bsdf_util.h | 106 |
10 files changed, 141 insertions, 23 deletions
diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h index c00890be54c..b2a9c9555c3 100644 --- a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h +++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h @@ -32,7 +32,7 @@ #pragma once -#include "kernel/kernel_montecarlo.h" +#include "kernel/sample/mapping.h" CCL_NAMESPACE_BEGIN diff --git a/intern/cycles/kernel/closure/bsdf_diffuse.h b/intern/cycles/kernel/closure/bsdf_diffuse.h index 16c9b428004..3139cb612fa 100644 --- a/intern/cycles/kernel/closure/bsdf_diffuse.h +++ b/intern/cycles/kernel/closure/bsdf_diffuse.h @@ -32,6 +32,8 @@ #pragma once +#include "kernel/sample/mapping.h" + CCL_NAMESPACE_BEGIN typedef struct DiffuseBsdf { diff --git a/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h b/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h index 8bff7709a32..fbb82617dad 100644 --- a/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h +++ b/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h @@ -32,6 +32,8 @@ #pragma once +#include "kernel/sample/mapping.h" + CCL_NAMESPACE_BEGIN #ifdef __OSL__ diff --git a/intern/cycles/kernel/closure/bsdf_hair_principled.h b/intern/cycles/kernel/closure/bsdf_hair_principled.h index a474c5661b3..f55ea0f6a2e 100644 --- a/intern/cycles/kernel/closure/bsdf_hair_principled.h +++ b/intern/cycles/kernel/closure/bsdf_hair_principled.h @@ -20,7 +20,7 @@ # include <fenv.h> #endif -#include "kernel/kernel_color.h" +#include "kernel/util/color.h" CCL_NAMESPACE_BEGIN diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index a4e1b7a491c..466ba3e229e 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -32,8 +32,11 @@ #pragma once -#include "kernel/kernel_lookup_table.h" -#include "kernel/kernel_random.h" +#include "kernel/closure/bsdf_util.h" + +#include "kernel/sample/pattern.h" + +#include "kernel/util/lookup_table.h" CCL_NAMESPACE_BEGIN @@ -312,8 +315,8 @@ ccl_device int bsdf_microfacet_ggx_setup(ccl_private MicrofacetBsdf *bsdf) { bsdf->extra = NULL; - bsdf->alpha_x = saturate(bsdf->alpha_x); - bsdf->alpha_y = saturate(bsdf->alpha_y); + bsdf->alpha_x = saturatef(bsdf->alpha_x); + bsdf->alpha_y = saturatef(bsdf->alpha_y); bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ID; @@ -333,8 +336,8 @@ ccl_device int bsdf_microfacet_ggx_fresnel_setup(ccl_private MicrofacetBsdf *bsd { bsdf->extra->cspec0 = saturate3(bsdf->extra->cspec0); - bsdf->alpha_x = saturate(bsdf->alpha_x); - bsdf->alpha_y = saturate(bsdf->alpha_y); + bsdf->alpha_x = saturatef(bsdf->alpha_x); + bsdf->alpha_y = saturatef(bsdf->alpha_y); bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID; @@ -348,7 +351,7 @@ ccl_device int bsdf_microfacet_ggx_clearcoat_setup(ccl_private MicrofacetBsdf *b { bsdf->extra->cspec0 = saturate3(bsdf->extra->cspec0); - bsdf->alpha_x = saturate(bsdf->alpha_x); + bsdf->alpha_x = saturatef(bsdf->alpha_x); bsdf->alpha_y = bsdf->alpha_x; bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID; @@ -362,7 +365,7 @@ ccl_device int bsdf_microfacet_ggx_refraction_setup(ccl_private MicrofacetBsdf * { bsdf->extra = NULL; - bsdf->alpha_x = saturate(bsdf->alpha_x); + bsdf->alpha_x = saturatef(bsdf->alpha_x); bsdf->alpha_y = bsdf->alpha_x; bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; @@ -780,8 +783,8 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg, ccl_device int bsdf_microfacet_beckmann_setup(ccl_private MicrofacetBsdf *bsdf) { - bsdf->alpha_x = saturate(bsdf->alpha_x); - bsdf->alpha_y = saturate(bsdf->alpha_y); + bsdf->alpha_x = saturatef(bsdf->alpha_x); + bsdf->alpha_y = saturatef(bsdf->alpha_y); bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID; return SD_BSDF | SD_BSDF_HAS_EVAL; @@ -797,7 +800,7 @@ ccl_device int bsdf_microfacet_beckmann_isotropic_setup(ccl_private MicrofacetBs ccl_device int bsdf_microfacet_beckmann_refraction_setup(ccl_private MicrofacetBsdf *bsdf) { - bsdf->alpha_x = saturate(bsdf->alpha_x); + bsdf->alpha_x = saturatef(bsdf->alpha_x); bsdf->alpha_y = bsdf->alpha_x; bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h index b7bd7faaa54..5badbe9aa80 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h @@ -16,6 +16,9 @@ #pragma once +#include "kernel/sample/lcg.h" +#include "kernel/sample/mapping.h" + CCL_NAMESPACE_BEGIN /* Most of the code is based on the supplemental implementations from @@ -217,12 +220,12 @@ ccl_device_forceinline float mf_lambda(const float3 w, const float2 alpha) /* Height distribution CDF (based on page 4 of the supplemental implementation). */ ccl_device_forceinline float mf_invC1(const float h) { - return 2.0f * saturate(h) - 1.0f; + return 2.0f * saturatef(h) - 1.0f; } ccl_device_forceinline float mf_C1(const float h) { - return saturate(0.5f * (h + 1.0f)); + return saturatef(0.5f * (h + 1.0f)); } /* Masking function (based on page 16 of the supplemental implementation). */ @@ -281,7 +284,7 @@ ccl_device_forceinline float mf_ggx_albedo(float r) 0.027803f) * r + 0.00568739f; - return saturate(albedo); + return saturatef(albedo); } ccl_device_inline float mf_ggx_transmission_albedo(float a, float ior) @@ -289,7 +292,7 @@ ccl_device_inline float mf_ggx_transmission_albedo(float a, float ior) if (ior < 1.0f) { ior = 1.0f / ior; } - a = saturate(a); + a = saturatef(a); ior = clamp(ior, 1.0f, 3.0f); float I_1 = 0.0476898f * expf(-0.978352f * (ior - 0.65657f) * (ior - 0.65657f)) - 0.033756f * ior + 0.993261f; @@ -299,7 +302,7 @@ ccl_device_inline float mf_ggx_transmission_albedo(float a, float ior) float R_2 = ((((5.3725f * a - 24.9307f) * a + 22.7437f) * a - 3.40751f) * a + 0.0986325f) * a + 0.00493504f; - return saturate(1.0f + I_2 * R_2 * 0.0019127f - (1.0f - I_1) * (1.0f - R_1) * 9.3205f); + return saturatef(1.0f + I_2 * R_2 * 0.0019127f - (1.0f - I_1) * (1.0f - R_1) * 9.3205f); } ccl_device_forceinline float mf_ggx_pdf(const float3 wi, const float3 wo, const float alpha) diff --git a/intern/cycles/kernel/closure/bsdf_oren_nayar.h b/intern/cycles/kernel/closure/bsdf_oren_nayar.h index 00c2678f0a0..8827309a811 100644 --- a/intern/cycles/kernel/closure/bsdf_oren_nayar.h +++ b/intern/cycles/kernel/closure/bsdf_oren_nayar.h @@ -50,7 +50,7 @@ ccl_device int bsdf_oren_nayar_setup(ccl_private OrenNayarBsdf *bsdf) bsdf->type = CLOSURE_BSDF_OREN_NAYAR_ID; - sigma = saturate(sigma); + sigma = saturatef(sigma); float div = 1.0f / (M_PI_F + ((3.0f * M_PI_F - 4.0f) / 6.0f) * sigma); diff --git a/intern/cycles/kernel/closure/bsdf_principled_diffuse.h b/intern/cycles/kernel/closure/bsdf_principled_diffuse.h index 74390f768a2..69376c1294d 100644 --- a/intern/cycles/kernel/closure/bsdf_principled_diffuse.h +++ b/intern/cycles/kernel/closure/bsdf_principled_diffuse.h @@ -27,6 +27,8 @@ #include "kernel/closure/bsdf_util.h" +#include "kernel/sample/mapping.h" + CCL_NAMESPACE_BEGIN enum PrincipledDiffuseBsdfComponents { diff --git a/intern/cycles/kernel/closure/bsdf_toon.h b/intern/cycles/kernel/closure/bsdf_toon.h index 7f20a328b5e..20f3b8f0074 100644 --- a/intern/cycles/kernel/closure/bsdf_toon.h +++ b/intern/cycles/kernel/closure/bsdf_toon.h @@ -48,8 +48,8 @@ static_assert(sizeof(ShaderClosure) >= sizeof(ToonBsdf), "ToonBsdf is too large! ccl_device int bsdf_diffuse_toon_setup(ccl_private ToonBsdf *bsdf) { bsdf->type = CLOSURE_BSDF_DIFFUSE_TOON_ID; - bsdf->size = saturate(bsdf->size); - bsdf->smooth = saturate(bsdf->smooth); + bsdf->size = saturatef(bsdf->size); + bsdf->smooth = saturatef(bsdf->smooth); return SD_BSDF | SD_BSDF_HAS_EVAL; } @@ -146,8 +146,8 @@ ccl_device int bsdf_diffuse_toon_sample(ccl_private const ShaderClosure *sc, ccl_device int bsdf_glossy_toon_setup(ccl_private ToonBsdf *bsdf) { bsdf->type = CLOSURE_BSDF_GLOSSY_TOON_ID; - bsdf->size = saturate(bsdf->size); - bsdf->smooth = saturate(bsdf->smooth); + bsdf->size = saturatef(bsdf->size); + bsdf->smooth = saturatef(bsdf->smooth); return SD_BSDF | SD_BSDF_HAS_EVAL; } diff --git a/intern/cycles/kernel/closure/bsdf_util.h b/intern/cycles/kernel/closure/bsdf_util.h index 873494c1e03..b1c16a037df 100644 --- a/intern/cycles/kernel/closure/bsdf_util.h +++ b/intern/cycles/kernel/closure/bsdf_util.h @@ -148,4 +148,110 @@ interpolate_fresnel_color(float3 L, float3 H, float ior, float F0, float3 cspec0 return cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; } +ccl_device float3 ensure_valid_reflection(float3 Ng, float3 I, float3 N) +{ + float3 R = 2 * dot(N, I) * N - I; + + /* Reflection rays may always be at least as shallow as the incoming ray. */ + float threshold = min(0.9f * dot(Ng, I), 0.01f); + if (dot(Ng, R) >= threshold) { + return N; + } + + /* Form coordinate system with Ng as the Z axis and N inside the X-Z-plane. + * The X axis is found by normalizing the component of N that's orthogonal to Ng. + * The Y axis isn't actually needed. + */ + float NdotNg = dot(N, Ng); + float3 X = normalize(N - NdotNg * Ng); + + /* Keep math expressions. */ + /* clang-format off */ + /* Calculate N.z and N.x in the local coordinate system. + * + * The goal of this computation is to find a N' that is rotated towards Ng just enough + * to lift R' above the threshold (here called t), therefore dot(R', Ng) = t. + * + * According to the standard reflection equation, + * this means that we want dot(2*dot(N', I)*N' - I, Ng) = t. + * + * Since the Z axis of our local coordinate system is Ng, dot(x, Ng) is just x.z, so we get + * 2*dot(N', I)*N'.z - I.z = t. + * + * The rotation is simple to express in the coordinate system we formed - + * since N lies in the X-Z-plane, we know that N' will also lie in the X-Z-plane, + * so N'.y = 0 and therefore dot(N', I) = N'.x*I.x + N'.z*I.z . + * + * Furthermore, we want N' to be normalized, so N'.x = sqrt(1 - N'.z^2). + * + * With these simplifications, + * we get the final equation 2*(sqrt(1 - N'.z^2)*I.x + N'.z*I.z)*N'.z - I.z = t. + * + * The only unknown here is N'.z, so we can solve for that. + * + * The equation has four solutions in general: + * + * N'.z = +-sqrt(0.5*(+-sqrt(I.x^2*(I.x^2 + I.z^2 - t^2)) + t*I.z + I.x^2 + I.z^2)/(I.x^2 + I.z^2)) + * We can simplify this expression a bit by grouping terms: + * + * a = I.x^2 + I.z^2 + * b = sqrt(I.x^2 * (a - t^2)) + * c = I.z*t + a + * N'.z = +-sqrt(0.5*(+-b + c)/a) + * + * Two solutions can immediately be discarded because they're negative so N' would lie in the + * lower hemisphere. + */ + /* clang-format on */ + + float Ix = dot(I, X), Iz = dot(I, Ng); + float Ix2 = sqr(Ix), Iz2 = sqr(Iz); + float a = Ix2 + Iz2; + + float b = safe_sqrtf(Ix2 * (a - sqr(threshold))); + float c = Iz * threshold + a; + + /* Evaluate both solutions. + * In many cases one can be immediately discarded (if N'.z would be imaginary or larger than + * one), so check for that first. If no option is viable (might happen in extreme cases like N + * being in the wrong hemisphere), give up and return Ng. */ + float fac = 0.5f / a; + float N1_z2 = fac * (b + c), N2_z2 = fac * (-b + c); + bool valid1 = (N1_z2 > 1e-5f) && (N1_z2 <= (1.0f + 1e-5f)); + bool valid2 = (N2_z2 > 1e-5f) && (N2_z2 <= (1.0f + 1e-5f)); + + float2 N_new; + if (valid1 && valid2) { + /* If both are possible, do the expensive reflection-based check. */ + float2 N1 = make_float2(safe_sqrtf(1.0f - N1_z2), safe_sqrtf(N1_z2)); + float2 N2 = make_float2(safe_sqrtf(1.0f - N2_z2), safe_sqrtf(N2_z2)); + + float R1 = 2 * (N1.x * Ix + N1.y * Iz) * N1.y - Iz; + float R2 = 2 * (N2.x * Ix + N2.y * Iz) * N2.y - Iz; + + valid1 = (R1 >= 1e-5f); + valid2 = (R2 >= 1e-5f); + if (valid1 && valid2) { + /* If both solutions are valid, return the one with the shallower reflection since it will be + * closer to the input (if the original reflection wasn't shallow, we would not be in this + * part of the function). */ + N_new = (R1 < R2) ? N1 : N2; + } + else { + /* If only one reflection is valid (= positive), pick that one. */ + N_new = (R1 > R2) ? N1 : N2; + } + } + else if (valid1 || valid2) { + /* Only one solution passes the N'.z criterium, so pick that one. */ + float Nz2 = valid1 ? N1_z2 : N2_z2; + N_new = make_float2(safe_sqrtf(1.0f - Nz2), safe_sqrtf(Nz2)); + } + else { + return Ng; + } + + return N_new.x * X + N_new.y * Ng; +} + CCL_NAMESPACE_END |