Fixed remaining syntax errors in OSL files. node_sepcomb_rgb.osl is split into 2...
[blender.git] / intern / cycles / kernel / osl / bsdf_oren_nayar.cpp
index a42c81e78f3c036e81fadc778a5051350b338d9b..83d0e583695c43bde81b1c5d54bdc29bc840a88b 100644 (file)
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
-/*
- *     An implementation of Oren-Nayar reflectance model, public domain
- *             http://www1.cs.columbia.edu/CAVE/publications/pdfs/Oren_SIGGRAPH94.pdf
- *
- *     NOTE:
- *             BSDF = A + B * cos() * sin() * tan()
- *
- *             The parameter sigma means different from original.
- *             A and B are calculated by the following formula:
- *                     0 <= sigma <= 1
- *                     A =     1 / ((1 + sigma / 2) * pi);
- *                     B = sigma / ((1 + sigma / 2) * pi);
- *
- *             This formula is derived as following:
- *
- *             0. Normalize A-term and B-term of BSDF *individually*.
- *                B-term is normalized at maximum point: dot(L, N) = 0.
- *                     A = (1/pi) * A'
- *                     B = (2/pi) * B'
- *
- *             1. Solve the following equation:
- *                     A' + B' = 1
- *                     B / A = sigma
- */
-
 #include <OpenImageIO/fmath.h>
 #include <OSL/genclosure.h>
 #include "osl_closures.h"
+#include "util_math.h"
 
 CCL_NAMESPACE_BEGIN
 
 using namespace OSL;
 
 
-class OrenNayarClosure: public BSDFClosure {
+class OrenNayarClosure : public BSDFClosure {
 public:
        Vec3 m_N;
        float m_sigma;
        float m_a, m_b;
 
-       OrenNayarClosure(): BSDFClosure(Labels::DIFFUSE) {}
+       OrenNayarClosure() : BSDFClosure(Labels::DIFFUSE) {}
 
        void setup() {
                m_sigma = clamp(m_sigma, 0.0f, 1.0f);
-               m_a =    1.0f / ((1.0f + 0.5f * m_sigma) * M_PI);
-               m_b = m_sigma / ((1.0f + 0.5f * m_sigma) * M_PI);
+               
+               float div = 1.0f / (M_PI + ((3.0f * M_PI - 4.0f) / 6.0f) * m_sigma);
+
+               m_a =    1.0f * div;
+               m_b = m_sigma * div;
        }
 
-       bool mergeable(const ClosurePrimitiveother) const {
-               const OrenNayarClosure* comp = static_cast<const OrenNayarClosure*>(other);
+       bool mergeable(const ClosurePrimitive *other) const {
+               const OrenNayarClosure *comp = static_cast<const OrenNayarClosure *>(other);
                return
-                       m_N == comp->m_N &&
-                       m_sigma == comp->m_sigma &&
-                       BSDFClosure::mergeable(other);
+                   m_N == comp->m_N &&
+                   m_sigma == comp->m_sigma &&
+                   BSDFClosure::mergeable(other);
        }
 
        size_t memsize() const {
                return sizeof(*this);
        }
 
-       const charname() const {
+       const char *name() const {
                return "oren_nayar";
        }
 
@@ -108,13 +87,13 @@ public:
        }
 
        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 {
-               sample_uniform_hemisphere (m_N, omega_out, randu, randv, omega_in, pdf);
+           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 {
+               sample_uniform_hemisphere(m_N, omega_out, randu, randv, omega_in, pdf);
 
                if (Ng.dot(omega_in) > 0.0f) {
                        float is = get_intensity(m_N, omega_out, omega_in);
@@ -137,35 +116,20 @@ private:
        float get_intensity(Vec3 const& n, Vec3 const& v, Vec3 const& l) const {
                float nl = max(n.dot(l), 0.0f);
                float nv = max(n.dot(v), 0.0f);
-
-               Vec3 al = l - nl * n;
-               al.normalize();
-               Vec3 av = v - nv * n;
-               av.normalize();
-               float t = max(al.dot(av), 0.0f);
-
-               float cos_a, cos_b;
-               if (nl < nv) {
-                       cos_a = nl;
-                       cos_b = nv;
+               float t = l.dot(v) - nl * nv;
+               
+               if (t > 0.0f) {
+                       t /= max(nl, nv) + 1e-8f;
                }
-               else {
-                       cos_a = nv;
-                       cos_b = nl;
-               }
-
-               float sin_a = sqrtf(1.0f - cos_a * cos_a);
-               float tan_b = sqrtf(1.0f - cos_b * cos_b) / (cos_b + FLT_MIN);
-
-               return nl * (m_a + m_b * t * sin_a * tan_b);
+               return nl * (m_a + m_b * t);
        }
 };
 
 ClosureParam bsdf_oren_nayar_params[] = {
-       CLOSURE_VECTOR_PARAM    (OrenNayarClosure, m_N),
-       CLOSURE_FLOAT_PARAM             (OrenNayarClosure, m_sigma),
-       CLOSURE_STRING_KEYPARAM ("label"),
-       CLOSURE_FINISH_PARAM    (OrenNayarClosure)
+       CLOSURE_VECTOR_PARAM(OrenNayarClosure, m_N),
+       CLOSURE_FLOAT_PARAM(OrenNayarClosure, m_sigma),
+       CLOSURE_STRING_KEYPARAM("label"),
+       CLOSURE_FINISH_PARAM(OrenNayarClosure)
 };
 
 CLOSURE_PREPARE(bsdf_oren_nayar_prepare, OrenNayarClosure)