diff options
Diffstat (limited to 'intern/cycles/kernel/closure/bsdf_microfacet.h')
-rw-r--r-- | intern/cycles/kernel/closure/bsdf_microfacet.h | 379 |
1 files changed, 197 insertions, 182 deletions
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index f29897bc55d..4eb7cd5df22 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -357,146 +357,129 @@ ccl_device void bsdf_microfacet_ggx_blur(ccl_private ShaderClosure *sc, float ro bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y); } -ccl_device Spectrum bsdf_microfacet_ggx_eval_reflect(ccl_private const ShaderClosure *sc, +ccl_device Spectrum bsdf_microfacet_ggx_eval_reflect(ccl_private const MicrofacetBsdf *bsdf, + const float3 N, const float3 I, const float3 omega_in, - ccl_private float *pdf) + ccl_private float *pdf, + const float alpha_x, + const float alpha_y, + const float cosNO, + const float cosNI) { - ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; - float alpha_x = bsdf->alpha_x; - float alpha_y = bsdf->alpha_y; - bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; - float3 N = bsdf->N; - - if (m_refractive || alpha_x * alpha_y <= 1e-7f) { + if (!(cosNI > 0 && cosNO > 0)) { *pdf = 0.0f; return zero_spectrum(); } - float cosNO = dot(N, I); - float cosNI = dot(N, omega_in); - - if (cosNI > 0 && cosNO > 0) { - /* get half vector */ - float3 m = normalize(omega_in + I); - float alpha2 = alpha_x * alpha_y; - float D, G1o, G1i; - - if (alpha_x == alpha_y) { - /* isotropic - * eq. 20: (F*G*D)/(4*in*on) - * eq. 33: first we calculate D(m) */ - float cosThetaM = dot(N, m); - float cosThetaM2 = cosThetaM * cosThetaM; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; - - if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) { - /* use GTR1 for clearcoat */ - D = D_GTR1(cosThetaM, bsdf->alpha_x); - - /* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */ - alpha2 = 0.0625f; - } - else { - /* use GTR2 otherwise */ - D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2)); - } + /* get half vector */ + float3 m = normalize(omega_in + I); + float alpha2 = alpha_x * alpha_y; + float D, G1o, G1i; + + if (alpha_x == alpha_y) { + /* isotropic + * eq. 20: (F*G*D)/(4*in*on) + * eq. 33: first we calculate D(m) */ + float cosThetaM = dot(N, m); + float cosThetaM2 = cosThetaM * cosThetaM; + float cosThetaM4 = cosThetaM2 * cosThetaM2; + float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; - /* eq. 34: now calculate G1(i,m) and G1(o,m) */ - G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); - G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); + if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) { + /* use GTR1 for clearcoat */ + D = D_GTR1(cosThetaM, bsdf->alpha_x); + + /* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */ + alpha2 = 0.0625f; } else { - /* anisotropic */ - float3 X, Y, Z = N; - make_orthonormals_tangent(Z, bsdf->T, &X, &Y); + /* use GTR2 otherwise */ + D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2)); + } - /* distribution */ - float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m)); - float slope_x = -local_m.x / (local_m.z * alpha_x); - float slope_y = -local_m.y / (local_m.z * alpha_y); - float slope_len = 1 + slope_x * slope_x + slope_y * slope_y; + /* eq. 34: now calculate G1(i,m) and G1(o,m) */ + G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); + G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); + } + else { + /* anisotropic */ + float3 X, Y, Z = N; + make_orthonormals_tangent(Z, bsdf->T, &X, &Y); - float cosThetaM = local_m.z; - float cosThetaM2 = cosThetaM * cosThetaM; - float cosThetaM4 = cosThetaM2 * cosThetaM2; + /* distribution */ + float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m)); + float slope_x = -local_m.x / (local_m.z * alpha_x); + float slope_y = -local_m.y / (local_m.z * alpha_y); + float slope_len = 1 + slope_x * slope_x + slope_y * slope_y; - D = 1 / ((slope_len * slope_len) * M_PI_F * alpha2 * cosThetaM4); + float cosThetaM = local_m.z; + float cosThetaM2 = cosThetaM * cosThetaM; + float cosThetaM4 = cosThetaM2 * cosThetaM2; - /* G1(i,m) and G1(o,m) */ - float tanThetaO2 = (1 - cosNO * cosNO) / (cosNO * cosNO); - float cosPhiO = dot(I, X); - float sinPhiO = dot(I, Y); + D = 1 / ((slope_len * slope_len) * M_PI_F * alpha2 * cosThetaM4); - float alphaO2 = (cosPhiO * cosPhiO) * (alpha_x * alpha_x) + - (sinPhiO * sinPhiO) * (alpha_y * alpha_y); - alphaO2 /= cosPhiO * cosPhiO + sinPhiO * sinPhiO; + /* G1(i,m) and G1(o,m) */ + float tanThetaO2 = (1 - cosNO * cosNO) / (cosNO * cosNO); + float cosPhiO = dot(I, X); + float sinPhiO = dot(I, Y); - G1o = 2 / (1 + safe_sqrtf(1 + alphaO2 * tanThetaO2)); + float alphaO2 = (cosPhiO * cosPhiO) * (alpha_x * alpha_x) + + (sinPhiO * sinPhiO) * (alpha_y * alpha_y); + alphaO2 /= cosPhiO * cosPhiO + sinPhiO * sinPhiO; - float tanThetaI2 = (1 - cosNI * cosNI) / (cosNI * cosNI); - float cosPhiI = dot(omega_in, X); - float sinPhiI = dot(omega_in, Y); + G1o = 2 / (1 + safe_sqrtf(1 + alphaO2 * tanThetaO2)); - float alphaI2 = (cosPhiI * cosPhiI) * (alpha_x * alpha_x) + - (sinPhiI * sinPhiI) * (alpha_y * alpha_y); - alphaI2 /= cosPhiI * cosPhiI + sinPhiI * sinPhiI; + float tanThetaI2 = (1 - cosNI * cosNI) / (cosNI * cosNI); + float cosPhiI = dot(omega_in, X); + float sinPhiI = dot(omega_in, Y); - G1i = 2 / (1 + safe_sqrtf(1 + alphaI2 * tanThetaI2)); - } + float alphaI2 = (cosPhiI * cosPhiI) * (alpha_x * alpha_x) + + (sinPhiI * sinPhiI) * (alpha_y * alpha_y); + alphaI2 /= cosPhiI * cosPhiI + sinPhiI * sinPhiI; - float G = G1o * G1i; + G1i = 2 / (1 + safe_sqrtf(1 + alphaI2 * tanThetaI2)); + } - /* eq. 20 */ - float common = D * 0.25f / cosNO; + float G = G1o * G1i; - Spectrum F = reflection_color(bsdf, omega_in, m); - if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) { - F *= 0.25f * bsdf->extra->clearcoat; - } + /* eq. 20 */ + float common = D * 0.25f / cosNO; - Spectrum out = F * G * common; + Spectrum F = reflection_color(bsdf, omega_in, m); + if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) { + F *= 0.25f * bsdf->extra->clearcoat; + } - /* eq. 2 in distribution of visible normals sampling - * `pm = Dw = G1o * dot(m, I) * D / dot(N, I);` */ + Spectrum out = F * G * common; - /* eq. 38 - but see also: - * eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf - * `pdf = pm * 0.25 / dot(m, I);` */ - *pdf = G1o * common; + /* eq. 2 in distribution of visible normals sampling + * `pm = Dw = G1o * dot(m, I) * D / dot(N, I);` */ - return out; - } + /* eq. 38 - but see also: + * eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf + * `pdf = pm * 0.25 / dot(m, I);` */ + *pdf = G1o * common; - return zero_spectrum(); + return out; } -ccl_device Spectrum bsdf_microfacet_ggx_eval_transmit(ccl_private const ShaderClosure *sc, +ccl_device Spectrum bsdf_microfacet_ggx_eval_transmit(ccl_private const MicrofacetBsdf *bsdf, + const float3 N, const float3 I, const float3 omega_in, - ccl_private float *pdf) + ccl_private float *pdf, + const float alpha_x, + const float alpha_y, + const float cosNO, + const float cosNI) { - ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; - float alpha_x = bsdf->alpha_x; - float alpha_y = bsdf->alpha_y; - float m_eta = bsdf->ior; - bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; - float3 N = bsdf->N; - - if (!m_refractive || alpha_x * alpha_y <= 1e-7f) { - *pdf = 0.0f; - return zero_spectrum(); - } - - float cosNO = dot(N, I); - float cosNI = dot(N, omega_in); - if (cosNO <= 0 || cosNI >= 0) { *pdf = 0.0f; return zero_spectrum(); /* vectors on same side -- not possible */ } /* compute half-vector of the refraction (eq. 16) */ + float m_eta = bsdf->ior; float3 ht = -(m_eta * omega_in + I); float3 Ht = normalize(ht); float cosHO = dot(Ht, I); @@ -533,6 +516,30 @@ ccl_device Spectrum bsdf_microfacet_ggx_eval_transmit(ccl_private const ShaderCl return make_spectrum(out); } +ccl_device Spectrum bsdf_microfacet_ggx_eval(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) +{ + ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; + const float alpha_x = bsdf->alpha_x; + const float alpha_y = bsdf->alpha_y; + const bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; + const float3 N = bsdf->N; + const float cosNO = dot(N, I); + const float cosNI = dot(N, omega_in); + + if (((cosNI < 0.0f) != m_refractive) || alpha_x * alpha_y <= 1e-7f) { + *pdf = 0.0f; + return zero_spectrum(); + } + + return (cosNI < 0.0f) ? bsdf_microfacet_ggx_eval_transmit( + bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI) : + bsdf_microfacet_ggx_eval_reflect( + bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI); +} + ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg, ccl_private const ShaderClosure *sc, float3 Ng, @@ -811,111 +818,95 @@ ccl_device_inline float bsdf_beckmann_aniso_G1( return ((2.181f * a + 3.535f) * a) / ((2.577f * a + 2.276f) * a + 1.0f); } -ccl_device Spectrum bsdf_microfacet_beckmann_eval_reflect(ccl_private const ShaderClosure *sc, +ccl_device Spectrum bsdf_microfacet_beckmann_eval_reflect(ccl_private const MicrofacetBsdf *bsdf, + const float3 N, const float3 I, const float3 omega_in, - ccl_private float *pdf) + ccl_private float *pdf, + const float alpha_x, + const float alpha_y, + const float cosNO, + const float cosNI) { - ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; - float alpha_x = bsdf->alpha_x; - float alpha_y = bsdf->alpha_y; - bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; - float3 N = bsdf->N; - - if (m_refractive || alpha_x * alpha_y <= 1e-7f) { + if (!(cosNO > 0 && cosNI > 0)) { *pdf = 0.0f; return zero_spectrum(); } - float cosNO = dot(N, I); - float cosNI = dot(N, omega_in); - - if (cosNO > 0 && cosNI > 0) { - /* get half vector */ - float3 m = normalize(omega_in + I); - - float alpha2 = alpha_x * alpha_y; - float D, G1o, G1i; - - if (alpha_x == alpha_y) { - /* isotropic - * eq. 20: (F*G*D)/(4*in*on) - * eq. 25: first we calculate D(m) */ - float cosThetaM = dot(N, m); - float cosThetaM2 = cosThetaM * cosThetaM; - float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4); - - /* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */ - G1o = bsdf_beckmann_G1(alpha_x, cosNO); - G1i = bsdf_beckmann_G1(alpha_x, cosNI); - } - else { - /* anisotropic */ - float3 X, Y, Z = N; - make_orthonormals_tangent(Z, bsdf->T, &X, &Y); + /* get half vector */ + float3 m = normalize(omega_in + I); - /* distribution */ - float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m)); - float slope_x = -local_m.x / (local_m.z * alpha_x); - float slope_y = -local_m.y / (local_m.z * alpha_y); + float alpha2 = alpha_x * alpha_y; + float D, G1o, G1i; - float cosThetaM = local_m.z; - float cosThetaM2 = cosThetaM * cosThetaM; - float cosThetaM4 = cosThetaM2 * cosThetaM2; + if (alpha_x == alpha_y) { + /* isotropic + * eq. 20: (F*G*D)/(4*in*on) + * eq. 25: first we calculate D(m) */ + float cosThetaM = dot(N, m); + float cosThetaM2 = cosThetaM * cosThetaM; + float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; + float cosThetaM4 = cosThetaM2 * cosThetaM2; + D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4); + + /* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */ + G1o = bsdf_beckmann_G1(alpha_x, cosNO); + G1i = bsdf_beckmann_G1(alpha_x, cosNI); + } + else { + /* anisotropic */ + float3 X, Y, Z = N; + make_orthonormals_tangent(Z, bsdf->T, &X, &Y); - D = expf(-slope_x * slope_x - slope_y * slope_y) / (M_PI_F * alpha2 * cosThetaM4); + /* distribution */ + float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m)); + float slope_x = -local_m.x / (local_m.z * alpha_x); + float slope_y = -local_m.y / (local_m.z * alpha_y); - /* G1(i,m) and G1(o,m) */ - G1o = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNO, dot(I, X), dot(I, Y)); - G1i = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNI, dot(omega_in, X), dot(omega_in, Y)); - } + float cosThetaM = local_m.z; + float cosThetaM2 = cosThetaM * cosThetaM; + float cosThetaM4 = cosThetaM2 * cosThetaM2; - float G = G1o * G1i; + D = expf(-slope_x * slope_x - slope_y * slope_y) / (M_PI_F * alpha2 * cosThetaM4); - /* eq. 20 */ - float common = D * 0.25f / cosNO; - float out = G * common; + /* G1(i,m) and G1(o,m) */ + G1o = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNO, dot(I, X), dot(I, Y)); + G1i = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNI, dot(omega_in, X), dot(omega_in, Y)); + } - /* eq. 2 in distribution of visible normals sampling - * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */ + float G = G1o * G1i; - /* eq. 38 - but see also: - * eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf - * pdf = pm * 0.25 / dot(m, I); */ - *pdf = G1o * common; + /* eq. 20 */ + float common = D * 0.25f / cosNO; + float out = G * common; - return make_spectrum(out); - } + /* eq. 2 in distribution of visible normals sampling + * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */ + + /* eq. 38 - but see also: + * eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf + * pdf = pm * 0.25 / dot(m, I); */ + *pdf = G1o * common; - return zero_spectrum(); + return make_spectrum(out); } -ccl_device Spectrum bsdf_microfacet_beckmann_eval_transmit(ccl_private const ShaderClosure *sc, +ccl_device Spectrum bsdf_microfacet_beckmann_eval_transmit(ccl_private const MicrofacetBsdf *bsdf, + const float3 N, const float3 I, const float3 omega_in, - ccl_private float *pdf) + ccl_private float *pdf, + const float alpha_x, + const float alpha_y, + const float cosNO, + const float cosNI) { - ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; - float alpha_x = bsdf->alpha_x; - float alpha_y = bsdf->alpha_y; - float m_eta = bsdf->ior; - bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; - float3 N = bsdf->N; - - if (!m_refractive || alpha_x * alpha_y <= 1e-7f) { - *pdf = 0.0f; - return zero_spectrum(); - } - - float cosNO = dot(N, I); - float cosNI = dot(N, omega_in); - if (cosNO <= 0 || cosNI >= 0) { *pdf = 0.0f; return zero_spectrum(); } + + const float m_eta = bsdf->ior; /* compute half-vector of the refraction (eq. 16) */ float3 ht = -(m_eta * omega_in + I); float3 Ht = normalize(ht); @@ -950,6 +941,30 @@ ccl_device Spectrum bsdf_microfacet_beckmann_eval_transmit(ccl_private const Sha return make_spectrum(out); } +ccl_device Spectrum bsdf_microfacet_beckmann_eval(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) +{ + ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; + const float alpha_x = bsdf->alpha_x; + const float alpha_y = bsdf->alpha_y; + const bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; + const float3 N = bsdf->N; + const float cosNO = dot(N, I); + const float cosNI = dot(N, omega_in); + + if (((cosNI < 0.0f) != m_refractive) || alpha_x * alpha_y <= 1e-7f) { + *pdf = 0.0f; + return zero_spectrum(); + } + + return (cosNI < 0.0f) ? bsdf_microfacet_beckmann_eval_transmit( + bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI) : + bsdf_microfacet_beckmann_eval_reflect( + bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI); +} + ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg, ccl_private const ShaderClosure *sc, float3 Ng, |