From 273f5226da53654039bddbf94210c458cfcc1e71 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 2 May 2013 22:05:57 +0000 Subject: Fix #35160: cycles was rendering glossy BSDF's with zero roughness too rough after a bugfix for precision issues with low roughness. Now it renders them as perfectly sharp which avoids the problematic calculations rather than increasing the roughness. --- intern/cycles/kernel/closure/bsdf_microfacet.h | 223 ++++++++++++++----------- 1 file changed, 126 insertions(+), 97 deletions(-) diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index b771e02f131..c586c1e3311 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -46,7 +46,7 @@ __device int bsdf_microfacet_ggx_setup(ShaderClosure *sc) { float ag = sc->data0; - float m_ag = clamp(ag, 1e-3f, 1.0f); + float m_ag = clamp(ag, 0.0f, 1.0f); sc->data0 = m_ag; sc->type = CLOSURE_BSDF_MICROFACET_GGX_ID; @@ -59,7 +59,7 @@ __device int bsdf_microfacet_ggx_refraction_setup(ShaderClosure *sc) float ag = sc->data0; float eta = sc->data1; - float m_ag = clamp(ag, 1e-3f, 1.0f); + float m_ag = clamp(ag, 0.0f, 1.0f); float m_eta = eta; sc->data0 = m_ag; @@ -82,7 +82,8 @@ __device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, const int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; float3 N = sc->N; - if(m_refractive) return make_float3 (0, 0, 0); + if(m_refractive || m_ag <= 1e-4f) + return make_float3 (0, 0, 0); float cosNO = dot(N, I); float cosNI = dot(N, omega_in); if(cosNI > 0 && cosNO > 0) { @@ -119,7 +120,8 @@ __device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, const int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; float3 N = sc->N; - if(!m_refractive) return make_float3 (0, 0, 0); + if(!m_refractive || m_ag <= 1e-4f) + return make_float3 (0, 0, 0); float cosNO = dot(N, I); float cosNI = dot(N, omega_in); if(cosNO <= 0 || cosNI >= 0) @@ -176,26 +178,33 @@ __device int bsdf_microfacet_ggx_sample(const ShaderClosure *sc, float3 Ng, floa // eq. 39 - compute actual reflected direction *omega_in = 2 * cosMO * m - I; if(dot(Ng, *omega_in) > 0) { - // microfacet normal is visible to this ray - // eq. 33 - float cosThetaM2 = cosThetaM * cosThetaM; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2)); - // eq. 24 - float pm = D * cosThetaM; - // convert into pdf of the sampled direction - // eq. 38 - but see also: - // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf - *pdf = pm * 0.25f / cosMO; - // eval BRDF*cosNI - float cosNI = dot(N, *omega_in); - // eq. 34: now calculate G1(i,m) and G1(o,m) - float G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); - float G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); - float G = G1o * G1i; - // eq. 20: (F*G*D)/(4*in*on) - float out = (G * D) * 0.25f / cosNO; - *eval = make_float3(out, out, out); + if (m_ag <= 1e-4f) { + *pdf = 1; + *eval = make_float3(1, 1, 1); + } + else { + // microfacet normal is visible to this ray + // eq. 33 + float cosThetaM2 = cosThetaM * cosThetaM; + float cosThetaM4 = cosThetaM2 * cosThetaM2; + float D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2)); + // eq. 24 + float pm = D * cosThetaM; + // convert into pdf of the sampled direction + // eq. 38 - but see also: + // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf + *pdf = pm * 0.25f / cosMO; + // eval BRDF*cosNI + float cosNI = dot(N, *omega_in); + // eq. 34: now calculate G1(i,m) and G1(o,m) + float G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); + float G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); + float G = G1o * G1i; + // eq. 20: (F*G*D)/(4*in*on) + float out = (G * D) * 0.25f / cosNO; + *eval = make_float3(out, out, out); + } + #ifdef __RAY_DIFFERENTIALS__ *domega_in_dx = (2 * dot(m, dIdx)) * m - dIdx; *domega_in_dy = (2 * dot(m, dIdy)) * m - dIdy; @@ -224,27 +233,34 @@ __device int bsdf_microfacet_ggx_sample(const ShaderClosure *sc, float3 Ng, floa *domega_in_dx = dTdx; *domega_in_dy = dTdy; #endif - // eq. 33 - float cosThetaM2 = cosThetaM * cosThetaM; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2)); - // eq. 24 - float pm = D * cosThetaM; - // eval BRDF*cosNI - float cosNI = dot(N, *omega_in); - // eq. 34: now calculate G1(i,m) and G1(o,m) - float G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); - float G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); - float G = G1o * G1i; - // eq. 21 - float cosHI = dot(m, *omega_in); - float cosHO = dot(m, I); - float Ht2 = m_eta * cosHI + cosHO; - Ht2 *= Ht2; - float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2); - // eq. 38 and eq. 17 - *pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2; - *eval = make_float3(out, out, out); + + if (m_ag <= 1e-4f) { + *pdf = 1; + *eval = make_float3(1, 1, 1); + } + else { + // eq. 33 + float cosThetaM2 = cosThetaM * cosThetaM; + float cosThetaM4 = cosThetaM2 * cosThetaM2; + float D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2)); + // eq. 24 + float pm = D * cosThetaM; + // eval BRDF*cosNI + float cosNI = dot(N, *omega_in); + // eq. 34: now calculate G1(i,m) and G1(o,m) + float G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); + float G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); + float G = G1o * G1i; + // eq. 21 + float cosHI = dot(m, *omega_in); + float cosHO = dot(m, I); + float Ht2 = m_eta * cosHI + cosHO; + Ht2 *= Ht2; + float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2); + // eq. 38 and eq. 17 + *pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2; + *eval = make_float3(out, out, out); + } } } } @@ -256,7 +272,7 @@ __device int bsdf_microfacet_ggx_sample(const ShaderClosure *sc, float3 Ng, floa __device int bsdf_microfacet_beckmann_setup(ShaderClosure *sc) { float ab = sc->data0; - float m_ab = clamp(ab, 1e-3f, 1.0f); + float m_ab = clamp(ab, 0.0f, 1.0f); sc->data0 = m_ab; @@ -268,7 +284,7 @@ __device int bsdf_microfacet_beckmann_refraction_setup(ShaderClosure *sc) { float ab = sc->data0; float eta = sc->data1; - float m_ab = clamp(ab, 1e-3f, 1.0f); + float m_ab = clamp(ab, 0.0f, 1.0f); float m_eta = eta; sc->data0 = m_ab; @@ -291,7 +307,8 @@ __device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc, c int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; float3 N = sc->N; - if(m_refractive) return make_float3 (0, 0, 0); + if(m_refractive || m_ab <= 1e-4f) + return make_float3 (0, 0, 0); float cosNO = dot(N, I); float cosNI = dot(N, omega_in); if(cosNO > 0 && cosNI > 0) { @@ -330,7 +347,8 @@ __device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc, int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; float3 N = sc->N; - if(!m_refractive) return make_float3 (0, 0, 0); + if(!m_refractive || m_ab <= 1e-4f) + return make_float3 (0, 0, 0); float cosNO = dot(N, I); float cosNI = dot(N, omega_in); if(cosNO <= 0 || cosNI >= 0) @@ -390,29 +408,35 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderClosure *sc, float3 Ng, // eq. 39 - compute actual reflected direction *omega_in = 2 * cosMO * m - I; if(dot(Ng, *omega_in) > 0) { - // microfacet normal is visible to this ray - // eq. 25 - float cosThetaM2 = cosThetaM * cosThetaM; - float tanThetaM2 = tanThetaM * tanThetaM; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4); - // eq. 24 - float pm = D * cosThetaM; - // convert into pdf of the sampled direction - // eq. 38 - but see also: - // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf - *pdf = pm * 0.25f / cosMO; - // Eval BRDF*cosNI - float cosNI = dot(N, *omega_in); - // eq. 26, 27: now calculate G1(i,m) and G1(o,m) - float ao = 1 / (safe_sqrtf(alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); - float ai = 1 / (safe_sqrtf(alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); - float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f; - float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f; - float G = G1o * G1i; - // eq. 20: (F*G*D)/(4*in*on) - float out = (G * D) * 0.25f / cosNO; - *eval = make_float3(out, out, out); + if (m_ab <= 1e-4f) { + *pdf = 1; + *eval = make_float3(1, 1, 1); + } + else { + // microfacet normal is visible to this ray + // eq. 25 + float cosThetaM2 = cosThetaM * cosThetaM; + float tanThetaM2 = tanThetaM * tanThetaM; + float cosThetaM4 = cosThetaM2 * cosThetaM2; + float D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4); + // eq. 24 + float pm = D * cosThetaM; + // convert into pdf of the sampled direction + // eq. 38 - but see also: + // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf + *pdf = pm * 0.25f / cosMO; + // Eval BRDF*cosNI + float cosNI = dot(N, *omega_in); + // eq. 26, 27: now calculate G1(i,m) and G1(o,m) + float ao = 1 / (m_ab * safe_sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO))); + float ai = 1 / (m_ab * safe_sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI))); + float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f; + float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f; + float G = G1o * G1i; + // eq. 20: (F*G*D)/(4*in*on) + float out = (G * D) * 0.25f / cosNO; + *eval = make_float3(out, out, out); + } #ifdef __RAY_DIFFERENTIALS__ *domega_in_dx = (2 * dot(m, dIdx)) * m - dIdx; *domega_in_dy = (2 * dot(m, dIdy)) * m - dIdy; @@ -441,31 +465,36 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderClosure *sc, float3 Ng, *domega_in_dx = dTdx; *domega_in_dy = dTdy; #endif - - // eq. 33 - float cosThetaM2 = cosThetaM * cosThetaM; - float tanThetaM2 = tanThetaM * tanThetaM; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4); - // eq. 24 - float pm = D * cosThetaM; - // eval BRDF*cosNI - float cosNI = dot(N, *omega_in); - // eq. 26, 27: now calculate G1(i,m) and G1(o,m) - float ao = 1 / (safe_sqrtf(alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); - float ai = 1 / (safe_sqrtf(alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); - float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f; - float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f; - float G = G1o * G1i; - // eq. 21 - float cosHI = dot(m, *omega_in); - float cosHO = dot(m, I); - float Ht2 = m_eta * cosHI + cosHO; - Ht2 *= Ht2; - float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2); - // eq. 38 and eq. 17 - *pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2; - *eval = make_float3(out, out, out); + if (m_ab <= 1e-4f) { + *pdf = 1; + *eval = make_float3(1, 1, 1); + } + else { + // eq. 33 + float cosThetaM2 = cosThetaM * cosThetaM; + float tanThetaM2 = tanThetaM * tanThetaM; + float cosThetaM4 = cosThetaM2 * cosThetaM2; + float D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4); + // eq. 24 + float pm = D * cosThetaM; + // eval BRDF*cosNI + float cosNI = dot(N, *omega_in); + // eq. 26, 27: now calculate G1(i,m) and G1(o,m) + float ao = 1 / (m_ab * safe_sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO))); + float ai = 1 / (m_ab * safe_sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI))); + float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f; + float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f; + float G = G1o * G1i; + // eq. 21 + float cosHI = dot(m, *omega_in); + float cosHO = dot(m, I); + float Ht2 = m_eta * cosHI + cosHO; + Ht2 *= Ht2; + float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2); + // eq. 38 and eq. 17 + *pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2; + *eval = make_float3(out, out, out); + } } } } -- cgit v1.2.3