diff options
Diffstat (limited to 'intern/cycles/kernel/osl/bsdf_westin.cpp')
-rw-r--r-- | intern/cycles/kernel/osl/bsdf_westin.cpp | 346 |
1 files changed, 175 insertions, 171 deletions
diff --git a/intern/cycles/kernel/osl/bsdf_westin.cpp b/intern/cycles/kernel/osl/bsdf_westin.cpp index d322f6a7f7e..a476e8045f7 100644 --- a/intern/cycles/kernel/osl/bsdf_westin.cpp +++ b/intern/cycles/kernel/osl/bsdf_westin.cpp @@ -44,193 +44,197 @@ using namespace OSL; class WestinBackscatterClosure : public BSDFClosure { public: - Vec3 m_N; - float m_roughness; - float m_invroughness; - WestinBackscatterClosure() : BSDFClosure(Labels::GLOSSY) { } + Vec3 m_N; + float m_roughness; + float m_invroughness; + WestinBackscatterClosure() : BSDFClosure(Labels::GLOSSY) {} - void setup() - { + void setup() + { m_roughness = clamp(m_roughness, 1e-5f, 1.0f); - m_invroughness = m_roughness > 0 ? 1 / m_roughness : 0; - } - - bool mergeable (const ClosurePrimitive *other) const { - const WestinBackscatterClosure *comp = (const WestinBackscatterClosure *)other; - return m_N == comp->m_N && m_roughness == comp->m_roughness && - BSDFClosure::mergeable(other); - } - - size_t memsize () const { return sizeof(*this); } - - const char *name () const { return "westin_backscatter"; } - - void print_on (std::ostream &out) const - { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_roughness; - out << ")"; - } - - float albedo (const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const - { - // pdf is implicitly 0 (no indirect sampling) - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNO > 0 && cosNI > 0) { - float cosine = omega_out.dot(omega_in); - pdf = cosine > 0 ? (m_invroughness + 1) * powf(cosine, m_invroughness) : 0; - pdf *= 0.5f * float(M_1_PI); - return Color3 (pdf, pdf, pdf); - } - return Color3 (0, 0, 0); - } - - Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const - { - return Color3 (0, 0, 0); - } - - ustring sample (const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - float cosNO = m_N.dot(omega_out); - if (cosNO > 0) { - domega_in_dx = domega_out_dx; - domega_in_dy = domega_out_dy; - Vec3 T, B; - make_orthonormals (omega_out, T, B); - float phi = 2 * (float) M_PI * randu; - float cosTheta = powf(randv, 1 / (m_invroughness + 1)); - float sinTheta2 = 1 - cosTheta * cosTheta; - float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0; - omega_in = (cosf(phi) * sinTheta) * T + - (sinf(phi) * sinTheta) * B + - ( cosTheta) * omega_out; - if (Ng.dot(omega_in) > 0) - { - // common terms for pdf and eval - float cosNI = m_N.dot(omega_in); - // make sure the direction we chose is still in the right hemisphere - if (cosNI > 0) - { - pdf = 0.5f * (float) M_1_PI * powf(cosTheta, m_invroughness); - pdf = (m_invroughness + 1) * pdf; - eval.setValue(pdf, pdf, pdf); - // Since there is some blur to this reflection, make the - // derivatives a bit bigger. In theory this varies with the - // exponent but the exact relationship is complex and - // requires more ops than are practical. - domega_in_dx *= 10; - domega_in_dy *= 10; - } - } - } - return Labels::REFLECT; - } + m_invroughness = m_roughness > 0 ? 1 / m_roughness : 0; + } + + bool mergeable(const ClosurePrimitive *other) const { + const WestinBackscatterClosure *comp = (const WestinBackscatterClosure *)other; + return m_N == comp->m_N && m_roughness == comp->m_roughness && + BSDFClosure::mergeable(other); + } + + size_t memsize() const { return sizeof(*this); } + + const char *name() const { return "westin_backscatter"; } + + void print_on(std::ostream &out) const + { + out << name() << " ("; + out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; + out << m_roughness; + out << ")"; + } + + float albedo(const Vec3 &omega_out) const + { + return 1.0f; + } + + Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const + { + // pdf is implicitly 0 (no indirect sampling) + float cosNO = m_N.dot(omega_out); + float cosNI = m_N.dot(omega_in); + if (cosNO > 0 && cosNI > 0) { + float cosine = omega_out.dot(omega_in); + pdf = cosine > 0 ? (m_invroughness + 1) * powf(cosine, m_invroughness) : 0; + pdf *= 0.5f * float(M_1_PI); + return Color3(pdf, pdf, pdf); + } + return Color3(0, 0, 0); + } + + Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const + { + return Color3(0, 0, 0); + } + + ustring sample(const Vec3 &Ng, + const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, + float randu, float randv, + Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, + float &pdf, Color3 &eval) const + { + float cosNO = m_N.dot(omega_out); + if (cosNO > 0) { + domega_in_dx = domega_out_dx; + domega_in_dy = domega_out_dy; + Vec3 T, B; + make_orthonormals(omega_out, T, B); + float phi = 2 * (float) M_PI * randu; + float cosTheta = powf(randv, 1 / (m_invroughness + 1)); + float sinTheta2 = 1 - cosTheta * cosTheta; + float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0; + omega_in = (cosf(phi) * sinTheta) * T + + (sinf(phi) * sinTheta) * B + + (cosTheta) * omega_out; + if (Ng.dot(omega_in) > 0) + { + // common terms for pdf and eval + float cosNI = m_N.dot(omega_in); + // make sure the direction we chose is still in the right hemisphere + if (cosNI > 0) + { + pdf = 0.5f * (float) M_1_PI * powf(cosTheta, m_invroughness); + pdf = (m_invroughness + 1) * pdf; + eval.setValue(pdf, pdf, pdf); + // Since there is some blur to this reflection, make the + // derivatives a bit bigger. In theory this varies with the + // exponent but the exact relationship is complex and + // requires more ops than are practical. + domega_in_dx *= 10; + domega_in_dy *= 10; + } + } + } + return Labels::REFLECT; + } }; class WestinSheenClosure : public BSDFClosure { public: - Vec3 m_N; - float m_edginess; + Vec3 m_N; + float m_edginess; // float m_normalization; - WestinSheenClosure() : BSDFClosure(Labels::DIFFUSE) { } - - void setup() {}; - - bool mergeable (const ClosurePrimitive *other) const { - const WestinSheenClosure *comp = (const WestinSheenClosure *)other; - return m_N == comp->m_N && m_edginess == comp->m_edginess && - BSDFClosure::mergeable(other); - } - - size_t memsize () const { return sizeof(*this); } - - const char *name () const { return "westin_sheen"; } - - void print_on (std::ostream &out) const - { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_edginess; - out << ")"; - } - - float albedo (const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const - { - // pdf is implicitly 0 (no indirect sampling) - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNO > 0 && cosNI > 0) { - float sinNO2 = 1 - cosNO * cosNO; - pdf = cosNI * float(M_1_PI); - float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * pdf : 0; - return Color3 (westin, westin, westin); - } - return Color3 (0, 0, 0); - } - - Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const - { - return Color3 (0, 0, 0); - } - - ustring sample (const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - // we are viewing the surface from the right side - send a ray out with cosine - // distribution over the hemisphere - sample_cos_hemisphere (m_N, omega_out, randu, randv, omega_in, pdf); - if (Ng.dot(omega_in) > 0) { - // TODO: account for sheen when sampling - float cosNO = m_N.dot(omega_out); - float sinNO2 = 1 - cosNO * cosNO; - float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * pdf : 0; - eval.setValue(westin, westin, westin); - // TODO: find a better approximation for the diffuse bounce - domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; - domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; - domega_in_dx *= 125; - domega_in_dy *= 125; - } else - pdf = 0; - return Labels::REFLECT; - } + WestinSheenClosure() : BSDFClosure(Labels::DIFFUSE) {} + + void setup() {}; + + bool mergeable(const ClosurePrimitive *other) const { + const WestinSheenClosure *comp = (const WestinSheenClosure *)other; + return m_N == comp->m_N && m_edginess == comp->m_edginess && + BSDFClosure::mergeable(other); + } + + size_t memsize() const { return sizeof(*this); } + + const char *name() const { return "westin_sheen"; } + + void print_on(std::ostream &out) const + { + out << name() << " ("; + out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; + out << m_edginess; + out << ")"; + } + + float albedo(const Vec3 &omega_out) const + { + return 1.0f; + } + + Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const + { + // pdf is implicitly 0 (no indirect sampling) + float cosNO = m_N.dot(omega_out); + float cosNI = m_N.dot(omega_in); + if (cosNO > 0 && cosNI > 0) { + float sinNO2 = 1 - cosNO * cosNO; + pdf = cosNI * float(M_1_PI); + float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * pdf : 0; + return Color3(westin, westin, westin); + } + return Color3(0, 0, 0); + } + + Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const + { + return Color3(0, 0, 0); + } + + ustring sample(const Vec3 &Ng, + const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, + float randu, float randv, + Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, + float &pdf, Color3 &eval) const + { + // we are viewing the surface from the right side - send a ray out with cosine + // distribution over the hemisphere + sample_cos_hemisphere(m_N, omega_out, randu, randv, omega_in, pdf); + if (Ng.dot(omega_in) > 0) { + // TODO: account for sheen when sampling + float cosNO = m_N.dot(omega_out); + float sinNO2 = 1 - cosNO * cosNO; + float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * pdf : 0; + eval.setValue(westin, westin, westin); + // TODO: find a better approximation for the diffuse bounce + domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; + domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; + domega_in_dx *= 125; + domega_in_dy *= 125; + } + else { + pdf = 0; + } + return Labels::REFLECT; + } }; ClosureParam bsdf_westin_backscatter_params[] = { - CLOSURE_VECTOR_PARAM(WestinBackscatterClosure, m_N), - CLOSURE_FLOAT_PARAM (WestinBackscatterClosure, m_roughness), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(WestinBackscatterClosure) }; + CLOSURE_VECTOR_PARAM(WestinBackscatterClosure, m_N), + CLOSURE_FLOAT_PARAM(WestinBackscatterClosure, m_roughness), + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(WestinBackscatterClosure) +}; ClosureParam bsdf_westin_sheen_params[] = { - CLOSURE_VECTOR_PARAM(WestinSheenClosure, m_N), - CLOSURE_FLOAT_PARAM (WestinSheenClosure, m_edginess), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(WestinSheenClosure) }; + CLOSURE_VECTOR_PARAM(WestinSheenClosure, m_N), + CLOSURE_FLOAT_PARAM(WestinSheenClosure, m_edginess), + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(WestinSheenClosure) +}; CLOSURE_PREPARE(bsdf_westin_backscatter_prepare, WestinBackscatterClosure) CLOSURE_PREPARE(bsdf_westin_sheen_prepare, WestinSheenClosure) |