Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/kernel/osl')
-rw-r--r--intern/cycles/kernel/osl/CMakeLists.txt33
-rw-r--r--intern/cycles/kernel/osl/background.cpp100
-rw-r--r--intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp175
-rw-r--r--intern/cycles/kernel/osl/bsdf_diffuse.cpp181
-rw-r--r--intern/cycles/kernel/osl/bsdf_microfacet.cpp533
-rw-r--r--intern/cycles/kernel/osl/bsdf_reflection.cpp108
-rw-r--r--intern/cycles/kernel/osl/bsdf_refraction.cpp120
-rw-r--r--intern/cycles/kernel/osl/bsdf_transparent.cpp97
-rw-r--r--intern/cycles/kernel/osl/bsdf_ward.cpp222
-rw-r--r--intern/cycles/kernel/osl/bsdf_westin.cpp239
-rw-r--r--intern/cycles/kernel/osl/bssrdf.cpp105
-rw-r--r--intern/cycles/kernel/osl/debug.cpp80
-rw-r--r--intern/cycles/kernel/osl/emissive.cpp107
-rw-r--r--intern/cycles/kernel/osl/nodes/CMakeLists.txt69
-rw-r--r--intern/cycles/kernel/osl/nodes/node_add_closure.osl28
-rw-r--r--intern/cycles/kernel/osl/nodes/node_attribute.osl43
-rw-r--r--intern/cycles/kernel/osl/nodes/node_background.osl28
-rw-r--r--intern/cycles/kernel/osl/nodes/node_blend_texture.osl78
-rw-r--r--intern/cycles/kernel/osl/nodes/node_bump.osl46
-rw-r--r--intern/cycles/kernel/osl/nodes/node_clouds_texture.osl42
-rw-r--r--intern/cycles/kernel/osl/nodes/node_convert_from_color.osl33
-rw-r--r--intern/cycles/kernel/osl/nodes/node_convert_from_float.osl33
-rw-r--r--intern/cycles/kernel/osl/nodes/node_convert_from_normal.osl33
-rw-r--r--intern/cycles/kernel/osl/nodes/node_convert_from_point.osl33
-rw-r--r--intern/cycles/kernel/osl/nodes/node_convert_from_vector.osl33
-rw-r--r--intern/cycles/kernel/osl/nodes/node_diffuse_bsdf.osl28
-rw-r--r--intern/cycles/kernel/osl/nodes/node_distorted_noise_texture.osl46
-rw-r--r--intern/cycles/kernel/osl/nodes/node_emission.osl32
-rw-r--r--intern/cycles/kernel/osl/nodes/node_environment_texture.osl28
-rw-r--r--intern/cycles/kernel/osl/nodes/node_fresnel.h21
-rw-r--r--intern/cycles/kernel/osl/nodes/node_fresnel.osl30
-rw-r--r--intern/cycles/kernel/osl/nodes/node_geometry.osl50
-rw-r--r--intern/cycles/kernel/osl/nodes/node_glass_bsdf.osl41
-rw-r--r--intern/cycles/kernel/osl/nodes/node_glossy_bsdf.osl45
-rw-r--r--intern/cycles/kernel/osl/nodes/node_image_texture.osl28
-rw-r--r--intern/cycles/kernel/osl/nodes/node_light_path.osl36
-rw-r--r--intern/cycles/kernel/osl/nodes/node_magic_texture.osl103
-rw-r--r--intern/cycles/kernel/osl/nodes/node_mapping.osl28
-rw-r--r--intern/cycles/kernel/osl/nodes/node_marble_texture.osl58
-rw-r--r--intern/cycles/kernel/osl/nodes/node_math.osl84
-rw-r--r--intern/cycles/kernel/osl/nodes/node_mix.osl388
-rw-r--r--intern/cycles/kernel/osl/nodes/node_mix_closure.osl30
-rw-r--r--intern/cycles/kernel/osl/nodes/node_musgrave_texture.osl218
-rw-r--r--intern/cycles/kernel/osl/nodes/node_noise_texture.osl36
-rw-r--r--intern/cycles/kernel/osl/nodes/node_output_displacement.osl25
-rw-r--r--intern/cycles/kernel/osl/nodes/node_output_surface.osl25
-rw-r--r--intern/cycles/kernel/osl/nodes/node_output_volume.osl25
-rw-r--r--intern/cycles/kernel/osl/nodes/node_sky_texture.osl162
-rw-r--r--intern/cycles/kernel/osl/nodes/node_stucci_texture.osl49
-rw-r--r--intern/cycles/kernel/osl/nodes/node_texture.h251
-rw-r--r--intern/cycles/kernel/osl/nodes/node_texture_coordinate.osl66
-rw-r--r--intern/cycles/kernel/osl/nodes/node_translucent_bsdf.osl28
-rw-r--r--intern/cycles/kernel/osl/nodes/node_transparent_bsdf.osl28
-rw-r--r--intern/cycles/kernel/osl/nodes/node_value.osl33
-rw-r--r--intern/cycles/kernel/osl/nodes/node_vector_math.osl53
-rw-r--r--intern/cycles/kernel/osl/nodes/node_velvet_bsdf.osl40
-rw-r--r--intern/cycles/kernel/osl/nodes/node_voronoi_texture.osl82
-rw-r--r--intern/cycles/kernel/osl/nodes/node_ward_bsdf.osl30
-rw-r--r--intern/cycles/kernel/osl/nodes/node_wood_texture.osl63
-rw-r--r--intern/cycles/kernel/osl/nodes/stdosl.h471
-rw-r--r--intern/cycles/kernel/osl/osl_closures.cpp93
-rw-r--r--intern/cycles/kernel/osl/osl_closures.h114
-rw-r--r--intern/cycles/kernel/osl/osl_globals.h74
-rw-r--r--intern/cycles/kernel/osl/osl_services.cpp424
-rw-r--r--intern/cycles/kernel/osl/osl_services.h111
-rw-r--r--intern/cycles/kernel/osl/osl_shader.cpp559
-rw-r--r--intern/cycles/kernel/osl/osl_shader.h87
-rw-r--r--intern/cycles/kernel/osl/vol_subsurface.cpp135
68 files changed, 6957 insertions, 0 deletions
diff --git a/intern/cycles/kernel/osl/CMakeLists.txt b/intern/cycles/kernel/osl/CMakeLists.txt
new file mode 100644
index 00000000000..3ca3fa4cd6b
--- /dev/null
+++ b/intern/cycles/kernel/osl/CMakeLists.txt
@@ -0,0 +1,33 @@
+
+INCLUDE_DIRECTORIES(. ../ ../svm ../../render ../../util ../../device)
+
+SET(sources
+ background.cpp
+ bsdf_ashikhmin_velvet.cpp
+ bsdf_diffuse.cpp
+ bsdf_microfacet.cpp
+ bsdf_reflection.cpp
+ bsdf_refraction.cpp
+ bsdf_transparent.cpp
+ bsdf_ward.cpp
+ bsdf_westin.cpp
+ bssrdf.cpp
+ debug.cpp
+ emissive.cpp
+ osl_closures.cpp
+ osl_services.cpp
+ osl_shader.cpp
+ vol_subsurface.cpp)
+
+SET(headers
+ osl_closures.h
+ osl_globals.h
+ osl_services.h
+ osl_shader.h)
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${RTTI_DISABLE_FLAGS}")
+
+ADD_LIBRARY(kernel_osl ${sources} ${headers})
+
+ADD_SUBDIRECTORY(nodes)
+
diff --git a/intern/cycles/kernel/osl/background.cpp b/intern/cycles/kernel/osl/background.cpp
new file mode 100644
index 00000000000..c35119ae9cf
--- /dev/null
+++ b/intern/cycles/kernel/osl/background.cpp
@@ -0,0 +1,100 @@
+/*
+ * Adapted from Open Shading Language with this license:
+ *
+ * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
+ * All Rights Reserved.
+ *
+ * Modifications Copyright 2011, Blender Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Sony Pictures Imageworks nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <OpenImageIO/fmath.h>
+
+#include <OSL/genclosure.h>
+
+#include "osl_closures.h"
+
+CCL_NAMESPACE_BEGIN
+
+using namespace OSL;
+
+/// Generic background closure
+///
+/// We only have a background closure for the shaders
+/// to return a color in background shaders. No methods,
+/// only the weight is taking into account
+///
+class GenericBackgroundClosure : public BackgroundClosure {
+public:
+ GenericBackgroundClosure() { }
+
+ void setup() {};
+
+ size_t memsize () const { return sizeof(*this); }
+
+ const char *name () const { return "background"; }
+
+ void print_on (std::ostream &out) const {
+ out << name() << " ()";
+ }
+
+};
+
+
+/// Holdout closure
+///
+/// This will be used by the shader to mark the
+/// amount of holdout for the current shading
+/// point. No parameters, only the weight will be
+/// used
+///
+class HoldoutClosure : ClosurePrimitive {
+public:
+ HoldoutClosure () : ClosurePrimitive (Holdout) { }
+
+ void setup() {};
+
+ size_t memsize () const { return sizeof(*this); }
+
+ const char *name () const { return "holdout"; }
+
+ void print_on (std::ostream &out) const {
+ out << name() << " ()";
+ }
+};
+
+ClosureParam closure_background_params[] = {
+ CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_FINISH_PARAM(GenericBackgroundClosure) };
+
+CLOSURE_PREPARE(closure_background_prepare, GenericBackgroundClosure)
+
+ClosureParam closure_holdout_params[] = {
+ CLOSURE_FINISH_PARAM(HoldoutClosure) };
+
+CLOSURE_PREPARE(closure_holdout_prepare, HoldoutClosure)
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp b/intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp
new file mode 100644
index 00000000000..a38c5b55cf5
--- /dev/null
+++ b/intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp
@@ -0,0 +1,175 @@
+/*
+ * Adapted from Open Shading Language with this license:
+ *
+ * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
+ * All Rights Reserved.
+ *
+ * Modifications Copyright 2011, Blender Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Sony Pictures Imageworks nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <OpenImageIO/fmath.h>
+
+#include <OSL/genclosure.h>
+
+#include "osl_closures.h"
+
+CCL_NAMESPACE_BEGIN
+
+using namespace OSL;
+
+class AshikhminVelvetClosure : public BSDFClosure {
+public:
+ Vec3 m_N;
+ float m_sigma;
+ float m_invsigma2;
+
+ AshikhminVelvetClosure() : BSDFClosure(Labels::DIFFUSE) { }
+
+ void setup()
+ {
+ m_sigma = std::max(m_sigma, 0.01f);
+ m_invsigma2 = 1.0f/(m_sigma * m_sigma);
+ }
+
+ bool mergeable (const ClosurePrimitive *other) const {
+ const AshikhminVelvetClosure *comp = (const AshikhminVelvetClosure *)other;
+ return m_N == comp->m_N && m_sigma == comp->m_sigma &&
+ BSDFClosure::mergeable(other);
+ }
+
+ size_t memsize () const { return sizeof(*this); }
+
+ const char *name () const { return "ashikhmin_velvet"; }
+
+ void print_on (std::ostream &out) const
+ {
+ out << name() << " (";
+ out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
+ out << m_sigma;
+ 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
+ {
+ float cosNO = m_N.dot(omega_out);
+ float cosNI = m_N.dot(omega_in);
+ if (cosNO > 0 && cosNI > 0) {
+ Vec3 H = omega_in + omega_out;
+ H.normalize();
+
+ float cosNH = m_N.dot(H);
+ float cosHO = fabsf(omega_out.dot(H));
+
+ float cosNHdivHO = cosNH / cosHO;
+ cosNHdivHO = std::max(cosNHdivHO, 0.00001f);
+
+ float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
+ float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
+
+ float sinNH2 = 1 - cosNH * cosNH;
+ float sinNH4 = sinNH2 * sinNH2;
+ float cotangent2 = (cosNH * cosNH) / sinNH2;
+
+ float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * float(M_1_PI) / sinNH4;
+ float G = std::min(1.0f, std::min(fac1, fac2)); // TODO: derive G from D analytically
+
+ float out = 0.25f * (D * G) / cosNO;
+
+ pdf = 0.5f * (float) M_1_PI;
+ return Color3 (out, out, out);
+ }
+ 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 above - send a ray out with uniform
+ // distribution over the hemisphere
+ sample_uniform_hemisphere (m_N, omega_out, randu, randv, omega_in, pdf);
+ if (Ng.dot(omega_in) > 0) {
+ Vec3 H = omega_in + omega_out;
+ H.normalize();
+
+ float cosNI = m_N.dot(omega_in);
+ float cosNO = m_N.dot(omega_out);
+ float cosNH = m_N.dot(H);
+ float cosHO = fabsf(omega_out.dot(H));
+
+ float cosNHdivHO = cosNH / cosHO;
+ cosNHdivHO = std::max(cosNHdivHO, 0.00001f);
+
+ float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
+ float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
+
+ float sinNH2 = 1 - cosNH * cosNH;
+ float sinNH4 = sinNH2 * sinNH2;
+ float cotangent2 = (cosNH * cosNH) / sinNH2;
+
+ float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * float(M_1_PI) / sinNH4;
+ float G = std::min(1.0f, std::min(fac1, fac2)); // TODO: derive G from D analytically
+
+ float power = 0.25f * (D * G) / cosNO;
+
+ eval.setValue(power, power, power);
+
+ // TODO: find a better approximation for the retroreflective 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_ashikhmin_velvet_params[] = {
+ CLOSURE_VECTOR_PARAM(AshikhminVelvetClosure, m_N),
+ CLOSURE_FLOAT_PARAM (AshikhminVelvetClosure, m_sigma),
+ CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_FINISH_PARAM(AshikhminVelvetClosure) };
+
+CLOSURE_PREPARE(bsdf_ashikhmin_velvet_prepare, AshikhminVelvetClosure)
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/osl/bsdf_diffuse.cpp b/intern/cycles/kernel/osl/bsdf_diffuse.cpp
new file mode 100644
index 00000000000..0d4b3fa471f
--- /dev/null
+++ b/intern/cycles/kernel/osl/bsdf_diffuse.cpp
@@ -0,0 +1,181 @@
+/*
+ * Adapted from Open Shading Language with this license:
+ *
+ * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
+ * All Rights Reserved.
+ *
+ * Modifications Copyright 2011, Blender Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Sony Pictures Imageworks nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <OpenImageIO/fmath.h>
+
+#include <OSL/genclosure.h>
+
+#include "osl_closures.h"
+
+CCL_NAMESPACE_BEGIN
+
+using namespace OSL;
+
+class DiffuseClosure : public BSDFClosure {
+public:
+ Vec3 m_N;
+
+ DiffuseClosure() : BSDFClosure(Labels::DIFFUSE) { }
+
+ void setup() {};
+
+ bool mergeable (const ClosurePrimitive *other) const {
+ const DiffuseClosure *comp = (const DiffuseClosure *)other;
+ return m_N == comp->m_N && BSDFClosure::mergeable(other);
+ }
+
+ size_t memsize () const { return sizeof(*this); }
+
+ const char *name () const { return "diffuse"; }
+
+ void print_on (std::ostream &out) const
+ {
+ out << name() << " ((" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))";
+ }
+
+ float albedo (const Vec3 &omega_out) const
+ {
+ return 1.0f;
+ }
+
+ Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
+ {
+ float cos_pi = std::max(m_N.dot(omega_in),0.0f) * (float) M_1_PI;
+ pdf = cos_pi;
+ return Color3 (cos_pi, cos_pi, cos_pi);
+ }
+
+ 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) {
+ eval.setValue(pdf, pdf, pdf);
+ // 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;
+ }
+};
+
+
+
+class TranslucentClosure : public BSDFClosure {
+public:
+ Vec3 m_N;
+
+ TranslucentClosure() : BSDFClosure(Labels::DIFFUSE, Back) { }
+
+ void setup() {};
+
+ bool mergeable (const ClosurePrimitive *other) const {
+ const TranslucentClosure *comp = (const TranslucentClosure *)other;
+ return m_N == comp->m_N && BSDFClosure::mergeable(other);
+ }
+
+ size_t memsize () const { return sizeof(*this); }
+
+ const char *name () const { return "translucent"; }
+
+ void print_on (std::ostream &out) const
+ {
+ out << name() << " ((" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))";
+ }
+
+ Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
+ {
+ return Color3 (0, 0, 0);
+ }
+
+ float albedo (const Vec3 &omega_out) const
+ {
+ return 1.0f;
+ }
+
+ Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
+ {
+ float cos_pi = std::max(-m_N.dot(omega_in), 0.0f) * (float) M_1_PI;
+ pdf = cos_pi;
+ return Color3 (cos_pi, cos_pi, cos_pi);
+ }
+
+ 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) {
+ eval.setValue(pdf, pdf, pdf);
+ // 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::TRANSMIT;
+ }
+};
+
+ClosureParam bsdf_diffuse_params[] = {
+ CLOSURE_VECTOR_PARAM (DiffuseClosure, m_N),
+ CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_FINISH_PARAM (DiffuseClosure) };
+
+ClosureParam bsdf_translucent_params[] = {
+ CLOSURE_VECTOR_PARAM (TranslucentClosure, m_N),
+ CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_FINISH_PARAM (TranslucentClosure) };
+
+CLOSURE_PREPARE(bsdf_diffuse_prepare, DiffuseClosure)
+CLOSURE_PREPARE(bsdf_translucent_prepare, TranslucentClosure)
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/osl/bsdf_microfacet.cpp b/intern/cycles/kernel/osl/bsdf_microfacet.cpp
new file mode 100644
index 00000000000..d87268da81e
--- /dev/null
+++ b/intern/cycles/kernel/osl/bsdf_microfacet.cpp
@@ -0,0 +1,533 @@
+/*
+ * Adapted from Open Shading Language with this license:
+ *
+ * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
+ * All Rights Reserved.
+ *
+ * Modifications Copyright 2011, Blender Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Sony Pictures Imageworks nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <OpenImageIO/fmath.h>
+
+#include <OSL/genclosure.h>
+
+#include "osl_closures.h"
+
+#include "util_math.h"
+
+using namespace OSL;
+
+CCL_NAMESPACE_BEGIN
+
+// TODO: fresnel_dielectric is only used for derivatives, could be optimized
+
+// TODO: refactor these two classes so they share everything by the microfacet
+// distribution terms
+
+// microfacet model with GGX facet distribution
+// see http://www.graphics.cornell.edu/~bjw/microfacetbsdf.pdf
+template <int Refractive = 0>
+class MicrofacetGGXClosure : public BSDFClosure {
+public:
+ Vec3 m_N;
+ float m_ag; // width parameter (roughness)
+ float m_eta; // index of refraction (for fresnel term)
+ MicrofacetGGXClosure() : BSDFClosure(Labels::GLOSSY, Refractive ? Back : Front) { m_eta = 1.0f; }
+
+ void setup()
+ {
+ m_ag = clamp(m_ag, 1e-5f, 1.0f);
+ }
+
+ bool mergeable (const ClosurePrimitive *other) const {
+ const MicrofacetGGXClosure *comp = (const MicrofacetGGXClosure *)other;
+ return m_N == comp->m_N && m_ag == comp->m_ag &&
+ m_eta == comp->m_eta && BSDFClosure::mergeable(other);
+ }
+
+ size_t memsize () const { return sizeof(*this); }
+
+ const char *name () const {
+ return Refractive ? "microfacet_ggx_refraction" : "microfacet_ggx";
+ }
+
+ void print_on (std::ostream &out) const {
+ out << name() << " (";
+ out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
+ out << m_ag << ", ";
+ out << m_eta;
+ 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
+ {
+ if (Refractive == 1) return Color3 (0, 0, 0);
+ float cosNO = m_N.dot(omega_out);
+ float cosNI = m_N.dot(omega_in);
+ if (cosNI > 0 && cosNO > 0) {
+ // get half vector
+ Vec3 Hr = omega_in + omega_out;
+ Hr.normalize();
+ // eq. 20: (F*G*D)/(4*in*on)
+ // eq. 33: first we calculate D(m) with m=Hr:
+ float alpha2 = m_ag * m_ag;
+ float cosThetaM = m_N.dot(Hr);
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ float D = alpha2 / ((float) M_PI * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
+ // eq. 34: now calculate G1(i,m) and G1(o,m)
+ float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
+ float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
+ float G = G1o * G1i;
+ float out = (G * D) * 0.25f / cosNO;
+ // 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 / Hr.dot(omega_out);
+ return Color3 (out, out, out);
+ }
+ return Color3 (0, 0, 0);
+ }
+
+ Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
+ {
+ if (Refractive == 0) return Color3 (0, 0, 0);
+ float cosNO = m_N.dot(omega_out);
+ float cosNI = m_N.dot(omega_in);
+ if (cosNO <= 0 || cosNI >= 0)
+ return Color3 (0, 0, 0); // vectors on same side -- not possible
+ // compute half-vector of the refraction (eq. 16)
+ Vec3 ht = -(m_eta * omega_in + omega_out);
+ Vec3 Ht = ht; Ht.normalize();
+ float cosHO = Ht.dot(omega_out);
+
+ float cosHI = Ht.dot(omega_in);
+ // eq. 33: first we calculate D(m) with m=Ht:
+ float alpha2 = m_ag * m_ag;
+ float cosThetaM = m_N.dot(Ht);
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ float D = alpha2 / ((float) M_PI * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
+ // eq. 34: now calculate G1(i,m) and G1(o,m)
+ float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
+ float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
+ float G = G1o * G1i;
+ // probability
+ float invHt2 = 1 / ht.dot(ht);
+ pdf = D * fabsf(cosThetaM) * (fabsf(cosHI) * (m_eta * m_eta)) * invHt2;
+ float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D) * invHt2) / cosNO;
+ return Color3 (out, out, out);
+ }
+
+ 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) {
+ Vec3 X, Y, Z = m_N;
+ make_orthonormals(Z, X, Y);
+ // generate a random microfacet normal m
+ // eq. 35,36:
+ // we take advantage of cos(atan(x)) == 1/sqrt(1+x^2)
+ // and sin(atan(x)) == x/sqrt(1+x^2)
+ float alpha2 = m_ag * m_ag;
+ float tanThetaM2 = alpha2 * randu / (1 - randu);
+ float cosThetaM = 1 / sqrtf(1 + tanThetaM2);
+ float sinThetaM = cosThetaM * sqrtf(tanThetaM2);
+ float phiM = 2 * float(M_PI) * randv;
+ Vec3 m = (cosf(phiM) * sinThetaM) * X +
+ (sinf(phiM) * sinThetaM) * Y +
+ cosThetaM * Z;
+ if (Refractive == 0) {
+ float cosMO = m.dot(omega_out);
+ if (cosMO > 0) {
+ // eq. 39 - compute actual reflected direction
+ omega_in = 2 * cosMO * m - omega_out;
+ if (Ng.dot(omega_in) > 0) {
+ // microfacet normal is visible to this ray
+ // eq. 33
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ float D = alpha2 / (float(M_PI) * 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 = m_N.dot(omega_in);
+ // eq. 34: now calculate G1(i,m) and G1(o,m)
+ float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
+ float G1i = 2 / (1 + 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.setValue(out, out, out);
+ domega_in_dx = (2 * m.dot(domega_out_dx)) * m - domega_out_dx;
+ domega_in_dy = (2 * m.dot(domega_out_dy)) * m - domega_out_dy;
+
+ /* disabled for now - gives texture filtering problems */
+#if 0
+ // Since there is some blur to this reflection, make the
+ // derivatives a bit bigger. In theory this varies with the
+ // roughness but the exact relationship is complex and
+ // requires more ops than are practical.
+ domega_in_dx *= 10;
+ domega_in_dy *= 10;
+#endif
+ }
+ }
+ } else {
+ // CAUTION: the i and o variables are inverted relative to the paper
+ // eq. 39 - compute actual refractive direction
+ Vec3 R, dRdx, dRdy;
+ Vec3 T, dTdx, dTdy;
+ bool inside;
+ fresnel_dielectric(m_eta, m, omega_out, domega_out_dx, domega_out_dy,
+ R, dRdx, dRdy,
+ T, dTdx, dTdy,
+ inside);
+
+ if (!inside) {
+ omega_in = T;
+ domega_in_dx = dTdx;
+ domega_in_dy = dTdy;
+ // eq. 33
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ float D = alpha2 / (float(M_PI) * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
+ // eq. 24
+ float pm = D * cosThetaM;
+ // eval BRDF*cosNI
+ float cosNI = m_N.dot(omega_in);
+ // eq. 34: now calculate G1(i,m) and G1(o,m)
+ float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
+ float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
+ float G = G1o * G1i;
+ // eq. 21
+ float cosHI = m.dot(omega_in);
+ float cosHO = m.dot(omega_out);
+ 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.setValue(out, out, out);
+
+ /* disabled for now - gives texture filtering problems */
+#if 0
+ // Since there is some blur to this refraction, make the
+ // derivatives a bit bigger. In theory this varies with the
+ // roughness but the exact relationship is complex and
+ // requires more ops than are practical.
+ domega_in_dx *= 10;
+ domega_in_dy *= 10;
+#endif
+ }
+ }
+ }
+ return Refractive ? Labels::TRANSMIT : Labels::REFLECT;
+ }
+};
+
+// microfacet model with Beckmann facet distribution
+// see http://www.graphics.cornell.edu/~bjw/microfacetbsdf.pdf
+template <int Refractive = 0>
+class MicrofacetBeckmannClosure : public BSDFClosure {
+public:
+ Vec3 m_N;
+ float m_ab; // width parameter (roughness)
+ float m_eta; // index of refraction (for fresnel term)
+ MicrofacetBeckmannClosure() : BSDFClosure(Labels::GLOSSY, Refractive ? Back : Front) { }
+
+ void setup()
+ {
+ m_ab = clamp(m_ab, 1e-5f, 1.0f);
+ }
+
+ bool mergeable (const ClosurePrimitive *other) const {
+ const MicrofacetBeckmannClosure *comp = (const MicrofacetBeckmannClosure *)other;
+ return m_N == comp->m_N && m_ab == comp->m_ab &&
+ m_eta == comp->m_eta && BSDFClosure::mergeable(other);
+ }
+
+ size_t memsize () const { return sizeof(*this); }
+
+ const char * name () const {
+ return Refractive ? "microfacet_beckmann_refraction"
+ : "microfacet_beckmann";
+ }
+
+ void print_on (std::ostream &out) const
+ {
+ out << name() << " (";
+ out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
+ out << m_ab << ", ";
+ out << m_eta;
+ 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
+ {
+ if (Refractive == 1) return Color3 (0, 0, 0);
+ float cosNO = m_N.dot(omega_out);
+ float cosNI = m_N.dot(omega_in);
+ if (cosNO > 0 && cosNI > 0) {
+ // get half vector
+ Vec3 Hr = omega_in + omega_out;
+ Hr.normalize();
+ // eq. 20: (F*G*D)/(4*in*on)
+ // eq. 25: first we calculate D(m) with m=Hr:
+ float alpha2 = m_ab * m_ab;
+ float cosThetaM = m_N.dot(Hr);
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4);
+ // eq. 26, 27: now calculate G1(i,m) and G1(o,m)
+ float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
+ float ai = 1 / (m_ab * 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;
+ float out = (G * D) * 0.25f / cosNO;
+ // 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 / Hr.dot(omega_out);
+ return Color3 (out, out, out);
+ }
+ return Color3 (0, 0, 0);
+ }
+
+ Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
+ {
+ if (Refractive == 0) return Color3 (0, 0, 0);
+ float cosNO = m_N.dot(omega_out);
+ float cosNI = m_N.dot(omega_in);
+ if (cosNO <= 0 || cosNI >= 0)
+ return Color3 (0, 0, 0);
+ // compute half-vector of the refraction (eq. 16)
+ Vec3 ht = -(m_eta * omega_in + omega_out);
+ Vec3 Ht = ht; Ht.normalize();
+ float cosHO = Ht.dot(omega_out);
+
+ float cosHI = Ht.dot(omega_in);
+ // eq. 33: first we calculate D(m) with m=Ht:
+ float alpha2 = m_ab * m_ab;
+ float cosThetaM = m_N.dot(Ht);
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4);
+ // eq. 26, 27: now calculate G1(i,m) and G1(o,m)
+ float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
+ float ai = 1 / (m_ab * 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;
+ // probability
+ float invHt2 = 1 / ht.dot(ht);
+ pdf = D * fabsf(cosThetaM) * (fabsf(cosHI) * (m_eta * m_eta)) * invHt2;
+ float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D) * invHt2) / cosNO;
+ return Color3 (out, out, out);
+ }
+
+ 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) {
+ Vec3 X, Y, Z = m_N;
+ make_orthonormals(Z, X, Y);
+ // generate a random microfacet normal m
+ // eq. 35,36:
+ // we take advantage of cos(atan(x)) == 1/sqrt(1+x^2)
+ // and sin(atan(x)) == x/sqrt(1+x^2)
+ float alpha2 = m_ab * m_ab;
+ float tanThetaM = sqrtf(-alpha2 * logf(1 - randu));
+ float cosThetaM = 1 / sqrtf(1 + tanThetaM * tanThetaM);
+ float sinThetaM = cosThetaM * tanThetaM;
+ float phiM = 2 * float(M_PI) * randv;
+ Vec3 m = (cosf(phiM) * sinThetaM) * X +
+ (sinf(phiM) * sinThetaM) * Y +
+ cosThetaM * Z;
+ if (Refractive == 0) {
+ float cosMO = m.dot(omega_out);
+ if (cosMO > 0) {
+ // eq. 39 - compute actual reflected direction
+ omega_in = 2 * cosMO * m - omega_out;
+ if (Ng.dot(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) / (float(M_PI) * 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 = m_N.dot(omega_in);
+ // eq. 26, 27: now calculate G1(i,m) and G1(o,m)
+ float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
+ float ai = 1 / (m_ab * 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.setValue(out, out, out);
+ domega_in_dx = (2 * m.dot(domega_out_dx)) * m - domega_out_dx;
+ domega_in_dy = (2 * m.dot(domega_out_dy)) * m - domega_out_dy;
+
+ /* disabled for now - gives texture filtering problems */
+#if 0
+ // Since there is some blur to this reflection, make the
+ // derivatives a bit bigger. In theory this varies with the
+ // roughness but the exact relationship is complex and
+ // requires more ops than are practical.
+ domega_in_dx *= 10;
+ domega_in_dy *= 10;
+#endif
+ }
+ }
+ } else {
+ // CAUTION: the i and o variables are inverted relative to the paper
+ // eq. 39 - compute actual refractive direction
+ Vec3 R, dRdx, dRdy;
+ Vec3 T, dTdx, dTdy;
+ bool inside;
+ fresnel_dielectric(m_eta, m, omega_out, domega_out_dx, domega_out_dy,
+ R, dRdx, dRdy,
+ T, dTdx, dTdy,
+ inside);
+ if (!inside) {
+ omega_in = T;
+ domega_in_dx = dTdx;
+ domega_in_dy = dTdy;
+ // eq. 33
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float tanThetaM2 = tanThetaM * tanThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4);
+ // eq. 24
+ float pm = D * cosThetaM;
+ // eval BRDF*cosNI
+ float cosNI = m_N.dot(omega_in);
+ // eq. 26, 27: now calculate G1(i,m) and G1(o,m)
+ float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
+ float ai = 1 / (m_ab * 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 = m.dot(omega_in);
+ float cosHO = m.dot(omega_out);
+ 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.setValue(out, out, out);
+
+ /* disabled for now - gives texture filtering problems */
+#if 0
+ // Since there is some blur to this refraction, make the
+ // derivatives a bit bigger. In theory this varies with the
+ // roughness but the exact relationship is complex and
+ // requires more ops than are practical.
+ domega_in_dx *= 10;
+ domega_in_dy *= 10;
+#endif
+ }
+ }
+ }
+ return Refractive ? Labels::TRANSMIT : Labels::REFLECT;
+ }
+};
+
+
+
+ClosureParam bsdf_microfacet_ggx_params[] = {
+ CLOSURE_VECTOR_PARAM(MicrofacetGGXClosure<0>, m_N),
+ CLOSURE_FLOAT_PARAM (MicrofacetGGXClosure<0>, m_ag),
+ CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_FINISH_PARAM(MicrofacetGGXClosure<0>) };
+
+ClosureParam bsdf_microfacet_ggx_refraction_params[] = {
+ CLOSURE_VECTOR_PARAM(MicrofacetGGXClosure<1>, m_N),
+ CLOSURE_FLOAT_PARAM (MicrofacetGGXClosure<1>, m_ag),
+ CLOSURE_FLOAT_PARAM (MicrofacetGGXClosure<1>, m_eta),
+ CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_FINISH_PARAM(MicrofacetGGXClosure<1>) };
+
+ClosureParam bsdf_microfacet_beckmann_params[] = {
+ CLOSURE_VECTOR_PARAM(MicrofacetBeckmannClosure<0>, m_N),
+ CLOSURE_FLOAT_PARAM (MicrofacetBeckmannClosure<0>, m_ab),
+ CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_FINISH_PARAM(MicrofacetBeckmannClosure<0>) };
+
+ClosureParam bsdf_microfacet_beckmann_refraction_params[] = {
+ CLOSURE_VECTOR_PARAM(MicrofacetBeckmannClosure<1>, m_N),
+ CLOSURE_FLOAT_PARAM (MicrofacetBeckmannClosure<1>, m_ab),
+ CLOSURE_FLOAT_PARAM (MicrofacetBeckmannClosure<1>, m_eta),
+ CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_FINISH_PARAM(MicrofacetBeckmannClosure<1>) };
+
+CLOSURE_PREPARE(bsdf_microfacet_ggx_prepare, MicrofacetGGXClosure<0>)
+CLOSURE_PREPARE(bsdf_microfacet_ggx_refraction_prepare, MicrofacetGGXClosure<1>)
+CLOSURE_PREPARE(bsdf_microfacet_beckmann_prepare, MicrofacetBeckmannClosure<0>)
+CLOSURE_PREPARE(bsdf_microfacet_beckmann_refraction_prepare, MicrofacetBeckmannClosure<1>)
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/osl/bsdf_reflection.cpp b/intern/cycles/kernel/osl/bsdf_reflection.cpp
new file mode 100644
index 00000000000..b0caff6df44
--- /dev/null
+++ b/intern/cycles/kernel/osl/bsdf_reflection.cpp
@@ -0,0 +1,108 @@
+/*
+ * Adapted from Open Shading Language with this license:
+ *
+ * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
+ * All Rights Reserved.
+ *
+ * Modifications Copyright 2011, Blender Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Sony Pictures Imageworks nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <OpenImageIO/fmath.h>
+
+#include <OSL/genclosure.h>
+
+#include "osl_closures.h"
+
+CCL_NAMESPACE_BEGIN
+
+using namespace OSL;
+
+class ReflectionClosure : public BSDFClosure {
+public:
+ Vec3 m_N; // shading normal
+ ReflectionClosure() : BSDFClosure(Labels::SINGULAR) { }
+
+ void setup() {};
+
+ bool mergeable (const ClosurePrimitive *other) const {
+ const ReflectionClosure *comp = (const ReflectionClosure *)other;
+ return m_N == comp->m_N && BSDFClosure::mergeable(other);
+ }
+
+ size_t memsize () const { return sizeof(*this); }
+
+ const char *name () const { return "reflection"; }
+
+ void print_on (std::ostream &out) const {
+ out << name() << " (";
+ out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))";
+ }
+
+ float albedo (const Vec3 &omega_out) const
+ {
+ return 1.0f;
+ }
+
+ Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
+ {
+ 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
+ {
+ // only one direction is possible
+ float cosNO = m_N.dot(omega_out);
+ if (cosNO > 0) {
+ omega_in = (2 * cosNO) * m_N - omega_out;
+ if (Ng.dot(omega_in) > 0) {
+ 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;
+ pdf = 1;
+ eval.setValue(1, 1, 1);
+ }
+ }
+ return Labels::REFLECT;
+ }
+};
+
+ClosureParam bsdf_reflection_params[] = {
+ CLOSURE_VECTOR_PARAM(ReflectionClosure, m_N),
+ CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_FINISH_PARAM(ReflectionClosure) };
+
+CLOSURE_PREPARE(bsdf_reflection_prepare, ReflectionClosure)
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/osl/bsdf_refraction.cpp b/intern/cycles/kernel/osl/bsdf_refraction.cpp
new file mode 100644
index 00000000000..3ae7a3811b4
--- /dev/null
+++ b/intern/cycles/kernel/osl/bsdf_refraction.cpp
@@ -0,0 +1,120 @@
+/*
+ * Adapted from Open Shading Language with this license:
+ *
+ * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
+ * All Rights Reserved.
+ *
+ * Modifications Copyright 2011, Blender Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Sony Pictures Imageworks nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <OpenImageIO/fmath.h>
+
+#include <OSL/genclosure.h>
+
+#include "osl_closures.h"
+
+CCL_NAMESPACE_BEGIN
+
+using namespace OSL;
+
+class RefractionClosure : public BSDFClosure {
+public:
+ Vec3 m_N; // shading normal
+ float m_eta; // ratio of indices of refraction (inside / outside)
+ RefractionClosure() : BSDFClosure(Labels::SINGULAR, Back) { }
+
+ void setup() {}
+
+ bool mergeable (const ClosurePrimitive *other) const {
+ const RefractionClosure *comp = (const RefractionClosure *)other;
+ return m_N == comp->m_N && m_eta == comp->m_eta &&
+ BSDFClosure::mergeable(other);
+ }
+
+ size_t memsize () const { return sizeof(*this); }
+
+ const char *name () const { return "refraction"; }
+
+ void print_on (std::ostream &out) const {
+ out << name() << " (";
+ out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
+ out << m_eta;
+ out << ")";
+ }
+
+ Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
+ {
+ return Color3 (0, 0, 0);
+ }
+
+ Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
+ {
+ return Color3 (0, 0, 0);
+ }
+
+ float albedo (const Vec3 &omega_out) const
+ {
+ return 1.0f;
+ }
+
+ 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
+ {
+ Vec3 R, dRdx, dRdy;
+ Vec3 T, dTdx, dTdy;
+ bool inside;
+
+ fresnel_dielectric(m_eta, m_N,
+ omega_out, domega_out_dx, domega_out_dy,
+ R, dRdx, dRdy,
+ T, dTdx, dTdy,
+ inside);
+
+ if (!inside) {
+ pdf = 1;
+ eval.setValue(1.0f, 1.0f, 1.0f);
+ omega_in = T;
+ domega_in_dx = dTdx;
+ domega_in_dy = dTdy;
+ }
+
+ return Labels::TRANSMIT;
+ }
+};
+
+ClosureParam bsdf_refraction_params[] = {
+ CLOSURE_VECTOR_PARAM(RefractionClosure, m_N),
+ CLOSURE_FLOAT_PARAM (RefractionClosure, m_eta),
+ CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_FINISH_PARAM(RefractionClosure) };
+
+CLOSURE_PREPARE(bsdf_refraction_prepare, RefractionClosure)
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/osl/bsdf_transparent.cpp b/intern/cycles/kernel/osl/bsdf_transparent.cpp
new file mode 100644
index 00000000000..941abd6a483
--- /dev/null
+++ b/intern/cycles/kernel/osl/bsdf_transparent.cpp
@@ -0,0 +1,97 @@
+/*
+ * Adapted from Open Shading Language with this license:
+ *
+ * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
+ * All Rights Reserved.
+ *
+ * Modifications Copyright 2011, Blender Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Sony Pictures Imageworks nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <OpenImageIO/fmath.h>
+
+#include <OSL/genclosure.h>
+
+#include "osl_closures.h"
+
+CCL_NAMESPACE_BEGIN
+
+using namespace OSL;
+
+class TransparentClosure : public BSDFClosure {
+public:
+ TransparentClosure() : BSDFClosure(Labels::STRAIGHT, Back) { }
+
+ void setup() {}
+
+ size_t memsize () const { return sizeof(*this); }
+
+ const char *name () const { return "transparent"; }
+
+ void print_on (std::ostream &out) const {
+ out << name() << " ()";
+ }
+
+ float albedo (const Vec3 &omega_out) const
+ {
+ return 1.0f;
+ }
+
+ Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
+ {
+ 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
+ {
+ // only one direction is possible
+ omega_in = -omega_out;
+ domega_in_dx = -domega_out_dx;
+ domega_in_dy = -domega_out_dy;
+ pdf = 1;
+ eval.setValue(1, 1, 1);
+ return Labels::TRANSMIT;
+ }
+};
+
+
+
+ClosureParam bsdf_transparent_params[] = {
+ CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_FINISH_PARAM(TransparentClosure) };
+
+CLOSURE_PREPARE(bsdf_transparent_prepare, TransparentClosure)
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/osl/bsdf_ward.cpp b/intern/cycles/kernel/osl/bsdf_ward.cpp
new file mode 100644
index 00000000000..a7742a04d13
--- /dev/null
+++ b/intern/cycles/kernel/osl/bsdf_ward.cpp
@@ -0,0 +1,222 @@
+/*
+ * Adapted from Open Shading Language with this license:
+ *
+ * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
+ * All Rights Reserved.
+ *
+ * Modifications Copyright 2011, Blender Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Sony Pictures Imageworks nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <OpenImageIO/fmath.h>
+
+#include <OSL/genclosure.h>
+
+#include "osl_closures.h"
+
+#include "util_math.h"
+
+CCL_NAMESPACE_BEGIN
+
+using namespace OSL;
+
+// anisotropic ward - leaks energy at grazing angles
+// see http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
+class WardClosure : public BSDFClosure {
+public:
+ Vec3 m_N;
+ Vec3 m_T;
+ float m_ax, m_ay;
+ WardClosure() : BSDFClosure(Labels::GLOSSY) { }
+
+ void setup()
+ {
+ m_ax = clamp(m_ax, 1e-5f, 1.0f);
+ m_ay = clamp(m_ay, 1e-5f, 1.0f);
+ }
+
+ bool mergeable (const ClosurePrimitive *other) const {
+ const WardClosure *comp = (const WardClosure *)other;
+ return m_N == comp->m_N && m_T == comp->m_T &&
+ m_ax == comp->m_ax && m_ay == comp->m_ay &&
+ BSDFClosure::mergeable(other);
+ }
+
+ size_t memsize () const { return sizeof(*this); }
+
+ const char *name () const { return "ward"; }
+
+ void print_on (std::ostream &out) const {
+ out << name() << " ((";
+ out << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), (";
+ out << m_T[0] << ", " << m_T[1] << ", " << m_T[2] << "), ";
+ out << m_ax << ", " << m_ay << ")";
+ }
+
+ float albedo (const Vec3 &omega_out) const
+ {
+ return 1.0f;
+ }
+
+ Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
+ {
+ float cosNO = m_N.dot(omega_out);
+ float cosNI = m_N.dot(omega_in);
+ if (cosNI > 0 && cosNO > 0) {
+ // get half vector and get x,y basis on the surface for anisotropy
+ Vec3 H = omega_in + omega_out;
+ H.normalize(); // normalize needed for pdf
+ Vec3 X, Y;
+ make_orthonormals(m_N, m_T, X, Y);
+ // eq. 4
+ float dotx = H.dot(X) / m_ax;
+ float doty = H.dot(Y) / m_ay;
+ float dotn = H.dot(m_N);
+ float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn);
+ float denom = (4 * (float) M_PI * m_ax * m_ay * sqrtf(cosNO * cosNI));
+ float exp_val = expf(-exp_arg);
+ float out = cosNI * exp_val / denom;
+ float oh = H.dot(omega_out);
+ denom = 4 * (float) M_PI * m_ax * m_ay * oh * dotn * dotn * dotn;
+ pdf = exp_val / denom;
+ return Color3 (out, out, out);
+ }
+ 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) {
+ // get x,y basis on the surface for anisotropy
+ Vec3 X, Y;
+ make_orthonormals(m_N, m_T, X, Y);
+ // generate random angles for the half vector
+ // eq. 7 (taking care around discontinuities to keep
+ // output angle in the right quadrant)
+ // we take advantage of cos(atan(x)) == 1/sqrt(1+x^2)
+ // and sin(atan(x)) == x/sqrt(1+x^2)
+ float alphaRatio = m_ay / m_ax;
+ float cosPhi, sinPhi;
+ if (randu < 0.25f) {
+ float val = 4 * randu;
+ float tanPhi = alphaRatio * tanf((float) M_PI_2 * val);
+ cosPhi = 1 / sqrtf(1 + tanPhi * tanPhi);
+ sinPhi = tanPhi * cosPhi;
+ } else if (randu < 0.5) {
+ float val = 1 - 4 * (0.5f - randu);
+ float tanPhi = alphaRatio * tanf((float) M_PI_2 * val);
+ // phi = (float) M_PI - phi;
+ cosPhi = -1 / sqrtf(1 + tanPhi * tanPhi);
+ sinPhi = -tanPhi * cosPhi;
+ } else if (randu < 0.75f) {
+ float val = 4 * (randu - 0.5f);
+ float tanPhi = alphaRatio * tanf((float) M_PI_2 * val);
+ //phi = (float) M_PI + phi;
+ cosPhi = -1 / sqrtf(1 + tanPhi * tanPhi);
+ sinPhi = tanPhi * cosPhi;
+ } else {
+ float val = 1 - 4 * (1 - randu);
+ float tanPhi = alphaRatio * tanf((float) M_PI_2 * val);
+ // phi = 2 * (float) M_PI - phi;
+ cosPhi = 1 / sqrtf(1 + tanPhi * tanPhi);
+ sinPhi = -tanPhi * cosPhi;
+ }
+ // eq. 6
+ // we take advantage of cos(atan(x)) == 1/sqrt(1+x^2)
+ // and sin(atan(x)) == x/sqrt(1+x^2)
+ float thetaDenom = (cosPhi * cosPhi) / (m_ax * m_ax) + (sinPhi * sinPhi) / (m_ay * m_ay);
+ float tanTheta2 = -logf(1 - randv) / thetaDenom;
+ float cosTheta = 1 / sqrtf(1 + tanTheta2);
+ float sinTheta = cosTheta * sqrtf(tanTheta2);
+
+ Vec3 h; // already normalized becaused expressed from spherical coordinates
+ h.x = sinTheta * cosPhi;
+ h.y = sinTheta * sinPhi;
+ h.z = cosTheta;
+ // compute terms that are easier in local space
+ float dotx = h.x / m_ax;
+ float doty = h.y / m_ay;
+ float dotn = h.z;
+ // transform to world space
+ h = h.x * X + h.y * Y + h.z * m_N;
+ // generate the final sample
+ float oh = h.dot(omega_out);
+ omega_in.x = 2 * oh * h.x - omega_out.x;
+ omega_in.y = 2 * oh * h.y - omega_out.y;
+ omega_in.z = 2 * oh * h.z - omega_out.z;
+ if (Ng.dot(omega_in) > 0) {
+ float cosNI = m_N.dot(omega_in);
+ if (cosNI > 0) {
+ // eq. 9
+ float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn);
+ float denom = 4 * (float) M_PI * m_ax * m_ay * oh * dotn * dotn * dotn;
+ pdf = expf(-exp_arg) / denom;
+ // compiler will reuse expressions already computed
+ denom = (4 * (float) M_PI * m_ax * m_ay * sqrtf(cosNO * cosNI));
+ float power = cosNI * expf(-exp_arg) / denom;
+ eval.setValue(power, power, power);
+ 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;
+
+ /* disabled for now - gives texture filtering problems */
+#if 0
+ // Since there is some blur to this reflection, make the
+ // derivatives a bit bigger. In theory this varies with the
+ // roughness but the exact relationship is complex and
+ // requires more ops than are practical.
+ domega_in_dx *= 10;
+ domega_in_dy *= 10;
+#endif
+ }
+ }
+ }
+ return Labels::REFLECT;
+ }
+};
+
+
+
+ClosureParam bsdf_ward_params[] = {
+ CLOSURE_VECTOR_PARAM(WardClosure, m_N),
+ CLOSURE_VECTOR_PARAM(WardClosure, m_T),
+ CLOSURE_FLOAT_PARAM (WardClosure, m_ax),
+ CLOSURE_FLOAT_PARAM (WardClosure, m_ay),
+ CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_FINISH_PARAM(WardClosure) };
+
+CLOSURE_PREPARE(bsdf_ward_prepare, WardClosure)
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/osl/bsdf_westin.cpp b/intern/cycles/kernel/osl/bsdf_westin.cpp
new file mode 100644
index 00000000000..d322f6a7f7e
--- /dev/null
+++ b/intern/cycles/kernel/osl/bsdf_westin.cpp
@@ -0,0 +1,239 @@
+/*
+ * Adapted from Open Shading Language with this license:
+ *
+ * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
+ * All Rights Reserved.
+ *
+ * Modifications Copyright 2011, Blender Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Sony Pictures Imageworks nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <OpenImageIO/fmath.h>
+
+#include <OSL/genclosure.h>
+
+#include "osl_closures.h"
+
+#include "util_math.h"
+
+CCL_NAMESPACE_BEGIN
+
+using namespace OSL;
+
+class WestinBackscatterClosure : public BSDFClosure {
+public:
+ Vec3 m_N;
+ float m_roughness;
+ float m_invroughness;
+ WestinBackscatterClosure() : BSDFClosure(Labels::GLOSSY) { }
+
+ 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;
+ }
+
+};
+
+
+class WestinSheenClosure : public BSDFClosure {
+public:
+ 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;
+ }
+};
+
+
+
+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) };
+
+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_PREPARE(bsdf_westin_backscatter_prepare, WestinBackscatterClosure)
+CLOSURE_PREPARE(bsdf_westin_sheen_prepare, WestinSheenClosure)
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/osl/bssrdf.cpp b/intern/cycles/kernel/osl/bssrdf.cpp
new file mode 100644
index 00000000000..66d7818e677
--- /dev/null
+++ b/intern/cycles/kernel/osl/bssrdf.cpp
@@ -0,0 +1,105 @@
+/*
+ * Adapted from Open Shading Language with this license:
+ *
+ * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
+ * All Rights Reserved.
+ *
+ * Modifications Copyright 2011, Blender Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Sony Pictures Imageworks nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <OpenImageIO/fmath.h>
+
+#include <OSL/genclosure.h>
+
+#include "osl_closures.h"
+
+CCL_NAMESPACE_BEGIN
+
+using namespace OSL;
+
+class BSSRDFCubicClosure : public BSSRDFClosure {
+public:
+ Color3 m_radius;
+ Color3 m_scale;
+ float m_max_radius;
+
+ template <typename T>
+ static inline T pow3 (const T &x) { return x * x * x; }
+
+ template <typename T>
+ static inline T pow5 (const T &x) { T x2 = x * x; return x2 * x2 * x; }
+
+ BSSRDFCubicClosure() { }
+
+ void setup()
+ {
+ // pre-compute some terms
+ m_max_radius = 0;
+ for (int i = 0; i < 3; i++) {
+ m_scale[i] = m_radius[i] > 0 ? 4 / pow5 (m_radius[i]) : 0;
+ m_max_radius = std::max (m_max_radius, m_radius[i]);
+ }
+ }
+
+ bool mergeable (const ClosurePrimitive *other) const {
+ const BSSRDFCubicClosure *comp = (const BSSRDFCubicClosure *)other;
+ return m_radius == comp->m_radius && BSSRDFClosure::mergeable(other);
+ }
+
+ size_t memsize () const { return sizeof(*this); }
+
+ const char *name () const { return "bssrdf_cubic"; }
+
+ void print_on (std::ostream &out) const
+ {
+ out << name() << " ((" << m_radius[0] << ", " << m_radius[1] << ", " << m_radius[2] << "), ("
+ << m_scale[0] << ", " << m_scale[1] << ", " << m_scale[2] << "))";
+ }
+
+ Color3 eval (float r) const
+ {
+ return Color3 ((r < m_radius.x) ? pow3 (m_radius.x - r) * m_scale.x : 0,
+ (r < m_radius.y) ? pow3 (m_radius.y - r) * m_scale.y : 0,
+ (r < m_radius.z) ? pow3 (m_radius.z - r) * m_scale.z : 0);
+ }
+
+ float max_radius() const
+ {
+ return m_max_radius;
+ }
+};
+
+
+
+ClosureParam closure_bssrdf_cubic_params[] = {
+ CLOSURE_COLOR_PARAM (BSSRDFCubicClosure, m_radius),
+ CLOSURE_STRING_KEYPARAM ("label"),
+ CLOSURE_FINISH_PARAM(BSSRDFCubicClosure) };
+
+CLOSURE_PREPARE(closure_bssrdf_cubic_prepare, BSSRDFCubicClosure)
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/osl/debug.cpp b/intern/cycles/kernel/osl/debug.cpp
new file mode 100644
index 00000000000..8c3f8b2b323
--- /dev/null
+++ b/intern/cycles/kernel/osl/debug.cpp
@@ -0,0 +1,80 @@
+/*
+ * Adapted from Open Shading Language with this license:
+ *
+ * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
+ * All Rights Reserved.
+ *
+ * Modifications Copyright 2011, Blender Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Sony Pictures Imageworks nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <OpenImageIO/fmath.h>
+
+#include <OSL/genclosure.h>
+
+#include "osl_closures.h"
+
+CCL_NAMESPACE_BEGIN
+
+using namespace OSL;
+
+/// Debug closure
+///
+/// This is going to be used for mask AOV's and similar
+/// purposes. A tag (string) is always associated with
+/// this closure, that "selects: the channel where the
+/// weight should be sent.
+
+class DebugClosure : public ClosurePrimitive {
+public:
+ ustring m_tag;
+
+ DebugClosure () : ClosurePrimitive (Debug) { }
+
+ bool mergeable (const ClosurePrimitive *other) const {
+ const DebugClosure *comp = (const DebugClosure *)other;
+ return m_tag == comp->m_tag &&
+ ClosurePrimitive::mergeable(other);
+ }
+
+ size_t memsize () const { return sizeof(*this); }
+
+ const char *name () const { return "debug"; }
+
+ void print_on (std::ostream &out) const {
+ out << name() << " (\"" << m_tag.c_str() << "\")";
+ }
+
+};
+
+ClosureParam closure_debug_params[] = {
+ CLOSURE_STRING_PARAM(DebugClosure, m_tag),
+ CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_FINISH_PARAM(DebugClosure) };
+
+CLOSURE_PREPARE(closure_debug_prepare, DebugClosure)
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/osl/emissive.cpp b/intern/cycles/kernel/osl/emissive.cpp
new file mode 100644
index 00000000000..28d3c73e59b
--- /dev/null
+++ b/intern/cycles/kernel/osl/emissive.cpp
@@ -0,0 +1,107 @@
+/*
+ * Adapted from Open Shading Language with this license:
+ *
+ * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
+ * All Rights Reserved.
+ *
+ * Modifications Copyright 2011, Blender Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Sony Pictures Imageworks nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <OpenImageIO/fmath.h>
+
+#include <OSL/genclosure.h>
+
+#include "osl_closures.h"
+
+CCL_NAMESPACE_BEGIN
+
+using namespace OSL;
+
+/// Variable cone emissive closure
+///
+/// This primitive emits in a cone having a configurable
+/// penumbra area where the light decays to 0 reaching the
+/// outer_angle limit. It can also behave as a lambertian emitter
+/// if the provided angles are PI/2, which is the default
+///
+class GenericEmissiveClosure : public EmissiveClosure {
+public:
+ GenericEmissiveClosure() { }
+
+ void setup() { }
+
+ size_t memsize () const { return sizeof(*this); }
+
+ const char *name () const { return "emission"; }
+
+ void print_on (std::ostream &out) const {
+ out << name() << "()";
+ }
+
+ Color3 eval (const Vec3 &Ng, const Vec3 &omega_out) const
+ {
+ float cosNO = fabsf(Ng.dot(omega_out));
+ float res = cosNO > 0 ? 1.0f / float(M_PI) : 0.0f;
+ return Color3(res, res, res);
+ }
+
+ void sample (const Vec3 &Ng, float randu, float randv,
+ Vec3 &omega_out, float &pdf) const
+ {
+ // We don't do anything sophisticated here for the step
+ // We just sample the whole cone uniformly to the cosine
+ Vec3 T, B;
+ make_orthonormals(Ng, T, B);
+ float phi = 2 * (float) M_PI * randu;
+ float cosTheta = sqrtf(1.0f - 1.0f * randv);
+ float sinTheta = sqrtf(1.0f - cosTheta * cosTheta);
+ omega_out = (cosf(phi) * sinTheta) * T +
+ (sinf(phi) * sinTheta) * B +
+ cosTheta * Ng;
+ pdf = 1.0f / float(M_PI);
+ }
+
+ /// Return the probability distribution function in the direction omega_out,
+ /// given the parameters and the light's surface normal. This MUST match
+ /// the PDF computed by sample().
+ float pdf (const Vec3 &Ng,
+ const Vec3 &omega_out) const
+ {
+ float cosNO = Ng.dot(omega_out);
+ return cosNO > 0 ? 1.0f / float(M_PI) : 0.0f;
+ }
+};
+
+
+
+ClosureParam closure_emission_params[] = {
+ CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_FINISH_PARAM(GenericEmissiveClosure) };
+
+CLOSURE_PREPARE(closure_emission_prepare, GenericEmissiveClosure)
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/osl/nodes/CMakeLists.txt b/intern/cycles/kernel/osl/nodes/CMakeLists.txt
new file mode 100644
index 00000000000..435acc5f680
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/CMakeLists.txt
@@ -0,0 +1,69 @@
+
+# OSL node shaders
+
+SET(osl_sources
+ node_add_closure.osl
+ node_attribute.osl
+ node_background.osl
+ node_blend_texture.osl
+ node_bump.osl
+ node_clouds_texture.osl
+ node_convert_from_color.osl
+ node_convert_from_float.osl
+ node_convert_from_normal.osl
+ node_convert_from_point.osl
+ node_convert_from_vector.osl
+ node_diffuse_bsdf.osl
+ node_distorted_noise_texture.osl
+ node_emission.osl
+ node_environment_texture.osl
+ node_fresnel.osl
+ node_geometry.osl
+ node_glass_bsdf.osl
+ node_glossy_bsdf.osl
+ node_image_texture.osl
+ node_light_path.osl
+ node_magic_texture.osl
+ node_mapping.osl
+ node_marble_texture.osl
+ node_math.osl
+ node_mix.osl
+ node_mix_closure.osl
+ node_musgrave_texture.osl
+ node_noise_texture.osl
+ node_output_displacement.osl
+ node_output_surface.osl
+ node_output_volume.osl
+ node_sky_texture.osl
+ node_stucci_texture.osl
+ node_texture_coordinate.osl
+ node_translucent_bsdf.osl
+ node_transparent_bsdf.osl
+ node_value.osl
+ node_vector_math.osl
+ node_velvet_bsdf.osl
+ node_voronoi_texture.osl
+ node_ward_bsdf.osl
+ node_wood_texture.osl)
+
+SET(osl_headers
+ node_texture.h
+ stdosl.h)
+
+SET(oso_sources)
+
+FOREACH(_file ${osl_sources})
+ SET(osl_file ${CMAKE_CURRENT_SOURCE_DIR}/${_file})
+ STRING(REPLACE ".osl" ".oso" oso_file ${osl_file})
+ STRING(REPLACE ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} oso_file ${oso_file})
+ ADD_CUSTOM_COMMAND(
+ OUTPUT ${oso_file}
+ COMMAND ${OSL_COMPILER} -O2 ${osl_file}
+ DEPENDS ${osl_file} ${osl_headers})
+ LIST(APPEND oso_sources ${oso_file})
+ENDFOREACH()
+
+ADD_CUSTOM_TARGET(shader ALL DEPENDS ${oso_sources} ${osl_headers})
+
+INSTALL(FILES ${oso_sources} DESTINATION ${INSTALL_PATH}/cycles/shader)
+
diff --git a/intern/cycles/kernel/osl/nodes/node_add_closure.osl b/intern/cycles/kernel/osl/nodes/node_add_closure.osl
new file mode 100644
index 00000000000..ecf6bf5912e
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_add_closure.osl
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+shader node_add_closure(
+ closure color Closure1 = background(),
+ closure color Closure2 = background(),
+ output closure color Closure = background())
+{
+ Closure = Closure1 + Closure2;
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_attribute.osl b/intern/cycles/kernel/osl/nodes/node_attribute.osl
new file mode 100644
index 00000000000..d273d0c68d7
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_attribute.osl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+shader node_attribute(
+ string bump_offset = "center",
+ string name = "",
+ output point Vector = point(0.0, 0.0, 0.0),
+ output color Color = color(0.0, 0.0, 0.0),
+ output float Fac = 0.0)
+{
+ getattribute(name, Color);
+ Vector = point(Color);
+ getattribute(name, Fac);
+
+ if(bump_offset == "dx") {
+ Color += Dx(Color);
+ Vector += Dx(Vector);
+ Fac += Dx(Fac);
+ }
+ else if(bump_offset == "dy") {
+ Color += Dy(Color);
+ Vector += Dy(Vector);
+ Fac += Dy(Fac);
+ }
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_background.osl b/intern/cycles/kernel/osl/nodes/node_background.osl
new file mode 100644
index 00000000000..69f8d85a82e
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_background.osl
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+shader node_background(
+ color Color = color(0.8, 0.8, 0.8),
+ float Strength = 1.0,
+ output closure color Background = background())
+{
+ Background = Color*Strength*background();
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_blend_texture.osl b/intern/cycles/kernel/osl/nodes/node_blend_texture.osl
new file mode 100644
index 00000000000..de1bdaca90b
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_blend_texture.osl
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+#include "node_texture.h"
+
+/* Blend */
+
+float blend(point p, string progression, string axis)
+{
+ float x, y;
+
+ if(axis == "Vertical") {
+ x= p[1];
+ y= p[0];
+ }
+ else {
+ x= p[0];
+ y= p[1];
+ }
+
+ float result = 0.0;
+
+ if(progression == "Linear") {
+ result = (1.0 + x)/2.0;
+ }
+ else if(progression == "Quadratic") {
+ float r = max((1.0 + x)/2.0, 0.0);
+ result = r*r;
+ }
+ else if(progression == "Easing") {
+ float r = min(max((1.0 + x)/2.0, 0.0), 1.0);
+ float t = r*r;
+
+ result = (3.0*t - 2.0*t*r);
+ }
+ else if(progression == "Diagonal") {
+ result = (2.0 + x + y)/4.0;
+ }
+ else if(progression == "Radial") {
+ result = atan2(y, x)/(2*M_PI) + 0.5;
+ }
+ else {
+ float r = max(1.0 - sqrt(x*x + y*y + p[2]*p[2]), 0.0);
+
+ if(progression == "Quadratic Sphere")
+ result = r*r;
+ else if(progression == "Spherical")
+ result = r;
+ }
+
+ return result;
+}
+
+shader node_blend_texture(
+ string Progression = "Linear",
+ string Axis = "Horizontal",
+ point Vector = P,
+ output float Fac = 0.0)
+{
+ Fac = blend(Vector, Progression, Axis);
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_bump.osl b/intern/cycles/kernel/osl/nodes/node_bump.osl
new file mode 100644
index 00000000000..a3849e70f98
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_bump.osl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+/* "Bump Mapping Unparametrized Surfaces on the GPU"
+ * Morten S. Mikkelsen, 2010 */
+
+surface node_bump(
+ float SampleCenter = 0.0,
+ float SampleX = 0.0,
+ float SampleY = 0.0,
+ output normal Normal = N)
+{
+ float dx = SampleX - SampleCenter;
+ float dy = SampleY - SampleCenter;
+
+ vector dPdx = Dx(P);
+ vector dPdy = Dy(P);
+
+ vector Rx = cross(dPdy, N);
+ vector Ry = cross(N, dPdx);
+
+ float det = dot(dPdx, Rx);
+ vector surfgrad = dx*Rx + dy*Ry;
+
+ surfgrad *= 0.1; /* todo: remove this factor */
+
+ Normal = normalize(abs(det)*N - sign(det)*surfgrad);
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_clouds_texture.osl b/intern/cycles/kernel/osl/nodes/node_clouds_texture.osl
new file mode 100644
index 00000000000..6d244d81e27
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_clouds_texture.osl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+#include "node_texture.h"
+
+/* Turbulence */
+
+shader node_clouds_texture(
+ string Basis = "Perlin",
+ int Hard = 0,
+ int Depth = 2,
+ float Size = 0.25,
+ point Vector = P,
+ output float Fac = 0.0,
+ output color Color = color(0.0, 0.0, 0.0))
+{
+ float size = nonzero(Size, 1e-5);
+ point p = Vector/size;
+
+ Fac = noise_turbulence(p, Basis, Depth, Hard);
+
+ Color[0] = Fac;
+ Color[1] = noise_turbulence(point(p[1], p[0], p[2]), Basis, Depth, Hard);
+ Color[2] = noise_turbulence(point(p[1], p[2], p[0]), Basis, Depth, Hard);
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_convert_from_color.osl b/intern/cycles/kernel/osl/nodes/node_convert_from_color.osl
new file mode 100644
index 00000000000..97356139c48
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_convert_from_color.osl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+shader node_convert_from_color(
+ color Color = color(0.0, 0.0, 0.0),
+ output float Val = 0.0,
+ output vector Vector = vector(0.0, 0.0, 0.0),
+ output point Point = point(0.0, 0.0, 0.0),
+ output normal Normal = normal(0.0, 0.0, 0.0))
+{
+ Val = Color[0]*0.2126 + Color[1]*0.7152 + Color[2]*0.0722;
+ Vector = vector(Color[0], Color[1], Color[2]);
+ Point = point(Color[0], Color[1], Color[2]);
+ Normal = normal(Color[0], Color[1], Color[2]);
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_convert_from_float.osl b/intern/cycles/kernel/osl/nodes/node_convert_from_float.osl
new file mode 100644
index 00000000000..00e78f3bab4
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_convert_from_float.osl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+shader node_convert_from_float(
+ float Val = 0.0,
+ output color Color = color(0.0, 0.0, 0.0),
+ output vector Vector = vector(0.0, 0.0, 0.0),
+ output point Point = point(0.0, 0.0, 0.0),
+ output normal Normal = normal(0.0, 0.0, 0.0))
+{
+ Color = color(Val, Val, Val);
+ Vector = vector(Val, Val, Val);
+ Point = point(Val, Val, Val);
+ Normal = normal(Val, Val, Val);
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_convert_from_normal.osl b/intern/cycles/kernel/osl/nodes/node_convert_from_normal.osl
new file mode 100644
index 00000000000..0bb9092591d
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_convert_from_normal.osl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+shader node_convert_from_normal(
+ normal Normal = normal(0.0, 0.0, 0.0),
+ output float Val = 0.0,
+ output vector Vector = vector(0.0, 0.0, 0.0),
+ output color Color = color(0.0, 0.0, 0.0),
+ output point Point = point(0.0, 0.0, 0.0))
+{
+ Val = (Normal[0] + Normal[1] + Normal[2])*(1.0/3.0);
+ Vector = vector(Normal[0], Normal[1], Normal[2]);
+ Color = color(Normal[0], Normal[1], Normal[2]);
+ Point = point(Normal[0], Normal[1], Normal[2]);
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_convert_from_point.osl b/intern/cycles/kernel/osl/nodes/node_convert_from_point.osl
new file mode 100644
index 00000000000..e66d6a864d6
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_convert_from_point.osl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+shader node_convert_from_point(
+ point Point = point(0.0, 0.0, 0.0),
+ output float Val = 0.0,
+ output vector Vector = vector(0.0, 0.0, 0.0),
+ output color Color = color(0.0, 0.0, 0.0),
+ output normal Normal = normal(0.0, 0.0, 0.0))
+{
+ Val = (Point[0] + Point[1] + Point[2])*(1.0/3.0);
+ Vector = vector(Point[0], Point[1], Point[2]);
+ Color = color(Point[0], Point[1], Point[2]);
+ Normal = normal(Point[0], Point[1], Point[2]);
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_convert_from_vector.osl b/intern/cycles/kernel/osl/nodes/node_convert_from_vector.osl
new file mode 100644
index 00000000000..37ba9582cad
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_convert_from_vector.osl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+shader node_convert_from_vector(
+ vector Vector = vector(0.0, 0.0, 0.0),
+ output float Val = 0.0,
+ output color Color = color(0.0, 0.0, 0.0),
+ output point Point = point(0.0, 0.0, 0.0),
+ output normal Normal = normal(0.0, 0.0, 0.0))
+{
+ Val = (Vector[0] + Vector[1] + Vector[2])*(1.0/3.0);
+ Color = color(Vector[0], Vector[1], Vector[2]);
+ Point = point(Vector[0], Vector[1], Vector[2]);
+ Normal = normal(Vector[0], Vector[1], Vector[2]);
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_diffuse_bsdf.osl b/intern/cycles/kernel/osl/nodes/node_diffuse_bsdf.osl
new file mode 100644
index 00000000000..8cf161c17cc
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_diffuse_bsdf.osl
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+shader node_diffuse_bsdf(
+ color Color = color(0.8, 0.8, 0.8),
+ normal Normal = N,
+ output closure color BSDF = diffuse(Normal))
+{
+ BSDF = Color*diffuse(Normal);
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_distorted_noise_texture.osl b/intern/cycles/kernel/osl/nodes/node_distorted_noise_texture.osl
new file mode 100644
index 00000000000..bb338c4ef0f
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_distorted_noise_texture.osl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+#include "node_texture.h"
+
+/* Distorted Noise (variable lacunarity noise) */
+
+float noise_distorted(point p, string basis, string distortion_basis, float distortion)
+{
+ point r;
+
+ r[0] = noise_basis(p + point(13.5), basis) * distortion;
+ r[1] = noise_basis(p, basis) * distortion;
+ r[2] = noise_basis(p - point(13.5), basis) * distortion;
+
+ return noise_basis(p + r, distortion_basis); /* distorted-domain noise */
+}
+
+shader node_distorted_noise_texture(
+ string Basis = "Perlin",
+ string DistortionBasis = "Perlin",
+ float Distortion = 1.0,
+ float Size = 0.25,
+ point Vector = P,
+ output float Fac = 0.0)
+{
+ float size = nonzero(Size, 1e-5);
+ Fac = noise_distorted(Vector/size, Basis, DistortionBasis, Distortion);
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_emission.osl b/intern/cycles/kernel/osl/nodes/node_emission.osl
new file mode 100644
index 00000000000..8bfd1af173a
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_emission.osl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+shader node_emission(
+ int TotalPower = 0,
+ color Color = color(0.8, 0.8, 0.8),
+ float Strength = 1.0,
+ output closure color Emission = emission())
+{
+ if(TotalPower)
+ Emission = ((Strength/surfacearea())*Color)*emission();
+ else
+ Emission = (Strength*Color)*emission();
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_environment_texture.osl b/intern/cycles/kernel/osl/nodes/node_environment_texture.osl
new file mode 100644
index 00000000000..569b22d53ec
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_environment_texture.osl
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+shader node_environment_texture(
+ vector Vector = P,
+ string filename = "",
+ output color Color = color(0.0, 0.0, 0.0))
+{
+ Color = (color)environment(filename, Vector);
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_fresnel.h b/intern/cycles/kernel/osl/nodes/node_fresnel.h
new file mode 100644
index 00000000000..0c8a5276ede
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_fresnel.h
@@ -0,0 +1,21 @@
+
+float fresnel_dielectric(vector Incoming, normal Normal, float eta)
+{
+ /* compute fresnel reflectance without explicitly computing
+ the refracted direction */
+ float c = fabs(dot(Incoming, Normal));
+ float g = eta * eta - 1 + c * c;
+ float result;
+
+ if(g > 0) {
+ g = sqrt(g);
+ float A =(g - c)/(g + c);
+ float B =(c *(g + c)- 1)/(c *(g - c)+ 1);
+ result = 0.5 * A * A *(1 + B * B);
+ }
+ else
+ result = 1.0; /* TIR (no refracted component) */
+
+ return result;
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_fresnel.osl b/intern/cycles/kernel/osl/nodes/node_fresnel.osl
new file mode 100644
index 00000000000..ddc86db130f
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_fresnel.osl
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+#include "node_fresnel.h"
+
+shader node_fresnel(
+ float Fresnel = 0.3,
+ normal Normal = N,
+ output float Fac = 0.0)
+{
+ float f = max(1.0 - Fresnel, 0.00001);
+ Fac = fresnel_dielectric(I, Normal, backfacing()? f: 1.0/f);
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_geometry.osl b/intern/cycles/kernel/osl/nodes/node_geometry.osl
new file mode 100644
index 00000000000..bf76e2e597a
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_geometry.osl
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+shader node_geometry(
+ normal NormalIn = N,
+ string bump_offset = "center",
+
+ output point Position = point(0.0, 0.0, 0.0),
+ output normal Normal = normal(0.0, 0.0, 0.0),
+ output normal Tangent = normal(0.0, 0.0, 0.0),
+ output normal TrueNormal = normal(0.0, 0.0, 0.0),
+ output vector Incoming = vector(0.0, 0.0, 0.0),
+ output point UV = point(0.0, 0.0, 0.0),
+ output float Backfacing = 0.0)
+{
+ Position = P;
+ Normal = NormalIn;
+ Tangent = normalize(dPdu);
+ TrueNormal = Ng;
+ Incoming = I;
+ UV = point(u, v, 0.0);
+ Backfacing = backfacing();
+
+ if(bump_offset == "dx") {
+ Position += Dx(Position);
+ UV += Dx(UV);
+ }
+ else if(bump_offset == "dy") {
+ Position += Dy(Position);
+ UV += Dy(UV);
+ }
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_glass_bsdf.osl b/intern/cycles/kernel/osl/nodes/node_glass_bsdf.osl
new file mode 100644
index 00000000000..af946048011
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_glass_bsdf.osl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+#include "node_fresnel.h"
+
+shader node_glass_bsdf(
+ color Color = color(0.8, 0.8, 0.8),
+ string distribution = "Sharp",
+ float Roughness = 0.2,
+ float Fresnel = 0.3,
+ normal Normal = N,
+ output closure color BSDF = diffuse(Normal))
+{
+ float f = clamp(1.0 - Fresnel, 1e-5, 1.0 - 1e-5);
+ float eta = backfacing()? f: 1.0/f;
+ float Fr = fresnel_dielectric(I, Normal, eta);
+
+ if(distribution == "Sharp")
+ BSDF = Color*(Fr*reflection(Normal) + (1.0-Fr)*refraction(Normal, eta));
+ else if(distribution == "Beckmann")
+ BSDF = Color*(Fr*microfacet_beckmann(Normal, Roughness) + (1.0-Fr)*microfacet_beckmann_refraction(Normal, Roughness, eta));
+ else if(distribution == "GGX")
+ BSDF = Color*(Fr*microfacet_ggx(Normal, Roughness) + (1.0-Fr)*microfacet_ggx_refraction(Normal, Roughness, eta));
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_glossy_bsdf.osl b/intern/cycles/kernel/osl/nodes/node_glossy_bsdf.osl
new file mode 100644
index 00000000000..ca6bee74b38
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_glossy_bsdf.osl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+#include "node_fresnel.h"
+
+shader node_glossy_bsdf(
+ color Color = color(0.8, 0.8, 0.8),
+ string distribution = "Beckmann",
+ float Roughness = 0.2,
+ float Fresnel = 1.0,
+ normal Normal = N,
+ output closure color BSDF = diffuse(Normal))
+{
+ float Fr = 1.0;
+
+ if(Fresnel < 1.0) {
+ float eta = 1.0/clamp(1.0 - Fresnel, 1e-5, 1.0 - 1e-5);
+ Fr = fresnel_dielectric(I, Normal, eta);
+ }
+
+ if(distribution == "Sharp")
+ BSDF = (Fr*Color)*reflection(Normal);
+ else if(distribution == "Beckmann")
+ BSDF = (Fr*Color)*microfacet_beckmann(Normal, Roughness);
+ else if(distribution == "GGX")
+ BSDF = (Fr*Color)*microfacet_ggx(Normal, Roughness);
+
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_image_texture.osl b/intern/cycles/kernel/osl/nodes/node_image_texture.osl
new file mode 100644
index 00000000000..0dbcc122deb
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_image_texture.osl
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+shader node_image_texture(
+ point Vector = P,
+ string filename = "",
+ output color Color = color(0.0, 0.0, 0.0))
+{
+ Color = (color)texture(filename, Vector[0], 1.0-Vector[1], "wrap", "periodic");
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_light_path.osl b/intern/cycles/kernel/osl/nodes/node_light_path.osl
new file mode 100644
index 00000000000..081640428ab
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_light_path.osl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+shader node_light_path(
+ output float IsCameraRay = 0.0,
+ output float IsShadowRay = 0.0,
+ output float IsDiffuseRay = 0.0,
+ output float IsGlossyRay = 0.0,
+ output float IsReflectionRay = 0.0,
+ output float IsTransmissionRay = 0.0)
+{
+ IsCameraRay = raytype("camera");
+ IsShadowRay = raytype("shadow");
+ IsDiffuseRay = raytype("diffuse");
+ IsGlossyRay = raytype("glossy");
+ IsReflectionRay = raytype("reflection");
+ IsTransmissionRay = raytype("refraction");
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_magic_texture.osl b/intern/cycles/kernel/osl/nodes/node_magic_texture.osl
new file mode 100644
index 00000000000..0b6e980debc
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_magic_texture.osl
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+#include "node_texture.h"
+
+/* Magic */
+
+color magic(point p, int n, float turbulence)
+{
+ float turb = turbulence/5.0;
+
+ float x = sin((p[0] + p[1] + p[2])*5.0);
+ float y = cos((-p[0] + p[1] - p[2])*5.0);
+ float z = -cos((-p[0] - p[1] + p[2])*5.0);
+
+ if(n > 0) {
+ x *= turb;
+ y *= turb;
+ z *= turb;
+ y = -cos(x-y+z);
+ y *= turb;
+
+ if(n > 1) {
+ x= cos(x-y-z);
+ x *= turb;
+
+ if(n > 2) {
+ z= sin(-x-y-z);
+ z *= turb;
+
+ if(n > 3) {
+ x= -cos(-x+y-z);
+ x *= turb;
+
+ if(n > 4) {
+ y= -sin(-x+y+z);
+ y *= turb;
+
+ if(n > 5) {
+ y= -cos(-x+y+z);
+ y *= turb;
+
+ if(n > 6) {
+ x= cos(x+y+z);
+ x *= turb;
+
+ if(n > 7) {
+ z= sin(x+y-z);
+ z *= turb;
+
+ if(n > 8) {
+ x= -cos(-x-y+z);
+ x *= turb;
+
+ if(n > 9) {
+ y= -sin(x-y+z);
+ y *= turb;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if(turb != 0.0) {
+ turb *= 2.0;
+ x /= turb;
+ y /= turb;
+ z /= turb;
+ }
+
+ return color(0.5 - x, 0.5 - y, 0.5 - z);
+}
+
+shader node_magic_texture(
+ int Depth = 2,
+ float Turbulence = 5.0,
+ point Vector = P,
+ output color Color = color(0.0, 0.0, 0.0))
+{
+ Color = magic(Vector, Depth, Turbulence);
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_mapping.osl b/intern/cycles/kernel/osl/nodes/node_mapping.osl
new file mode 100644
index 00000000000..f342837d3c9
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_mapping.osl
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+shader node_mapping(
+ matrix Matrix = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ point Vector = point(0.0, 0.0, 0.0),
+ output point Vector_ = point(0.0, 0.0, 0.0))
+{
+ Vector_ = transform(Matrix, Vector);
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_marble_texture.osl b/intern/cycles/kernel/osl/nodes/node_marble_texture.osl
new file mode 100644
index 00000000000..9e18dee3235
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_marble_texture.osl
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+#include "node_texture.h"
+
+/* Marble */
+
+float marble(point p, float size, string type, string wave, string basis, int hard, float turb, int depth)
+{
+ float x = p[0];
+ float y = p[1];
+ float z = p[2];
+
+ float n = 5.0 * (x + y + z);
+
+ float mi = n + turb * noise_turbulence(p/size, basis, depth, hard);
+
+ mi = noise_wave(wave, mi);
+
+ if(type == "Sharp")
+ mi = sqrt(mi);
+ else if(type == "Sharper")
+ mi = sqrt(sqrt(mi));
+
+ return mi;
+}
+
+shader node_marble_texture(
+ string Type = "Soft",
+ string Wave = "Sine",
+ string Basis = "Perlin",
+ int Hard = 0,
+ float Size = 0.25,
+ float Turbulence = 5.0,
+ int Depth = 2,
+ point Vector = P,
+ output float Fac = 0.0)
+{
+ float size = nonzero(Size, 1e-5);
+ Fac = marble(Vector, size, Type, Wave, Basis, Hard, Turbulence, Depth);
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_math.osl b/intern/cycles/kernel/osl/nodes/node_math.osl
new file mode 100644
index 00000000000..be9bb71d511
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_math.osl
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+float safe_divide(float a, float b)
+{
+ float result;
+
+ if(b == 0.0)
+ result = 0.0;
+ else
+ result = a/b;
+
+ return result;
+}
+
+float safe_log(float a, float b)
+{
+ if(a < 0.0 || b < 0.0)
+ return 0.0;
+
+ return log(a)/log(b);
+}
+
+shader node_math(
+ string type = "Add",
+ float Value1 = 0.0,
+ float Value2 = 0.0,
+ output float Value = 0.0)
+{
+ /* OSL asin, acos, pow check for values that could give rise to nan */
+
+ if(type == "Add")
+ Value = Value1 + Value2;
+ if(type == "Subtract")
+ Value = Value1 - Value2;
+ if(type == "Multiply")
+ Value = Value1*Value2;
+ if(type == "Divide")
+ Value = safe_divide(Value1, Value2);
+ if(type == "Sine")
+ Value = sin(Value1);
+ if(type == "Cosine")
+ Value = cos(Value1);
+ if(type == "Tangent")
+ Value = tan(Value1);
+ if(type == "Arcsine")
+ Value = asin(Value1);
+ if(type == "Arccosine")
+ Value = acos(Value1);
+ if(type == "Arctangent")
+ Value = atan(Value1);
+ if(type == "Power")
+ Value = pow(Value1, Value2);
+ if(type == "Logarithm")
+ Value = safe_log(Value1, Value2);
+ if(type == "Minimum")
+ Value = min(Value1, Value2);
+ if(type == "Maximum")
+ Value = max(Value1, Value2);
+ if(type == "Round")
+ Value = floor(Value1 + 0.5);
+ if(type == "Less Than")
+ Value = Value1 < Value2;
+ if(type == "Greater Than")
+ Value = Value1 > Value2;
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_mix.osl b/intern/cycles/kernel/osl/nodes/node_mix.osl
new file mode 100644
index 00000000000..582aa7b3c60
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_mix.osl
@@ -0,0 +1,388 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+color rgb_to_hsv(color rgb)
+{
+ float cmax, cmin, h, s, v, cdelta;
+ color c;
+
+ cmax = max(rgb[0], max(rgb[1], rgb[2]));
+ cmin = min(rgb[0], min(rgb[1], rgb[2]));
+ cdelta = cmax - cmin;
+
+ v = cmax;
+
+ if(cmax != 0.0) {
+ s = cdelta/cmax;
+ }
+ else {
+ s = 0.0;
+ h = 0.0;
+ }
+
+ if(s == 0.0) {
+ h = 0.0;
+ }
+ else {
+ c = (color(cmax, cmax, cmax) - rgb)/cdelta;
+
+ if(rgb[0] == cmax) h = c[2] - c[1];
+ else if(rgb[1] == cmax) h = 2.0 + c[0] - c[2];
+ else h = 4.0 + c[1] - c[0];
+
+ h /= 6.0;
+
+ if(h < 0.0)
+ h += 1.0;
+ }
+
+ return color(h, s, v);
+}
+
+color hsv_to_rgb(color hsv)
+{
+ float i, f, p, q, t, h, s, v;
+ color rgb;
+
+ h = hsv[0];
+ s = hsv[1];
+ v = hsv[2];
+
+ if(s==0.0) {
+ rgb = color(v, v, v);
+ }
+ else {
+ if(h==1.0)
+ h = 0.0;
+
+ h *= 6.0;
+ i = floor(h);
+ f = h - i;
+ rgb = color(f, f, f);
+ p = v*(1.0-s);
+ q = v*(1.0-(s*f));
+ t = v*(1.0-(s*(1.0-f)));
+
+ if(i == 0.0) rgb = color(v, t, p);
+ else if(i == 1.0) rgb = color(q, v, p);
+ else if(i == 2.0) rgb = color(p, v, t);
+ else if(i == 3.0) rgb = color(p, q, v);
+ else if(i == 4.0) rgb = color(t, p, v);
+ else rgb = color(v, p, q);
+ }
+
+ return rgb;
+}
+
+color node_mix_blend(float t, color col1, color col2)
+{
+ return mix(col1, col2, t);
+}
+
+color node_mix_add(float t, color col1, color col2)
+{
+ return mix(col1, col1 + col2, t);
+}
+
+color node_mix_mul(float t, color col1, color col2)
+{
+ return mix(col1, col1 * col2, t);
+}
+
+color node_mix_screen(float t, color col1, color col2)
+{
+ float tm = 1.0 - t;
+
+ return color(1.0) - (color(tm) + t*(color(1.0) - col2))*(color(1.0) - col1);
+}
+
+color node_mix_overlay(float t, color col1, color col2)
+{
+ float tm = 1.0 - t;
+
+ color outcol = col1;
+
+ if(outcol[0] < 0.5)
+ outcol[0] *= tm + 2.0*t*col2[0];
+ else
+ outcol[0] = 1.0 - (tm + 2.0*t*(1.0 - col2[0]))*(1.0 - outcol[0]);
+
+ if(outcol[1] < 0.5)
+ outcol[1] *= tm + 2.0*t*col2[1];
+ else
+ outcol[1] = 1.0 - (tm + 2.0*t*(1.0 - col2[1]))*(1.0 - outcol[1]);
+
+ if(outcol[2] < 0.5)
+ outcol[2] *= tm + 2.0*t*col2[2];
+ else
+ outcol[2] = 1.0 - (tm + 2.0*t*(1.0 - col2[2]))*(1.0 - outcol[2]);
+
+ return outcol;
+}
+
+color node_mix_sub(float t, color col1, color col2)
+{
+ return mix(col1, col1 - col2, t);
+}
+
+color node_mix_div(float t, color col1, color col2)
+{
+ float tm = 1.0 - t;
+
+ color outcol = col1;
+
+ if(col2[0] != 0.0) outcol[0] = tm*outcol[0] + t*outcol[0]/col2[0];
+ if(col2[1] != 0.0) outcol[1] = tm*outcol[1] + t*outcol[1]/col2[1];
+ if(col2[2] != 0.0) outcol[2] = tm*outcol[2] + t*outcol[2]/col2[2];
+
+ return outcol;
+}
+
+color node_mix_diff(float t, color col1, color col2)
+{
+ return mix(col1, abs(col1 - col2), t);
+}
+
+color node_mix_dark(float t, color col1, color col2)
+{
+ return min(col1, col2*t);
+}
+
+color node_mix_light(float t, color col1, color col2)
+{
+ return max(col1, col2*t);
+}
+
+color node_mix_dodge(float t, color col1, color col2)
+{
+ color outcol = col1;
+
+ if(outcol[0] != 0.0) {
+ float tmp = 1.0 - t*col2[0];
+ if(tmp <= 0.0)
+ outcol[0] = 1.0;
+ else if((tmp = outcol[0]/tmp) > 1.0)
+ outcol[0] = 1.0;
+ else
+ outcol[0] = tmp;
+ }
+ if(outcol[1] != 0.0) {
+ float tmp = 1.0 - t*col2[1];
+ if(tmp <= 0.0)
+ outcol[1] = 1.0;
+ else if((tmp = outcol[1]/tmp) > 1.0)
+ outcol[1] = 1.0;
+ else
+ outcol[1] = tmp;
+ }
+ if(outcol[2] != 0.0) {
+ float tmp = 1.0 - t*col2[2];
+ if(tmp <= 0.0)
+ outcol[2] = 1.0;
+ else if((tmp = outcol[2]/tmp) > 1.0)
+ outcol[2] = 1.0;
+ else
+ outcol[2] = tmp;
+ }
+
+ return outcol;
+}
+
+color node_mix_burn(float t, color col1, color col2)
+{
+ float tmp, tm = 1.0 - t;
+
+ color outcol = col1;
+
+ tmp = tm + t*col2[0];
+ if(tmp <= 0.0)
+ outcol[0] = 0.0;
+ else if((tmp = (1.0 - (1.0 - outcol[0])/tmp)) < 0.0)
+ outcol[0] = 0.0;
+ else if(tmp > 1.0)
+ outcol[0] = 1.0;
+ else
+ outcol[0] = tmp;
+
+ tmp = tm + t*col2[1];
+ if(tmp <= 0.0)
+ outcol[1] = 0.0;
+ else if((tmp = (1.0 - (1.0 - outcol[1])/tmp)) < 0.0)
+ outcol[1] = 0.0;
+ else if(tmp > 1.0)
+ outcol[1] = 1.0;
+ else
+ outcol[1] = tmp;
+
+ tmp = tm + t*col2[2];
+ if(tmp <= 0.0)
+ outcol[2] = 0.0;
+ else if((tmp = (1.0 - (1.0 - outcol[2])/tmp)) < 0.0)
+ outcol[2] = 0.0;
+ else if(tmp > 1.0)
+ outcol[2] = 1.0;
+ else
+ outcol[2] = tmp;
+
+ return outcol;
+}
+
+color node_mix_hue(float t, color col1, color col2)
+{
+ color outcol = col1;
+ color hsv2 = rgb_to_hsv(col2);
+
+ if(hsv2[1] != 0.0) {
+ color hsv = rgb_to_hsv(outcol);
+ hsv[0] = hsv2[0];
+ color tmp = hsv_to_rgb(hsv);
+
+ outcol = mix(outcol, tmp, t);
+ }
+
+ return outcol;
+}
+
+color node_mix_sat(float t, color col1, color col2)
+{
+ float tm = 1.0 - t;
+
+ color outcol = col1;
+
+ color hsv = rgb_to_hsv(outcol);
+
+ if(hsv[1] != 0.0) {
+ color hsv2 = rgb_to_hsv(col2);
+
+ hsv[1] = tm*hsv[1] + t*hsv2[1];
+ outcol = hsv_to_rgb(hsv);
+ }
+
+ return outcol;
+}
+
+color node_mix_val(float t, color col1, color col2)
+{
+ float tm = 1.0 - t;
+
+ color hsv = rgb_to_hsv(col1);
+ color hsv2 = rgb_to_hsv(col2);
+
+ hsv[2] = tm*hsv[2] + t*hsv2[2];
+
+ return hsv_to_rgb(hsv);
+}
+
+color node_mix_color(float t, color col1, color col2)
+{
+ color outcol = col1;
+ color hsv2 = rgb_to_hsv(col2);
+
+ if(hsv2[1] != 0.0) {
+ color hsv = rgb_to_hsv(outcol);
+ hsv[0] = hsv2[0];
+ hsv[1] = hsv2[1];
+ color tmp = hsv_to_rgb(hsv);
+
+ outcol = mix(outcol, tmp, t);
+ }
+
+ return outcol;
+}
+
+color node_mix_soft(float t, color col1, color col2)
+{
+ float tm = 1.0 - t;
+
+ color one= color(1.0);
+ color scr= one - (one - col2)*(one - col1);
+
+ return tm*col1 + t*((one - col1)*col2*col1 + col1*scr);
+}
+
+color node_mix_linear(float t, color col1, color col2)
+{
+ color outcol = col1;
+
+ if(col2[0] > 0.5)
+ outcol[0]= col1[0] + t*(2.0*(col2[0] - 0.5));
+ else
+ outcol[0]= col1[0] + t*(2.0*(col2[0]) - 1.0);
+
+ if(col2[1] > 0.5)
+ outcol[1]= col1[1] + t*(2.0*(col2[1] - 0.5));
+ else
+ outcol[1]= col1[1] + t*(2.0*(col2[1]) - 1.0);
+
+ if(col2[2] > 0.5)
+ outcol[2]= col1[2] + t*(2.0*(col2[2] - 0.5));
+ else
+ outcol[2]= col1[2] + t*(2.0*(col2[2]) - 1.0);
+
+ return outcol;
+}
+
+shader node_mix(
+ string type = "Mix",
+ float Fac = 0.5,
+ color Color1 = color(0.0, 0.0, 0.0),
+ color Color2 = color(0.0, 0.0, 0.0),
+ output color Color = color(0.0, 0.0, 0.0))
+{
+ float t = clamp(Fac, 0.0, 1.0);
+
+ if(type == "Mix")
+ Color = node_mix_blend(t, Color1, Color2);
+ if(type == "Add")
+ Color = node_mix_add(t, Color1, Color2);
+ if(type == "Multiply")
+ Color = node_mix_mul(t, Color1, Color2);
+ if(type == "Screen")
+ Color = node_mix_screen(t, Color1, Color2);
+ if(type == "Overlay")
+ Color = node_mix_overlay(t, Color1, Color2);
+ if(type == "Subtract")
+ Color = node_mix_sub(t, Color1, Color2);
+ if(type == "Divide")
+ Color = node_mix_div(t, Color1, Color2);
+ if(type == "Difference")
+ Color = node_mix_diff(t, Color1, Color2);
+ if(type == "Darken")
+ Color = node_mix_dark(t, Color1, Color2);
+ if(type == "Lighten")
+ Color = node_mix_light(t, Color1, Color2);
+ if(type == "Dodge")
+ Color = node_mix_dodge(t, Color1, Color2);
+ if(type == "Burn")
+ Color = node_mix_burn(t, Color1, Color2);
+ if(type == "Hue")
+ Color = node_mix_hue(t, Color1, Color2);
+ if(type == "Saturation")
+ Color = node_mix_sat(t, Color1, Color2);
+ if(type == "Value")
+ Color = node_mix_val (t, Color1, Color2);
+ if(type == "Color")
+ Color = node_mix_color(t, Color1, Color2);
+ if(type == "Soft Light")
+ Color = node_mix_soft(t, Color1, Color2);
+ if(type == "Linear Light")
+ Color = node_mix_linear(t, Color1, Color2);
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_mix_closure.osl b/intern/cycles/kernel/osl/nodes/node_mix_closure.osl
new file mode 100644
index 00000000000..1a377abd381
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_mix_closure.osl
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+shader node_mix_closure(
+ float Fac = 0.5,
+ closure color Closure1 = background(),
+ closure color Closure2 = background(),
+ output closure color Closure = background())
+{
+ float t = clamp(Fac, 0.0, 1.0);
+ Closure = (1.0 - t)*Closure1 + t*Closure2;
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_musgrave_texture.osl b/intern/cycles/kernel/osl/nodes/node_musgrave_texture.osl
new file mode 100644
index 00000000000..fbd0ce5c3bd
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_musgrave_texture.osl
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+#include "node_texture.h"
+
+/* Musgrave fBm
+ *
+ * H: fractal increment parameter
+ * lacunarity: gap between successive frequencies
+ * octaves: number of frequencies in the fBm
+ *
+ * from "Texturing and Modelling: A procedural approach"
+ */
+
+float noise_musgrave_fBm(point p, string basis, float H, float lacunarity, float octaves)
+{
+ float rmd;
+ float value = 0.0;
+ float pwr = 1.0;
+ float pwHL = pow(lacunarity, -H);
+ int i;
+
+ for(i = 0; i < (int)octaves; i++) {
+ value += noise_basis(p, basis) * pwr;
+ pwr *= pwHL;
+ p *= lacunarity;
+ }
+
+ rmd = octaves - floor(octaves);
+ if(rmd != 0.0)
+ value += rmd * noise_basis(p, basis) * pwr;
+
+ return value;
+}
+
+/* Musgrave Multifractal
+ *
+ * H: highest fractal dimension
+ * lacunarity: gap between successive frequencies
+ * octaves: number of frequencies in the fBm
+ */
+
+float noise_musgrave_multi_fractal(point p, string basis, float H, float lacunarity, float octaves)
+{
+ float rmd;
+ float value = 1.0;
+ float pwr = 1.0;
+ float pwHL = pow(lacunarity, -H);
+ int i;
+
+ for(i = 0; i < (int)octaves; i++) {
+ value *= (pwr * noise_basis(p, basis) + 1.0);
+ pwr *= pwHL;
+ p *= lacunarity;
+ }
+
+ rmd = octaves - floor(octaves);
+ if(rmd != 0.0)
+ value *= (rmd * pwr * noise_basis(p, basis) + 1.0); /* correct? */
+
+ return value;
+}
+
+/* Musgrave Heterogeneous Terrain
+ *
+ * H: fractal dimension of the roughest area
+ * lacunarity: gap between successive frequencies
+ * octaves: number of frequencies in the fBm
+ * offset: raises the terrain from `sea level'
+ */
+
+float noise_musgrave_hetero_terrain(point p, string basis, float H, float lacunarity, float octaves, float offset)
+{
+ float value, increment, rmd;
+ float pwHL = pow(lacunarity, -H);
+ float pwr = pwHL;
+ int i;
+
+ /* first unscaled octave of function; later octaves are scaled */
+ value = offset + noise_basis(p, basis);
+ p *= lacunarity;
+
+ for(i = 1; i < (int)octaves; i++) {
+ increment = (noise_basis(p, basis) + offset) * pwr * value;
+ value += increment;
+ pwr *= pwHL;
+ p *= lacunarity;
+ }
+
+ rmd = octaves - floor(octaves);
+ if(rmd != 0.0) {
+ increment = (noise_basis(p, basis) + offset) * pwr * value;
+ value += rmd * increment;
+ }
+
+ return value;
+}
+
+/* Hybrid Additive/Multiplicative Multifractal Terrain
+ *
+ * H: fractal dimension of the roughest area
+ * lacunarity: gap between successive frequencies
+ * octaves: number of frequencies in the fBm
+ * offset: raises the terrain from `sea level'
+ */
+
+float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H, float lacunarity, float octaves, float offset, float gain)
+{
+ float result, signal, weight, rmd;
+ float pwHL = pow(lacunarity, -H);
+ float pwr = pwHL;
+ int i;
+
+ result = noise_basis(p, basis) + offset;
+ weight = gain * result;
+ p *= lacunarity;
+
+ for(i = 1; (weight > 0.001) && (i < (int)octaves); i++) {
+ if(weight > 1.0)
+ weight = 1.0;
+
+ signal = (noise_basis(p, basis) + offset) * pwr;
+ pwr *= pwHL;
+ result += weight * signal;
+ weight *= gain * signal;
+ p *= lacunarity;
+ }
+
+ rmd = octaves - floor(octaves);
+ if(rmd != 0.0)
+ result += rmd * ((noise_basis(p, basis) + offset) * pwr);
+
+ return result;
+}
+
+/* Ridged Multifractal Terrain
+ *
+ * H: fractal dimension of the roughest area
+ * lacunarity: gap between successive frequencies
+ * octaves: number of frequencies in the fBm
+ * offset: raises the terrain from `sea level'
+ */
+
+float noise_musgrave_ridged_multi_fractal(point p, string basis, float H, float lacunarity, float octaves, float offset, float gain)
+{
+ float result, signal, weight;
+ float pwHL = pow(lacunarity, -H);
+ float pwr = pwHL;
+ int i;
+
+ signal = offset - fabs(noise_basis(p, basis));
+ signal *= signal;
+ result = signal;
+ weight = 1.0;
+
+ for(i = 1; i < (int)octaves; i++) {
+ p *= lacunarity;
+ weight = clamp(signal * gain, 0.0, 1.0);
+ signal = offset - fabs(noise_basis(p, basis));
+ signal *= signal;
+ signal *= weight;
+ result += signal * pwr;
+ pwr *= pwHL;
+ }
+
+ return result;
+}
+
+/* Shader */
+
+shader node_musgrave_texture(
+ string Type = "fBM",
+ string Basis = "Perlin",
+ float Dimension = 2.0,
+ float Lacunarity = 1.0,
+ float Octaves = 2.0,
+ float Offset = 0.0,
+ float Intensity = 1.0,
+ float Gain = 1.0,
+ float Size = 0.25,
+ point Vector = P,
+ output float Fac = 0.0)
+{
+ float dimension = max(Dimension, 0.0);
+ float octaves = max(Octaves, 0.0);
+ float lacunarity = max(Lacunarity, 1e-5);
+ float size = nonzero(Size, 1e-5);
+
+ point p = Vector/size;
+
+ if(Type == "Multifractal")
+ Fac = Intensity*noise_musgrave_multi_fractal(p, Basis, dimension, lacunarity, octaves);
+ else if(Type == "fBM")
+ Fac = Intensity*noise_musgrave_fBm(p, Basis, dimension, lacunarity, octaves);
+ else if(Type == "Hybrid Multifractal")
+ Fac = Intensity*noise_musgrave_hybrid_multi_fractal(p, Basis, dimension, lacunarity, octaves, Offset, Gain);
+ else if(Type == "Ridged Multifractal")
+ Fac = Intensity*noise_musgrave_ridged_multi_fractal(p, Basis, dimension, lacunarity, octaves, Offset, Gain);
+ else if(Type == "Hetero Terrain")
+ Fac = Intensity*noise_musgrave_hetero_terrain(p, Basis, dimension, lacunarity, octaves, Offset);
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_noise_texture.osl b/intern/cycles/kernel/osl/nodes/node_noise_texture.osl
new file mode 100644
index 00000000000..193ed67d16e
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_noise_texture.osl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+#include "node_texture.h"
+
+shader node_noise_texture(
+ point Vector = P,
+ output color Color = color(0.0, 0.0, 0.0),
+ output float Fac = 0.0)
+{
+ point p = Vector*1e8;
+
+ float r = cellnoise(p);
+ float g = cellnoise(point(p[1], p[0], p[2]));
+ float b = cellnoise(point(p[1], p[2], p[0]));
+
+ Fac = r;
+ Color = color(r, g, b);
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_output_displacement.osl b/intern/cycles/kernel/osl/nodes/node_output_displacement.osl
new file mode 100644
index 00000000000..a6b452c532a
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_output_displacement.osl
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+displacement node_output_displacement(float Displacement = 0.0)
+{
+ P += N*Displacement*0.1; /* todo: get rid of this factor */
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_output_surface.osl b/intern/cycles/kernel/osl/nodes/node_output_surface.osl
new file mode 100644
index 00000000000..6efaf91121b
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_output_surface.osl
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+surface node_output_surface(closure color Surface = background())
+{
+ Ci = Surface;
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_output_volume.osl b/intern/cycles/kernel/osl/nodes/node_output_volume.osl
new file mode 100644
index 00000000000..18094242dc7
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_output_volume.osl
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+volume node_output_volume(closure color Volume = background())
+{
+ Ci = Volume;
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_sky_texture.osl b/intern/cycles/kernel/osl/nodes/node_sky_texture.osl
new file mode 100644
index 00000000000..fdb9b1d9708
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_sky_texture.osl
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+struct KernelSunSky {
+ /* sun direction in spherical and cartesian */
+ float theta, phi;
+ vector dir;
+
+ /* perez function parameters */
+ float zenith_Y, zenith_x, zenith_y;
+ float perez_Y[5], perez_x[5], perez_y[5];
+};
+
+color xyY_to_xyz(float x, float y, float Y)
+{
+ float X, Z;
+
+ if(y != 0.0) X = (x / y) * Y;
+ else X = 0.0;
+
+ if(y != 0.0 && Y != 0.0) Z = ((1.0 - x - y) / y) * Y;
+ else Z = 0.0;
+
+ return color(X, Y, Z);
+}
+
+color xyz_to_rgb(float x, float y, float z)
+{
+ return color(3.240479 * x + -1.537150 * y + -0.498535 * z,
+ -0.969256 * x + 1.875991 * y + 0.041556 * z,
+ 0.055648 * x + -0.204043 * y + 1.057311 * z);
+}
+
+float sky_angle_between(float thetav, float phiv, float theta, float phi)
+{
+ float cospsi = sin(thetav)*sin(theta)*cos(phi - phiv) + cos(thetav)*cos(theta);
+
+ if(cospsi > 1.0)
+ return 0.0;
+ if(cospsi < -1.0)
+ return M_PI;
+
+ return acos(cospsi);
+}
+
+vector sky_spherical_coordinates(vector dir)
+{
+ return vector(acos(dir[2]), atan2(dir[0], dir[1]), 0);
+}
+
+float sky_perez_function(float lam[5], float theta, float gamma)
+{
+ float ctheta = cos(theta);
+ float cgamma = cos(gamma);
+
+ return (1.0 + lam[0]*exp(lam[1] / ctheta)) * (1.0 + lam[2]*exp(lam[3]*gamma) + lam[4]*cgamma*cgamma);
+}
+
+color sky_xyz_radiance(KernelSunSky sunsky, vector dir)
+{
+ /* convert vector to spherical coordinates */
+ vector spherical = sky_spherical_coordinates(dir);
+ float theta = spherical[0];
+ float phi = spherical[1];
+
+ /* angle between sun direction and dir */
+ float gamma = sky_angle_between(theta, phi, sunsky.theta, sunsky.phi);
+
+ /* clamp theta to horizon */
+ theta = min(theta, M_PI_2 - 0.001);
+
+ /* compute xyY color space values */
+ float x = sunsky.zenith_x * sky_perez_function(sunsky.perez_x, theta, gamma);
+ float y = sunsky.zenith_y * sky_perez_function(sunsky.perez_y, theta, gamma);
+ float Y = sunsky.zenith_Y * sky_perez_function(sunsky.perez_Y, theta, gamma);
+
+ /* convert to RGB */
+ color xyz = xyY_to_xyz(x, y, Y);
+ return xyz_to_rgb(xyz[0], xyz[1], xyz[2]);
+}
+
+void precompute_sunsky(vector dir, float turbidity, output KernelSunSky sunsky)
+{
+ vector spherical = sky_spherical_coordinates(dir);
+ float theta = spherical[0];
+ float phi = spherical[1];
+
+ sunsky.theta = theta;
+ sunsky.phi = phi;
+ sunsky.dir = dir;
+
+ float theta2 = theta*theta;
+ float theta3 = theta*theta*theta;
+ float T = turbidity;
+ float T2 = T*T;
+
+ float chi = (4.0/ 9.0- T / 120.0) * (M_PI - 2.0* theta);
+ sunsky.zenith_Y = (4.0453*T - 4.9710) * tan(chi) - 0.2155*T + 2.4192;
+ sunsky.zenith_Y *= 0.06;
+
+ sunsky.zenith_x =
+ (0.00166* theta3 - 0.00375* theta2 + 0.00209* theta)*T2 +
+ (-0.02903* theta3 + 0.06377* theta2 - 0.03202* theta + 0.00394)*T +
+ (0.11693* theta3 - 0.21196* theta2 + 0.06052* theta + 0.25886);
+
+ sunsky.zenith_y =
+ (0.00275* theta3 - 0.00610* theta2 + 0.00317* theta)*T2 +
+ (-0.04214* theta3 + 0.08970* theta2 - 0.04153* theta + 0.00516)*T +
+ (0.15346* theta3 - 0.26756* theta2 + 0.06670* theta + 0.26688);
+
+ sunsky.perez_Y[0] = (0.1787*T - 1.4630);
+ sunsky.perez_Y[1] = (-0.3554*T + 0.4275);
+ sunsky.perez_Y[2] = (-0.0227*T + 5.3251);
+ sunsky.perez_Y[3] = (0.1206*T - 2.5771);
+ sunsky.perez_Y[4] = (-0.0670*T + 0.3703);
+
+ sunsky.perez_x[0] = (-0.0193*T - 0.2592);
+ sunsky.perez_x[1] = (-0.0665*T + 0.0008);
+ sunsky.perez_x[2] = (-0.0004*T + 0.2125);
+ sunsky.perez_x[3] = (-0.0641*T - 0.8989);
+ sunsky.perez_x[4] = (-0.0033*T + 0.0452);
+
+ sunsky.perez_y[0] = (-0.0167*T - 0.2608);
+ sunsky.perez_y[1] = (-0.0950*T + 0.0092);
+ sunsky.perez_y[2] = (-0.0079*T + 0.2102);
+ sunsky.perez_y[3] = (-0.0441*T - 1.6537);
+ sunsky.perez_y[4] = (-0.0109*T + 0.0529);
+
+ sunsky.zenith_Y /= sky_perez_function(sunsky.perez_Y, 0, theta);
+ sunsky.zenith_x /= sky_perez_function(sunsky.perez_x, 0, theta);
+ sunsky.zenith_y /= sky_perez_function(sunsky.perez_y, 0, theta);
+}
+
+shader node_sky_texture(
+ vector Vector = P,
+ vector sun_direction = vector(0, 0, 1),
+ float turbidity = 2.2,
+ output color Color = color(0.0, 0.0, 0.0))
+{
+ KernelSunSky sunsky;
+
+ precompute_sunsky(sun_direction, turbidity, sunsky);
+ Color = sky_xyz_radiance(sunsky, Vector);
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_stucci_texture.osl b/intern/cycles/kernel/osl/nodes/node_stucci_texture.osl
new file mode 100644
index 00000000000..f03e03d9a98
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_stucci_texture.osl
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+#include "node_texture.h"
+
+/* Stucci */
+
+shader node_stucci_texture(
+ string Type = "Plastic",
+ string Basis = "Perlin",
+ int Hard = 0,
+ float Turbulence = 1.0,
+ float Size = 0.25,
+ point Vector = P,
+ output float Fac = 0.0)
+{
+ float size = nonzero(Size, 1e-5);
+ point p = Vector/size;
+
+ float b2 = noise_basis_hard(p, Basis, Hard);
+ float ofs = Turbulence/200.0;
+
+ if(Type != "Plastic")
+ ofs *= b2*b2;
+
+ Fac = noise_basis_hard(point(p[0], p[1], p[2]+ofs), Basis, Hard);
+
+ if(Type == "Wall Out")
+ Fac = 1.0 - Fac;
+
+ Fac = max(Fac, 0.0);
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_texture.h b/intern/cycles/kernel/osl/nodes/node_texture.h
new file mode 100644
index 00000000000..8adb0e8aeb5
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_texture.h
@@ -0,0 +1,251 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/* Voronoi Distances */
+
+float voronoi_distance(string distance_metric, vector d, float e)
+{
+ float result = 0.0;
+
+ if(distance_metric == "Distance Squared")
+ result = dot(d, d);
+ if(distance_metric == "Actual Distance")
+ result = length(d);
+ if(distance_metric == "Manhattan")
+ result = fabs(d[0]) + fabs(d[1]) + fabs(d[2]);
+ if(distance_metric == "Chebychev")
+ result = max(fabs(d[0]), max(fabs(d[1]), fabs(d[2])));
+ if(distance_metric == "Minkovsky 1/2")
+ result = sqrt(fabs(d[0])) + sqrt(fabs(d[1])) + sqrt(fabs(d[1]));
+ if(distance_metric == "Minkovsky 4")
+ result = sqrt(sqrt(dot(d*d, d*d)));
+ if(distance_metric == "Minkovsky")
+ result = pow(pow(fabs(d[0]), e) + pow(fabs(d[1]), e) + pow(fabs(d[2]), e), 1.0/e);
+
+ return result;
+}
+
+/* Voronoi / Worley like */
+
+color cellnoise_color(point p)
+{
+ float r = cellnoise(p);
+ float g = cellnoise(point(p[1], p[0], p[2]));
+ float b = cellnoise(point(p[1], p[2], p[0]));
+
+ return color(r, g, b);
+}
+
+void voronoi(point p, string distance_metric, float e, float da[4], point pa[4])
+{
+ /* returns distances in da and point coords in pa */
+ int xx, yy, zz, xi, yi, zi;
+
+ xi = (int)floor(p[0]);
+ yi = (int)floor(p[1]);
+ zi = (int)floor(p[2]);
+
+ da[0] = 1e10;
+ da[1] = 1e10;
+ da[2] = 1e10;
+ da[3] = 1e10;
+
+ for(xx = xi-1; xx <= xi+1; xx++) {
+ for(yy = yi-1; yy <= yi+1; yy++) {
+ for(zz = zi-1; zz <= zi+1; zz++) {
+ point ip = point(xx, yy, zz);
+ point vp = (point)cellnoise_color(ip);
+ point pd = p - (vp + ip);
+ float d = voronoi_distance(distance_metric, pd, e);
+
+ vp += point(xx, yy, zz);
+
+ if(d < da[0]) {
+ da[3] = da[2];
+ da[2] = da[1];
+ da[1] = da[0];
+ da[0] = d;
+
+ pa[3] = pa[2];
+ pa[2] = pa[1];
+ pa[1] = pa[0];
+ pa[0] = vp;
+ }
+ else if(d < da[1]) {
+ da[3] = da[2];
+ da[2] = da[1];
+ da[1] = d;
+
+ pa[3] = pa[2];
+ pa[2] = pa[1];
+ pa[1] = vp;
+ }
+ else if(d < da[2]) {
+ da[3] = da[2];
+ da[2] = d;
+
+ pa[3] = pa[2];
+ pa[2] = vp;
+ }
+ else if(d < da[3]) {
+ da[3] = d;
+ pa[3] = vp;
+ }
+ }
+ }
+ }
+}
+
+float voronoi_Fn(point p, int n)
+{
+ float da[4];
+ point pa[4];
+
+ voronoi(p, "Distance Squared", 0, da, pa);
+
+ return da[n];
+}
+
+float voronoi_FnFn(point p, int n1, int n2)
+{
+ float da[4];
+ point pa[4];
+
+ voronoi(p, "Distance Squared", 0, da, pa);
+
+ return da[n2] - da[n1];
+}
+
+float voronoi_F1(point p) { return voronoi_Fn(p, 0); }
+float voronoi_F2(point p) { return voronoi_Fn(p, 1); }
+float voronoi_F3(point p) { return voronoi_Fn(p, 2); }
+float voronoi_F4(point p) { return voronoi_Fn(p, 3); }
+float voronoi_F1F2(point p) { return voronoi_FnFn(p, 0, 1); }
+
+float voronoi_Cr(point p)
+{
+ /* crackle type pattern, just a scale/clamp of F2-F1 */
+ float t = 10.0*voronoi_F1F2(p);
+ return (t > 1.0)? 1.0: t;
+}
+
+float voronoi_F1S(point p) { return 2.0*voronoi_F1(p) - 1.0; }
+float voronoi_F2S(point p) { return 2.0*voronoi_F2(p) - 1.0; }
+float voronoi_F3S(point p) { return 2.0*voronoi_F3(p) - 1.0; }
+float voronoi_F4S(point p) { return 2.0*voronoi_F4(p) - 1.0; }
+float voronoi_F1F2S(point p) { return 2.0*voronoi_F1F2(p) - 1.0; }
+float voronoi_CrS(point p) { return 2.0*voronoi_Cr(p) - 1.0; }
+
+/* Noise Bases */
+
+float noise_basis(point p, string basis)
+{
+ float result = 0.0;
+
+ if(basis == "Perlin")
+ result = noise(p);
+ if(basis == "Voronoi F1")
+ result = voronoi_F1S(p);
+ if(basis == "Voronoi F2")
+ result = voronoi_F2S(p);
+ if(basis == "Voronoi F3")
+ result = voronoi_F3S(p);
+ if(basis == "Voronoi F4")
+ result = voronoi_F4S(p);
+ if(basis == "Voronoi F2-F1")
+ result = voronoi_F1F2S(p);
+ if(basis == "Voronoi Crackle")
+ result = voronoi_CrS(p);
+ if(basis == "Cell Noise")
+ result = cellnoise(p);
+
+ return result;
+}
+
+/* Soft/Hard Noise */
+
+float noise_basis_hard(point p, string basis, int hard)
+{
+ float t = noise_basis(p, basis);
+ return (hard)? fabs(2.0*t - 1.0): t;
+}
+
+/* Waves */
+
+float noise_wave(string wave, float a)
+{
+ float result = 0.0;
+
+ if(wave == "Sine") {
+ result = 0.5 + 0.5*sin(a);
+ }
+ else if(wave == "Saw") {
+ float b = 2*M_PI;
+ int n = (int)(a / b);
+ a -= n*b;
+ if(a < 0) a += b;
+
+ result = a / b;
+ }
+ else if(wave == "Tri") {
+ float b = 2*M_PI;
+ float rmax = 1.0;
+
+ result = rmax - 2.0*fabs(floor((a*(1.0/b))+0.5) - (a*(1.0/b)));
+ }
+
+ return result;
+}
+
+/* Turbulence */
+
+float noise_turbulence(point p, string basis, int octaves, int hard)
+{
+ float fscale = 1.0;
+ float amp = 1.0;
+ float sum = 0.0;
+ int i;
+
+ for(i = 0; i <= octaves; i++) {
+ float t = noise_basis(fscale*p, basis);
+
+ if(hard)
+ t = fabs(2.0*t - 1.0);
+
+ sum += t*amp;
+ amp *= 0.5;
+ fscale *= 2.0;
+ }
+
+ sum *= ((float)(1 << octaves)/(float)((1 << (octaves+1)) - 1));
+
+ return sum;
+}
+
+/* Utility */
+
+float nonzero(float f, float eps)
+{
+ float r;
+
+ if(abs(f) < eps)
+ r = sign(f)*eps;
+ else
+ r = f;
+
+ return r;
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_texture_coordinate.osl b/intern/cycles/kernel/osl/nodes/node_texture_coordinate.osl
new file mode 100644
index 00000000000..2acf72aef54
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_texture_coordinate.osl
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+shader node_texture_coordinate(
+ normal Normal = N,
+ int is_background = 0,
+ string bump_offset = "center",
+
+ output point Generated = point(0.0, 0.0, 0.0),
+ output point UV = point(0.0, 0.0, 0.0),
+ output point Object = point(0.0, 0.0, 0.0),
+ output point Camera = point(0.0, 0.0, 0.0),
+ output point Window = point(0.0, 0.0, 0.0),
+ output point Reflection = point(0.0, 0.0, 0.0))
+{
+ if(is_background) {
+ Generated = P;
+ UV = point(0.0, 0.0, 0.0);
+ Object = P;
+ point Pcam = transform("camera", "world", point(0, 0, 0));
+ Camera = transform("camera", P + Pcam);
+ Window = transform("NDC", P + Pcam);
+ Reflection = I;
+ }
+ else {
+ getattribute("std::generated", Generated);
+ getattribute("std::uv", UV);
+ Object = transform("object", P);
+ Camera = transform("camera", P);
+ Window = transform("NDC", P);
+ Reflection = reflect(I, Normal);
+ }
+
+ if(bump_offset == "dx") {
+ Generated += Dx(Generated);
+ UV += Dx(UV);
+ Object += Dx(Object);
+ Camera += Dx(Camera);
+ Window += Dx(Window);
+ }
+ else if(bump_offset == "dy") {
+ Generated += Dy(Generated);
+ UV += Dy(UV);
+ Object += Dy(Object);
+ Camera += Dy(Camera);
+ Window += Dy(Window);
+ }
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_translucent_bsdf.osl b/intern/cycles/kernel/osl/nodes/node_translucent_bsdf.osl
new file mode 100644
index 00000000000..9acd46756d2
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_translucent_bsdf.osl
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+shader node_translucent_bsdf(
+ color Color = color(0.8, 0.8, 0.8),
+ normal Normal = N,
+ output closure color BSDF = diffuse(Normal))
+{
+ BSDF = Color*translucent(Normal);
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_transparent_bsdf.osl b/intern/cycles/kernel/osl/nodes/node_transparent_bsdf.osl
new file mode 100644
index 00000000000..b347bfb116b
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_transparent_bsdf.osl
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+shader node_transparent_bsdf(
+ color Color = color(0.8, 0.8, 0.8),
+ normal Normal = N,
+ output closure color BSDF = diffuse(Normal))
+{
+ BSDF = Color*transparent();
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_value.osl b/intern/cycles/kernel/osl/nodes/node_value.osl
new file mode 100644
index 00000000000..bee6f39f2bc
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_value.osl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+shader node_value(
+ float value_value = 0.0,
+ vector vector_value = vector(0.0, 0.0, 0.0),
+ color color_value = color(0.0, 0.0, 0.0),
+ output float Value = 0.0,
+ output vector Vector = vector(0.0, 0.0, 0.0),
+ output color Color = color(0.0, 0.0, 0.0))
+{
+ Value = value_value;
+ Vector = vector_value;
+ Color = color_value;
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_vector_math.osl b/intern/cycles/kernel/osl/nodes/node_vector_math.osl
new file mode 100644
index 00000000000..c6231d4350d
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_vector_math.osl
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+shader node_vector_math(
+ string type = "Add",
+ vector Vector1 = vector(0.0, 0.0, 0.0),
+ vector Vector2 = vector(0.0, 0.0, 0.0),
+ output float Fac = 0.0,
+ output vector Vector = vector(0.0, 0.0, 0.0))
+{
+ if(type == "Add") {
+ Vector = Vector1 + Vector2;
+ Fac = (abs(Vector[0]) + abs(Vector[1]) + abs(Vector[2]))/3.0;
+ }
+ if(type == "Subtract") {
+ Vector = Vector1 + Vector2;
+ Fac = (abs(Vector[0]) + abs(Vector[1]) + abs(Vector[2]))/3.0;
+ }
+ if(type == "Average") {
+ Fac = length(Vector1 + Vector2);
+ Vector = normalize(Vector1 + Vector2);
+ }
+ if(type == "Dot Product") {
+ Fac = dot(Vector1, Vector2);
+ }
+ if(type == "Cross Product") {
+ vector c = cross(Vector1, Vector2);
+ Fac = length(c);
+ Vector = normalize(c);
+ }
+ if(type == "Normalize") {
+ Fac = length(Vector1);
+ Vector = normalize(Vector1);
+ }
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_velvet_bsdf.osl b/intern/cycles/kernel/osl/nodes/node_velvet_bsdf.osl
new file mode 100644
index 00000000000..2b6219f6325
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_velvet_bsdf.osl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+#include "node_fresnel.h"
+
+shader node_velvet_bsdf(
+ color Color = color(0.8, 0.8, 0.8),
+ float Sigma = 0.0,
+ float Fresnel = 0.3,
+ normal Normal = N,
+ output closure color BSDF = diffuse(Normal))
+{
+ float Fr = 1.0;
+
+ if(Fresnel < 1.0) {
+ float eta = 1.0/clamp(1.0 - Fresnel, 1e-5, 1.0 - 1e-5);
+ Fr = fresnel_dielectric(I, Normal, eta);
+ }
+
+ float sigma = clamp(Sigma, 0.0, 1.0);
+
+ BSDF = (Fr*Color)*ashikhmin_velvet(Normal, sigma);
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_voronoi_texture.osl b/intern/cycles/kernel/osl/nodes/node_voronoi_texture.osl
new file mode 100644
index 00000000000..140ba6a6ba1
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_voronoi_texture.osl
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+#include "node_texture.h"
+
+/* Voronoi */
+
+shader node_voronoi_texture(
+ string DistanceMetric = "Actual Distance",
+ string Coloring = "Intensity",
+ float Weight1 = 1.0,
+ float Weight2 = 0.0,
+ float Weight3 = 0.0,
+ float Weight4 = 0.0,
+ float Exponent = 2.5,
+ float Intensity = 1.0,
+ float Size = 0.25,
+ point Vector = P,
+ output float Fac = 0.0,
+ output color Color = color(0.0, 0.0, 0.0))
+{
+ float exponent = max(Exponent, 1e-5);
+ float size = nonzero(Size, 1e-5);
+
+ float aw1 = fabs(Weight1);
+ float aw2 = fabs(Weight2);
+ float aw3 = fabs(Weight3);
+ float aw4 = fabs(Weight4);
+ float sc = (aw1 + aw2 + aw3 + aw4);
+
+ if(sc != 0.0)
+ sc = Intensity/sc;
+
+ /* compute distance and point coordinate of 4 nearest neighbours */
+ float da[4];
+ point pa[4];
+
+ voronoi(Vector/size, DistanceMetric, exponent, da, pa);
+
+ /* Scalar output */
+ Fac = sc * fabs(Weight1*da[0] + Weight2*da[1] + Weight3*da[2] + Weight4*da[3]);
+
+ /* Colored output */
+ if(Coloring == "Intensity") {
+ Color = color(Fac, Fac, Fac);
+ }
+ else {
+ Color = aw1*cellnoise_color(pa[0]);
+ Color += aw2*cellnoise_color(pa[1]);
+ Color += aw3*cellnoise_color(pa[2]);
+ Color += aw4*cellnoise_color(pa[3]);
+
+ if(Coloring != "Position") {
+ float t1 = min((da[1] - da[0])*10.0, 1.0);
+
+ if(Coloring == "Position, Outline, and Intensity")
+ Color *= t1*Fac;
+ else if(Coloring == "Position and Outline")
+ Color *= t1*sc;
+ }
+ else {
+ Color *= sc;
+ }
+ }
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_ward_bsdf.osl b/intern/cycles/kernel/osl/nodes/node_ward_bsdf.osl
new file mode 100644
index 00000000000..68db07109ed
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_ward_bsdf.osl
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+shader node_ward_bsdf(
+ color Color = color(0.8, 0.8, 0.8),
+ float RoughnessU = 0.0,
+ float RoughnessV = 0.0,
+ normal Normal = N,
+ output closure color BSDF = diffuse(Normal))
+{
+ BSDF = Color*ward(Normal, normalize(dPdu), RoughnessU, RoughnessV);
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_wood_texture.osl b/intern/cycles/kernel/osl/nodes/node_wood_texture.osl
new file mode 100644
index 00000000000..f1d2e278597
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_wood_texture.osl
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+#include "node_texture.h"
+
+/* Wood */
+
+float wood(point p, float size, string type, string wave, string basis, int hard, float turb)
+{
+ float x = p[0];
+ float y = p[1];
+ float z = p[2];
+
+ float result = 0.0;
+
+ if(type == "Bands") {
+ result = noise_wave(wave, (x + y + z)*10.0);
+ }
+ else if(type == "Rings") {
+ result = noise_wave(wave, sqrt(x*x + y*y + z*z)*20.0);
+ }
+ else if (type == "Band Noise") {
+ float wi = turb*noise_basis_hard(p/size, basis, hard);
+ result = noise_wave(wave, (x + y + z)*10.0 + wi);
+ }
+ else if (type == "Ring Noise") {
+ float wi = turb*noise_basis_hard(p/size, basis, hard);
+ result = noise_wave(wave, sqrt(x*x + y*y + z*z)*20.0 + wi);
+ }
+
+ return result;
+}
+
+shader node_wood_texture(
+ string Type = "Bands",
+ string Wave = "Sine",
+ string Basis = "Perlin",
+ int Hard = 0,
+ float Size = 0.25,
+ float Turbulence = 5.0,
+ point Vector = P,
+ output float Fac = 0.0)
+{
+ float size = nonzero(Size, 1e-5);
+ Fac = wood(Vector, size, Type, Wave, Basis, Hard, Turbulence);
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/stdosl.h b/intern/cycles/kernel/osl/nodes/stdosl.h
new file mode 100644
index 00000000000..6fe4f52df4a
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/stdosl.h
@@ -0,0 +1,471 @@
+/////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of Sony Pictures Imageworks nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef CCL_STDOSL_H
+#define CCL_STDOSL_H
+
+
+#ifndef M_PI
+#define M_PI 3.1415926535897932 /* pi */
+#define M_PI_2 1.5707963267948966 /* pi/2 */
+#define M_PI_4 0.7853981633974483 /* pi/4 */
+#define M_2_PI 0.6366197723675813 /* 2/pi */
+#define M_2_SQRTPI 1.1283791670955126 /* 2/sqrt(pi) */
+#define M_E 2.7182818284590452 /* e (Euler's number) */
+#define M_LN2 0.6931471805599453 /* ln(2) */
+#define M_LN10 2.3025850929940457 /* ln(10) */
+#define M_LOG2E 1.4426950408889634 /* log_2(e) */
+#define M_LOG10E 0.4342944819032518 /* log_10(e) */
+#define M_SQRT2 1.4142135623730950 /* sqrt(2) */
+#define M_SQRT1_2 0.7071067811865475 /* 1/sqrt(2) */
+#endif
+
+
+
+// Declaration of built-in functions and closures
+#define BUILTIN [[ int builtin = 1 ]]
+#define BUILTIN_DERIV [[ int builtin = 1, int deriv = 1 ]]
+
+#define PERCOMP1(name) \
+ normal name (normal x) BUILTIN; \
+ vector name (vector x) BUILTIN; \
+ point name (point x) BUILTIN; \
+ color name (color x) BUILTIN; \
+ float name (float x) BUILTIN;
+
+#define PERCOMP2(name) \
+ normal name (normal x, normal y) BUILTIN; \
+ vector name (vector x, vector y) BUILTIN; \
+ point name (point x, point y) BUILTIN; \
+ color name (color x, color y) BUILTIN; \
+ float name (float x, float y) BUILTIN;
+
+#define PERCOMP2F(name) \
+ normal name (normal x, float y) BUILTIN; \
+ vector name (vector x, float y) BUILTIN; \
+ point name (point x, float y) BUILTIN; \
+ color name (color x, float y) BUILTIN; \
+ float name (float x, float y) BUILTIN;
+
+
+// Basic math
+normal degrees (normal x) { return x*(180.0/M_PI); }
+vector degrees (vector x) { return x*(180.0/M_PI); }
+point degrees (point x) { return x*(180.0/M_PI); }
+color degrees (color x) { return x*(180.0/M_PI); }
+float degrees (float x) { return x*(180.0/M_PI); }
+normal radians (normal x) { return x*(M_PI/180.0); }
+vector radians (vector x) { return x*(M_PI/180.0); }
+point radians (point x) { return x*(M_PI/180.0); }
+color radians (color x) { return x*(M_PI/180.0); }
+float radians (float x) { return x*(M_PI/180.0); }
+PERCOMP1 (cos)
+PERCOMP1 (sin)
+PERCOMP1 (tan)
+PERCOMP1 (acos)
+PERCOMP1 (asin)
+PERCOMP1 (atan)
+PERCOMP2 (atan2)
+PERCOMP1 (cosh)
+PERCOMP1 (sinh)
+PERCOMP1 (tanh)
+PERCOMP2F (pow)
+PERCOMP1 (exp)
+PERCOMP1 (exp2)
+PERCOMP1 (expm1)
+PERCOMP1 (log)
+point log (point a, float b) { return log(a)/log(b); }
+vector log (vector a, float b) { return log(a)/log(b); }
+color log (color a, float b) { return log(a)/log(b); }
+float log (float a, float b) { return log(a)/log(b); }
+PERCOMP1 (log2)
+PERCOMP1 (log10)
+PERCOMP1 (logb)
+PERCOMP1 (sqrt)
+PERCOMP1 (inversesqrt)
+float hypot (float a, float b) { return sqrt (a*a + b*b); }
+float hypot (float a, float b, float c) { return sqrt (a*a + b*b + c*c); }
+PERCOMP1 (abs)
+int abs (int x) BUILTIN;
+PERCOMP1 (fabs)
+int fabs (int x) BUILTIN;
+PERCOMP1 (sign)
+PERCOMP1 (floor)
+PERCOMP1 (ceil)
+PERCOMP1 (round)
+PERCOMP1 (trunc)
+PERCOMP2 (fmod)
+PERCOMP2F (fmod)
+PERCOMP2 (mod)
+PERCOMP2F (mod)
+int mod (int x, int y) BUILTIN;
+PERCOMP2 (min)
+PERCOMP2 (max)
+normal clamp (normal x, normal minval, normal maxval) { return max(min(x,maxval),minval); }
+vector clamp (vector x, vector minval, vector maxval) { return max(min(x,maxval),minval); }
+point clamp (point x, point minval, point maxval) { return max(min(x,maxval),minval); }
+color clamp (color x, color minval, color maxval) { return max(min(x,maxval),minval); }
+float clamp (float x, float minval, float maxval) { return max(min(x,maxval),minval); }
+//normal clamp (normal x, normal minval, normal maxval) BUILTIN;
+//vector clamp (vector x, vector minval, vector maxval) BUILTIN;
+//point clamp (point x, point minval, point maxval) BUILTIN;
+//color clamp (color x, color minval, color maxval) BUILTIN;
+//float clamp (float x, float minval, float maxval) BUILTIN;
+normal mix (normal x, normal y, normal a) { return x*(1-a) + y*a; }
+normal mix (normal x, normal y, float a) { return x*(1-a) + y*a; }
+vector mix (vector x, vector y, vector a) { return x*(1-a) + y*a; }
+vector mix (vector x, vector y, float a) { return x*(1-a) + y*a; }
+point mix (point x, point y, point a) { return x*(1-a) + y*a; }
+point mix (point x, point y, float a) { return x*(1-a) + y*a; }
+color mix (color x, color y, color a) { return x*(1-a) + y*a; }
+color mix (color x, color y, float a) { return x*(1-a) + y*a; }
+float mix (float x, float y, float a) { return x*(1-a) + y*a; }
+int isnan (float x) BUILTIN;
+int isinf (float x) BUILTIN;
+int isfinite (float x) BUILTIN;
+float erf (float x) BUILTIN;
+float erfc (float x) BUILTIN;
+
+// Vector functions
+
+vector cross (vector a, vector b) BUILTIN;
+float dot (vector a, vector b) BUILTIN;
+float length (vector v) BUILTIN;
+float distance (point a, point b) BUILTIN;
+float distance (point a, point b, point q) BUILTIN;
+normal normalize (normal v) BUILTIN;
+vector normalize (vector v) BUILTIN;
+vector faceforward (vector N, vector I, vector Nref) BUILTIN;
+vector faceforward (vector N, vector I) BUILTIN;
+vector reflect (vector I, vector N) { return I - 2*dot(N,I)*N; }
+vector refract (vector I, vector N, float eta) {
+ float IdotN = dot (I, N);
+ float k = 1 - eta*eta * (1 - IdotN*IdotN);
+ return (k < 0) ? vector(0,0,0) : (eta*I - N * (eta*IdotN + sqrt(k)));
+}
+void fresnel (vector I, normal N, float eta,
+ output float Kr, output float Kt,
+ output vector R, output vector T)
+{
+ float sqr(float x) { return x*x; }
+ float c = dot(I, N);
+ if (c < 0)
+ c = -c;
+ R = reflect(I, N);
+ float g = 1.0 / sqr(eta) - 1.0 + c * c;
+ if (g >= 0.0) {
+ g = sqrt (g);
+ float beta = g - c;
+ float F = (c * (g+c) - 1.0) / (c * beta + 1.0);
+ F = 0.5 * (1.0 + sqr(F));
+ F *= sqr (beta / (g+c));
+ Kr = F;
+ Kt = (1.0 - Kr) * eta*eta;
+ // OPT: the following recomputes some of the above values, but it
+ // gives us the same result as if the shader-writer called refract()
+ T = refract(I, N, eta);
+ } else {
+ // total internal reflection
+ Kr = 1.0;
+ Kt = 0.0;
+ T = vector (0,0,0);
+ }
+#undef sqr
+}
+
+void fresnel (vector I, normal N, float eta,
+ output float Kr, output float Kt)
+{
+ vector R, T;
+ fresnel(I, N, eta, Kr, Kt, R, T);
+}
+
+point rotate (point q, float angle, point a, point b) BUILTIN;
+
+normal transform (matrix Mto, normal p) BUILTIN;
+vector transform (matrix Mto, vector p) BUILTIN;
+point transform (matrix Mto, point p) BUILTIN;
+
+// Implementation of transform-with-named-space in terms of matrices:
+
+point transform (string tospace, point x)
+{
+ return transform (matrix ("common", tospace), x);
+}
+
+point transform (string fromspace, string tospace, point x)
+{
+ return transform (matrix (fromspace, tospace), x);
+}
+
+
+vector transform (string tospace, vector x)
+{
+ return transform (matrix ("common", tospace), x);
+}
+
+vector transform (string fromspace, string tospace, vector x)
+{
+ return transform (matrix (fromspace, tospace), x);
+}
+
+
+normal transform (string tospace, normal x)
+{
+ return transform (matrix ("common", tospace), x);
+}
+
+normal transform (string fromspace, string tospace, normal x)
+{
+ return transform (matrix (fromspace, tospace), x);
+}
+
+float transformu (string tounits, float x) BUILTIN;
+float transformu (string fromunits, string tounits, float x) BUILTIN;
+
+
+// Color functions
+
+float luminance (color c) {
+ return dot ((vector)c, vector(0.2126, 0.7152, 0.0722));
+}
+
+
+
+color transformc (string to, color x)
+{
+ color rgb_to_hsv (color rgb) { // See Foley & van Dam
+ float r = rgb[0], g = rgb[1], b = rgb[2];
+ float mincomp = min (r, min (g, b));
+ float maxcomp = max (r, max (g, b));
+ float delta = maxcomp - mincomp; // chroma
+ float h, s, v;
+ v = maxcomp;
+ if (maxcomp > 0)
+ s = delta / maxcomp;
+ else s = 0;
+ if (s <= 0)
+ h = 0;
+ else {
+ if (r >= maxcomp) h = (g-b) / delta;
+ else if (g >= maxcomp) h = 2 + (b-r) / delta;
+ else h = 4 + (r-g) / delta;
+ h /= 6;
+ if (h < 0)
+ h += 1;
+ }
+ return color (h, s, v);
+ }
+
+ color rgb_to_hsl (color rgb) { // See Foley & van Dam
+ // First convert rgb to hsv, then to hsl
+ float minval = min (rgb[0], min (rgb[1], rgb[2]));
+ color hsv = rgb_to_hsv (rgb);
+ float maxval = hsv[2]; // v == maxval
+ float h = hsv[0], s, l = (minval+maxval) / 2;
+ if (minval == maxval)
+ s = 0; // special 'achromatic' case, hue is 0
+ else if (l <= 0.5)
+ s = (maxval - minval) / (maxval + minval);
+ else
+ s = (maxval - minval) / (2 - maxval - minval);
+ return color (h, s, l);
+ }
+
+ color r;
+ if (to == "rgb" || to == "RGB")
+ r = x;
+ else if (to == "hsv")
+ r = rgb_to_hsv (x);
+ else if (to == "hsl")
+ r = rgb_to_hsl (x);
+ else if (to == "YIQ")
+ r = color (dot (vector(0.299, 0.587, 0.114), (vector)x),
+ dot (vector(0.596, -0.275, -0.321), (vector)x),
+ dot (vector(0.212, -0.523, 0.311), (vector)x));
+ else if (to == "xyz")
+ r = color (dot (vector(0.412453, 0.357580, 0.180423), (vector)x),
+ dot (vector(0.212671, 0.715160, 0.072169), (vector)x),
+ dot (vector(0.019334, 0.119193, 0.950227), (vector)x));
+ else {
+ error ("Unknown color space \"%s\"", to);
+ r = x;
+ }
+ return r;
+}
+
+
+color transformc (string from, string to, color x)
+{
+ color hsv_to_rgb (color c) { // Reference: Foley & van Dam
+ float h = c[0], s = c[1], v = c[2];
+ color r;
+ if (s < 0.0001) {
+ r = v;
+ } else {
+ h = 6 * (h - floor(h)); // expand to [0..6)
+ int hi = (int)h;
+ float f = h - hi;
+ float p = v * (1-s);
+ float q = v * (1-s*f);
+ float t = v * (1-s*(1-f));
+ if (hi == 0) r = color (v, t, p);
+ else if (hi == 1) r = color (q, v, p);
+ else if (hi == 2) r = color (p, v, t);
+ else if (hi == 3) r = color (p, q, v);
+ else if (hi == 4) r = color (t, p, v);
+ else r = color (v, p, q);
+ }
+ return r;
+ }
+
+ color hsl_to_rgb (color c) {
+ float h = c[0], s = c[1], l = c[2];
+ // Easiest to convert hsl -> hsv, then hsv -> RGB (per Foley & van Dam)
+ float v = (l <= 0.5) ? (l * (1 + s)) : (l * (1 - s) + s);
+ color r;
+ if (v <= 0) {
+ r = 0;
+ } else {
+ float min = 2 * l - v;
+ s = (v - min) / v;
+ r = hsv_to_rgb (color (h, s, v));
+ }
+ return r;
+ }
+
+ color r;
+ if (from == "rgb" || from == "RGB")
+ r = x;
+ else if (from == "hsv")
+ r = hsv_to_rgb (x);
+ else if (from == "hsl")
+ r = hsl_to_rgb (x);
+ else if (from == "YIQ")
+ r = color (dot (vector(1, 0.9557, 0.6199), (vector)x),
+ dot (vector(1, -0.2716, -0.6469), (vector)x),
+ dot (vector(1, -1.1082, 1.7051), (vector)x));
+ else if (from == "xyz")
+ r = color (dot (vector( 3.240479, -1.537150, -0.498535), (vector)x),
+ dot (vector(-0.969256, 1.875991, 0.041556), (vector)x),
+ dot (vector( 0.055648, -0.204043, 1.057311), (vector)x));
+ else {
+ error ("Unknown color space \"%s\"", to);
+ r = x;
+ }
+ return transformc (to, r);
+}
+
+
+
+// Matrix functions
+
+float determinant (matrix m) BUILTIN;
+matrix transpose (matrix m) BUILTIN;
+
+
+
+// Pattern generation
+
+float step (float edge, float x) BUILTIN;
+color step (color edge, color x) BUILTIN;
+point step (point edge, point x) BUILTIN;
+vector step (vector edge, vector x) BUILTIN;
+normal step (normal edge, normal x) BUILTIN;
+float smoothstep (float edge0, float edge1, float x) BUILTIN;
+
+
+// Derivatives and area operators
+
+
+// Displacement functions
+
+
+// String functions
+
+int strlen (string s) BUILTIN;
+int startswith (string s, string prefix) BUILTIN;
+int endswith (string s, string suffix) BUILTIN;
+string substr (string s, int start, int len) BUILTIN;
+string substr (string s, int start) { return substr (s, start, strlen(s)); }
+
+// Define concat in terms of shorter concat
+string concat (string a, string b, string c) {
+ return concat(concat(a,b), c);
+}
+string concat (string a, string b, string c, string d) {
+ return concat(concat(a,b,c), d);
+}
+string concat (string a, string b, string c, string d, string e) {
+ return concat(concat(a,b,c,d), e);
+}
+string concat (string a, string b, string c, string d, string e, string f) {
+ return concat(concat(a,b,c,d,e), f);
+}
+
+
+// Texture
+
+
+// Closures
+
+closure color diffuse(normal N) BUILTIN;
+closure color translucent(normal N) BUILTIN;
+closure color reflection(normal N, float eta) BUILTIN;
+closure color reflection(normal N) { return reflection (N, 0.0); }
+closure color refraction(normal N, float eta) BUILTIN;
+closure color dielectric(normal N, float eta) BUILTIN;
+closure color transparent() BUILTIN;
+closure color microfacet_ggx(normal N, float ag) BUILTIN;
+closure color microfacet_ggx_refraction(normal N, float ag, float eta) BUILTIN;
+closure color microfacet_beckmann(normal N, float ab) BUILTIN;
+closure color microfacet_beckmann_refraction(normal N, float ab, float eta) BUILTIN;
+closure color ward(normal N, vector T,float ax, float ay) BUILTIN;
+closure color ashikhmin_velvet(normal N, float sigma) BUILTIN;
+closure color westin_backscatter(normal N, float roughness) BUILTIN;
+closure color westin_sheen(normal N, float edginess) BUILTIN;
+closure color bssrdf_cubic(color radius) BUILTIN;
+closure color emission(float inner_angle, float outer_angle) BUILTIN;
+closure color emission(float outer_angle) BUILTIN;
+closure color emission() BUILTIN;
+closure color debug(string tag) BUILTIN;
+closure color background() BUILTIN;
+closure color holdout() BUILTIN;
+closure color subsurface(float eta, float g, float mfp, float albedo) BUILTIN;
+
+// Renderer state
+int raytype (string typename) BUILTIN;
+
+#undef BUILTIN
+#undef BUILTIN_DERIV
+#undef PERCOMP1
+#undef PERCOMP2
+#undef PERCOMP2F
+
+#endif /* CCL_STDOSL_H */
+
diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp
new file mode 100644
index 00000000000..4c2261942fd
--- /dev/null
+++ b/intern/cycles/kernel/osl/osl_closures.cpp
@@ -0,0 +1,93 @@
+/*
+ * Adapted from Open Shading Language with this license:
+ *
+ * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., closure_et al.
+ * All Rights Reserved.
+ *
+ * Modifications Copyright 2011, Blender Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Sony Pictures Imageworks nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <OSL/genclosure.h>
+#include <OSL/oslclosure.h>
+
+#include "osl_closures.h"
+#include "osl_shader.h"
+
+#include "util_debug.h"
+#include "util_param.h"
+
+CCL_NAMESPACE_BEGIN
+
+static void generic_closure_setup(OSL::RendererServices *, int id, void *data)
+{
+ assert(data);
+ OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)data;
+ prim->setup();
+}
+
+static bool generic_closure_mergeable(int id, const void *dataA, const void *dataB)
+{
+ assert(dataA && dataB);
+
+ OSL::ClosurePrimitive *primA = (OSL::ClosurePrimitive *)dataA;
+ OSL::ClosurePrimitive *primB = (OSL::ClosurePrimitive *)dataB;
+ return primA->mergeable(primB);
+}
+
+static void register_closure(OSL::ShadingSystem *ss, const char *name, int id, OSL::ClosureParam *params, OSL::PrepareClosureFunc prepare)
+{
+ int j;
+ for(j = 0; params[j].type != TypeDesc(); ++j) {}
+ int size = params[j].offset;
+
+ ss->register_closure(name, id, params, size, prepare, generic_closure_setup, generic_closure_mergeable);
+}
+
+void OSLShader::register_closures(OSL::ShadingSystem *ss)
+{
+ register_closure(ss, "diffuse", OSL_CLOSURE_BSDF_DIFFUSE_ID, bsdf_diffuse_params, bsdf_diffuse_prepare);
+ register_closure(ss, "translucent", OSL_CLOSURE_BSDF_TRANSLUCENT_ID, bsdf_translucent_params, bsdf_translucent_prepare);
+ register_closure(ss, "reflection", OSL_CLOSURE_BSDF_REFLECTION_ID, bsdf_reflection_params, bsdf_reflection_prepare);
+ register_closure(ss, "refraction", OSL_CLOSURE_BSDF_REFRACTION_ID, bsdf_refraction_params, bsdf_refraction_prepare);
+ register_closure(ss, "transparent", OSL_CLOSURE_BSDF_TRANSPARENT_ID, bsdf_transparent_params, bsdf_transparent_prepare);
+ register_closure(ss, "microfacet_ggx", OSL_CLOSURE_BSDF_MICROFACET_GGX_ID, bsdf_microfacet_ggx_params, bsdf_microfacet_ggx_prepare);
+ register_closure(ss, "microfacet_ggx_refraction", OSL_CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID, bsdf_microfacet_ggx_refraction_params, bsdf_microfacet_ggx_refraction_prepare);
+ register_closure(ss, "microfacet_beckmann", OSL_CLOSURE_BSDF_MICROFACET_BECKMANN_ID, bsdf_microfacet_beckmann_params, bsdf_microfacet_beckmann_prepare);
+ register_closure(ss, "microfacet_beckmann_refraction", OSL_CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID, bsdf_microfacet_beckmann_refraction_params, bsdf_microfacet_beckmann_refraction_prepare);
+ register_closure(ss, "ward", OSL_CLOSURE_BSDF_WARD_ID, bsdf_ward_params, bsdf_ward_prepare);
+ register_closure(ss, "ashikhmin_velvet", OSL_CLOSURE_BSDF_ASHIKHMIN_VELVET_ID, bsdf_ashikhmin_velvet_params, bsdf_ashikhmin_velvet_prepare);
+ register_closure(ss, "westin_backscatter", OSL_CLOSURE_BSDF_WESTIN_BACKSCATTER_ID, bsdf_westin_backscatter_params, bsdf_westin_backscatter_prepare);
+ register_closure(ss, "westin_sheen", OSL_CLOSURE_BSDF_WESTIN_SHEEN_ID, bsdf_westin_sheen_params, bsdf_westin_sheen_prepare);
+ register_closure(ss, "bssrdf_cubic", OSL_CLOSURE_BSSRDF_CUBIC_ID, closure_bssrdf_cubic_params, closure_bssrdf_cubic_prepare);
+ register_closure(ss, "emission", OSL_CLOSURE_EMISSION_ID, closure_emission_params, closure_emission_prepare);
+ register_closure(ss, "debug", OSL_CLOSURE_DEBUG_ID, closure_debug_params, closure_debug_prepare);
+ register_closure(ss, "background", OSL_CLOSURE_BACKGROUND_ID, closure_background_params, closure_background_prepare);
+ register_closure(ss, "holdout", OSL_CLOSURE_HOLDOUT_ID, closure_holdout_params, closure_holdout_prepare);
+ register_closure(ss, "subsurface", OSL_CLOSURE_SUBSURFACE_ID, closure_subsurface_params, closure_subsurface_prepare);
+}
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h
new file mode 100644
index 00000000000..20a759586b0
--- /dev/null
+++ b/intern/cycles/kernel/osl/osl_closures.h
@@ -0,0 +1,114 @@
+/*
+ * Adapted from Open Shading Language with this license:
+ *
+ * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
+ * All Rights Reserved.
+ *
+ * Modifications Copyright 2011, Blender Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Sony Pictures Imageworks nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __OSL_CLOSURES_H__
+#define __OSL_CLOSURES_H__
+
+#include <OSL/oslclosure.h>
+#include <OSL/oslexec.h>
+#include <OSL/genclosure.h>
+
+CCL_NAMESPACE_BEGIN
+
+enum {
+ OSL_CLOSURE_BSDF_DIFFUSE_ID,
+ OSL_CLOSURE_BSDF_TRANSLUCENT_ID,
+ OSL_CLOSURE_BSDF_REFLECTION_ID,
+ OSL_CLOSURE_BSDF_REFRACTION_ID,
+ OSL_CLOSURE_BSDF_TRANSPARENT_ID,
+ OSL_CLOSURE_BSDF_MICROFACET_GGX_ID,
+ OSL_CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID,
+ OSL_CLOSURE_BSDF_MICROFACET_BECKMANN_ID,
+ OSL_CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID,
+ OSL_CLOSURE_BSDF_WARD_ID,
+ OSL_CLOSURE_BSDF_ASHIKHMIN_VELVET_ID,
+ OSL_CLOSURE_BSDF_WESTIN_BACKSCATTER_ID,
+ OSL_CLOSURE_BSDF_WESTIN_SHEEN_ID,
+ OSL_CLOSURE_BSSRDF_CUBIC_ID,
+ OSL_CLOSURE_EMISSION_ID,
+ OSL_CLOSURE_DEBUG_ID,
+ OSL_CLOSURE_BACKGROUND_ID,
+ OSL_CLOSURE_HOLDOUT_ID,
+ OSL_CLOSURE_SUBSURFACE_ID
+};
+
+extern OSL::ClosureParam bsdf_diffuse_params[];
+extern OSL::ClosureParam bsdf_translucent_params[];
+extern OSL::ClosureParam bsdf_reflection_params[];
+extern OSL::ClosureParam bsdf_refraction_params[];
+extern OSL::ClosureParam bsdf_transparent_params[];
+extern OSL::ClosureParam bsdf_microfacet_ggx_params[];
+extern OSL::ClosureParam bsdf_microfacet_ggx_refraction_params[];
+extern OSL::ClosureParam bsdf_microfacet_beckmann_params[];
+extern OSL::ClosureParam bsdf_microfacet_beckmann_refraction_params[];
+extern OSL::ClosureParam bsdf_ward_params[];
+extern OSL::ClosureParam bsdf_ashikhmin_velvet_params[];
+extern OSL::ClosureParam bsdf_westin_backscatter_params[];
+extern OSL::ClosureParam bsdf_westin_sheen_params[];
+extern OSL::ClosureParam closure_bssrdf_cubic_params[];
+extern OSL::ClosureParam closure_emission_params[];
+extern OSL::ClosureParam closure_debug_params[];
+extern OSL::ClosureParam closure_background_params[];
+extern OSL::ClosureParam closure_holdout_params[];
+extern OSL::ClosureParam closure_subsurface_params[];
+
+void bsdf_diffuse_prepare(OSL::RendererServices *, int id, void *data);
+void bsdf_translucent_prepare(OSL::RendererServices *, int id, void *data);
+void bsdf_reflection_prepare(OSL::RendererServices *, int id, void *data);
+void bsdf_refraction_prepare(OSL::RendererServices *, int id, void *data);
+void bsdf_transparent_prepare(OSL::RendererServices *, int id, void *data);
+void bsdf_microfacet_ggx_prepare(OSL::RendererServices *, int id, void *data);
+void bsdf_microfacet_ggx_refraction_prepare(OSL::RendererServices *, int id, void *data);
+void bsdf_microfacet_beckmann_prepare(OSL::RendererServices *, int id, void *data);
+void bsdf_microfacet_beckmann_refraction_prepare(OSL::RendererServices *, int id, void *data);
+void bsdf_ward_prepare(OSL::RendererServices *, int id, void *data);
+void bsdf_ashikhmin_velvet_prepare(OSL::RendererServices *, int id, void *data);
+void bsdf_westin_backscatter_prepare(OSL::RendererServices *, int id, void *data);
+void bsdf_westin_sheen_prepare(OSL::RendererServices *, int id, void *data);
+void closure_bssrdf_cubic_prepare(OSL::RendererServices *, int id, void *data);
+void closure_emission_prepare(OSL::RendererServices *, int id, void *data);
+void closure_debug_prepare(OSL::RendererServices *, int id, void *data);
+void closure_background_prepare(OSL::RendererServices *, int id, void *data);
+void closure_holdout_prepare(OSL::RendererServices *, int id, void *data);
+void closure_subsurface_prepare(OSL::RendererServices *, int id, void *data);
+
+#define CLOSURE_PREPARE(name, classname) \
+void name(RendererServices *, int id, void *data) \
+{ \
+ memset(data, 0, sizeof(classname)); \
+ new (data) classname(); \
+}
+
+CCL_NAMESPACE_END
+
+#endif /* __OSL_CLOSURES_H__ */
+
diff --git a/intern/cycles/kernel/osl/osl_globals.h b/intern/cycles/kernel/osl/osl_globals.h
new file mode 100644
index 00000000000..90746c385c7
--- /dev/null
+++ b/intern/cycles/kernel/osl/osl_globals.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __OSL_GLOBALS_H__
+#define __OSL_GLOBALS_H__
+
+#ifdef WITH_OSL
+
+#include <OSL/oslexec.h>
+
+#include "util_map.h"
+#include "util_param.h"
+#include "util_thread.h"
+#include "util_vector.h"
+
+CCL_NAMESPACE_BEGIN
+
+struct OSLGlobals {
+ /* use */
+ bool use;
+
+ /* shading system */
+ OSL::ShadingSystem *ss;
+
+ /* shader states */
+ vector<OSL::ShadingAttribStateRef> surface_state;
+ vector<OSL::ShadingAttribStateRef> volume_state;
+ vector<OSL::ShadingAttribStateRef> displacement_state;
+ OSL::ShadingAttribStateRef background_state;
+
+ /* attributes */
+ struct Attribute {
+ TypeDesc type;
+ AttributeElement elem;
+ int offset;
+ ParamValue value;
+ };
+
+ typedef unordered_map<ustring, Attribute, ustringHash> AttributeMap;
+ typedef unordered_map<ustring, int, ustringHash> ObjectNameMap;
+
+ vector<AttributeMap> attribute_map;
+ ObjectNameMap object_name_map;
+
+ /* thread key for thread specific data lookup */
+ struct ThreadData {
+ OSL::ShaderGlobals globals;
+ void *thread_info;
+ };
+
+ static tls_ptr(ThreadData, thread_data);
+};
+
+CCL_NAMESPACE_END
+
+#endif
+
+#endif /* __OSL_GLOBALS_H__ */
+
diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp
new file mode 100644
index 00000000000..ded3a68d667
--- /dev/null
+++ b/intern/cycles/kernel/osl/osl_services.cpp
@@ -0,0 +1,424 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <string.h>
+
+#include "mesh.h"
+#include "object.h"
+#include "scene.h"
+
+#include "osl_services.h"
+#include "osl_shader.h"
+
+#include "util_foreach.h"
+#include "util_string.h"
+
+#include "kernel_compat_cpu.h"
+#include "kernel_globals.h"
+#include "kernel_object.h"
+#include "kernel_triangle.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* RenderServices implementation */
+
+#define TO_MATRIX44(m) (*(OSL::Matrix44*)&(m))
+
+/* static ustrings */
+ustring OSLRenderServices::u_distance("distance");
+ustring OSLRenderServices::u_index("index");
+ustring OSLRenderServices::u_camera("camera");
+ustring OSLRenderServices::u_screen("screen");
+ustring OSLRenderServices::u_raster("raster");
+ustring OSLRenderServices::u_ndc("NDC");
+ustring OSLRenderServices::u_empty;
+
+OSLRenderServices::OSLRenderServices()
+{
+ kernel_globals = NULL;
+}
+
+OSLRenderServices::~OSLRenderServices()
+{
+}
+
+void OSLRenderServices::thread_init(KernelGlobals *kernel_globals_)
+{
+ kernel_globals = kernel_globals_;
+}
+
+bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform, float time)
+{
+ /* this is only used for shader and object space, we don't really have
+ a concept of shader space, so we just use object space for both. */
+ if(xform) {
+ KernelGlobals *kg = kernel_globals;
+ const ShaderData *sd = (const ShaderData*)xform;
+ int object = sd->object;
+
+ if(object != ~0) {
+ Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
+ tfm = transform_transpose(tfm);
+ result = TO_MATRIX44(tfm);
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform, float time)
+{
+ /* this is only used for shader and object space, we don't really have
+ a concept of shader space, so we just use object space for both. */
+ if(xform) {
+ KernelGlobals *kg = kernel_globals;
+ const ShaderData *sd = (const ShaderData*)xform;
+ int object = sd->object;
+
+ if(object != ~0) {
+ Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
+ tfm = transform_transpose(tfm);
+ result = TO_MATRIX44(tfm);
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, ustring from, float time)
+{
+ KernelGlobals *kg = kernel_globals;
+
+ if(from == u_ndc) {
+ Transform tfm = transform_transpose(kernel_data.cam.ndctoworld);
+ result = TO_MATRIX44(tfm);
+ return true;
+ }
+ else if(from == u_raster) {
+ Transform tfm = transform_transpose(kernel_data.cam.rastertoworld);
+ result = TO_MATRIX44(tfm);
+ return true;
+ }
+ else if(from == u_screen) {
+ Transform tfm = transform_transpose(kernel_data.cam.screentoworld);
+ result = TO_MATRIX44(tfm);
+ return true;
+ }
+ else if(from == u_camera) {
+ Transform tfm = transform_transpose(kernel_data.cam.cameratoworld);
+ result = TO_MATRIX44(tfm);
+ return true;
+ }
+
+ return false;
+}
+
+bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, ustring to, float time)
+{
+ KernelGlobals *kg = kernel_globals;
+
+ if(to == u_ndc) {
+ Transform tfm = transform_transpose(kernel_data.cam.worldtondc);
+ result = TO_MATRIX44(tfm);
+ return true;
+ }
+ else if(to == u_raster) {
+ Transform tfm = transform_transpose(kernel_data.cam.worldtoraster);
+ result = TO_MATRIX44(tfm);
+ return true;
+ }
+ else if(to == u_screen) {
+ Transform tfm = transform_transpose(kernel_data.cam.worldtoscreen);
+ result = TO_MATRIX44(tfm);
+ return true;
+ }
+ else if(to == u_camera) {
+ Transform tfm = transform_transpose(kernel_data.cam.worldtocamera);
+ result = TO_MATRIX44(tfm);
+ return true;
+ }
+
+ return false;
+}
+
+bool OSLRenderServices::get_array_attribute(void *renderstate, bool derivatives,
+ ustring object, TypeDesc type, ustring name,
+ int index, void *val)
+{
+ return false;
+}
+
+static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd,
+ const OSLGlobals::Attribute& attr, bool derivatives, void *val)
+{
+ if(attr.type == TypeDesc::TypeFloat) {
+ float *fval = (float*)val;
+ fval[0] = triangle_attribute_float(kg, sd, attr.elem, attr.offset,
+ (derivatives)? &fval[1]: NULL, (derivatives)? &fval[2]: NULL);
+ }
+ else {
+ float3 *fval = (float3*)val;
+ fval[0] = triangle_attribute_float3(kg, sd, attr.elem, attr.offset,
+ (derivatives)? &fval[1]: NULL, (derivatives)? &fval[2]: NULL);
+ }
+
+ return true;
+}
+
+static bool get_mesh_attribute_convert(KernelGlobals *kg, const ShaderData *sd,
+ const OSLGlobals::Attribute& attr, const TypeDesc& type, bool derivatives, void *val)
+{
+ if(attr.type == TypeDesc::TypeFloat) {
+ float tmp[3];
+ float3 *fval = (float3*)val;
+
+ get_mesh_attribute(kg, sd, attr, derivatives, tmp);
+
+ fval[0] = make_float3(tmp[0], tmp[0], tmp[0]);
+ if(derivatives) {
+ fval[1] = make_float3(tmp[1], tmp[1], tmp[1]);
+ fval[2] = make_float3(tmp[2], tmp[2], tmp[2]);
+ }
+
+ return true;
+ }
+ else if(attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector ||
+ attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) {
+ float3 tmp[3];
+ float *fval = (float*)val;
+
+ get_mesh_attribute(kg, sd, attr, derivatives, tmp);
+
+ fval[0] = average(tmp[0]);
+ if(derivatives) {
+ fval[1] = average(tmp[1]);
+ fval[2] = average(tmp[2]);
+ }
+
+ return true;
+ }
+ else
+ return false;
+}
+
+static void get_object_attribute(const OSLGlobals::Attribute& attr, bool derivatives, void *val)
+{
+ size_t datasize = attr.value.datasize();
+
+ memcpy(val, attr.value.data(), datasize);
+ if(derivatives)
+ memset((char*)val + datasize, 0, datasize*2);
+}
+
+bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustring object_name,
+ TypeDesc type, ustring name, void *val)
+{
+ KernelGlobals *kg = kernel_globals;
+ const ShaderData *sd = (const ShaderData*)renderstate;
+ int object = sd->object;
+ int tri = sd->prim;
+
+ /* lookup of attribute on another object */
+ if(object_name != u_empty) {
+ OSLGlobals::ObjectNameMap::iterator it = kg->osl.object_name_map.find(object_name);
+
+ if(it == kg->osl.object_name_map.end())
+ return false;
+
+ object = it->second;
+ tri = ~0;
+ }
+ else if(object == ~0) {
+ /* no background attributes supported */
+ return false;
+ }
+
+ /* find attribute on object */
+ OSLGlobals::AttributeMap& attribute_map = kg->osl.attribute_map[object];
+ OSLGlobals::AttributeMap::iterator it = attribute_map.find(name);
+
+ if(it == attribute_map.end())
+ return false;
+
+ /* type mistmatch? */
+ const OSLGlobals::Attribute& attr = it->second;
+
+ if(attr.elem != ATTR_ELEMENT_VALUE) {
+ /* triangle and vertex attributes */
+ if(tri != ~0) {
+ if(attr.type == type || (attr.type == TypeDesc::TypeColor &&
+ (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || type == TypeDesc::TypeNormal)))
+ return get_mesh_attribute(kg, sd, attr, derivatives, val);
+ else
+ return get_mesh_attribute_convert(kg, sd, attr, type, derivatives, val);
+ }
+ }
+ else {
+ /* object attribute */
+ get_object_attribute(attr, derivatives, val);
+ return true;
+ }
+
+ return false;
+}
+
+bool OSLRenderServices::get_userdata(bool derivatives, ustring name, TypeDesc type,
+ void *renderstate, void *val)
+{
+ return false; /* disabled by lockgeom */
+}
+
+bool OSLRenderServices::has_userdata(ustring name, TypeDesc type, void *renderstate)
+{
+ return false; /* never called by OSL */
+}
+
+void *OSLRenderServices::get_pointcloud_attr_query(ustring *attr_names,
+ TypeDesc *attr_types, int nattrs)
+{
+#ifdef WITH_PARTIO
+ m_attr_queries.push_back(AttrQuery());
+ AttrQuery &query = m_attr_queries.back();
+
+ /* make space for what we need. the only reason to use
+ std::vector is to skip the delete */
+ query.attr_names.resize(nattrs);
+ query.attr_partio_types.resize(nattrs);
+ /* capacity will keep the length of the smallest array passed
+ to the query. Just to prevent buffer overruns */
+ query.capacity = -1;
+
+ for(int i = 0; i < nattrs; ++i)
+ {
+ query.attr_names[i] = attr_names[i];
+
+ TypeDesc element_type = attr_types[i].elementtype ();
+
+ if(query.capacity < 0)
+ query.capacity = attr_types[i].numelements();
+ else
+ query.capacity = min(query.capacity, (int)attr_types[i].numelements());
+
+ /* convert the OSL (OIIO) type to the equivalent Partio type so
+ we can do a fast check at query time. */
+ if(element_type == TypeDesc::TypeFloat)
+ query.attr_partio_types[i] = Partio::FLOAT;
+ else if(element_type == TypeDesc::TypeInt)
+ query.attr_partio_types[i] = Partio::INT;
+ else if(element_type == TypeDesc::TypeColor || element_type == TypeDesc::TypePoint ||
+ element_type == TypeDesc::TypeVector || element_type == TypeDesc::TypeNormal)
+ query.attr_partio_types[i] = Partio::VECTOR;
+ else
+ return NULL; /* report some error of unknown type */
+ }
+
+ /* this is valid until the end of RenderServices */
+ return &query;
+#else
+ return NULL;
+#endif
+}
+
+#ifdef WITH_PARTIO
+Partio::ParticlesData *OSLRenderServices::get_pointcloud(ustring filename)
+{
+ return Partio::readCached(filename.c_str(), true);
+}
+
+#endif
+
+int OSLRenderServices::pointcloud(ustring filename, const OSL::Vec3 &center, float radius,
+ int max_points, void *_attr_query, void **attr_outdata)
+{
+ /* todo: this code has never been tested, and most likely does not
+ work. it's based on the example code in OSL */
+
+#ifdef WITH_PARTIO
+ /* query Partio for this pointcloud lookup using cached attr_query */
+ if(!_attr_query)
+ return 0;
+
+ AttrQuery *attr_query = (AttrQuery *)_attr_query;
+ if(attr_query->capacity < max_points)
+ return 0;
+
+ /* get the pointcloud entry for the given filename */
+ Partio::ParticlesData *cloud = get_pointcloud(filename);
+
+ /* now we have to look up all the attributes in the file. we can't do this
+ before hand cause we never know what we are going to load. */
+ int nattrs = attr_query->attr_names.size();
+ Partio::ParticleAttribute *attr = (Partio::ParticleAttribute *)alloca(sizeof(Partio::ParticleAttribute) * nattrs);
+
+ for(int i = 0; i < nattrs; ++i) {
+ /* special case attributes */
+ if(attr_query->attr_names[i] == u_distance || attr_query->attr_names[i] == u_index)
+ continue;
+
+ /* lookup the attribute by name*/
+ if(!cloud->attributeInfo(attr_query->attr_names[i].c_str(), attr[i])) {
+ /* issue an error here and return, types don't match */
+ Partio::endCachedAccess(cloud);
+ cloud->release();
+ return 0;
+ }
+ }
+
+ std::vector<Partio::ParticleIndex> indices;
+ std::vector<float> dist2;
+
+ Partio::beginCachedAccess(cloud);
+
+ /* finally, do the lookup */
+ cloud->findNPoints((const float *)&center, max_points, radius, indices, dist2);
+ int count = indices.size();
+
+ /* retrieve the attributes directly to user space */
+ for(int j = 0; j < nattrs; ++j) {
+ /* special cases */
+ if(attr_query->attr_names[j] == u_distance) {
+ for(int i = 0; i < count; ++i)
+ ((float *)attr_outdata[j])[i] = sqrtf(dist2[i]);
+ }
+ else if(attr_query->attr_names[j] == u_index) {
+ for(int i = 0; i < count; ++i)
+ ((int *)attr_outdata[j])[i] = indices[i];
+ }
+ else {
+ /* note we make a single call per attribute, we don't loop over the
+ points. Partio does it, so it is there that we have to care about
+ performance */
+ cloud->data(attr[j], count, &indices[0], true, attr_outdata[j]);
+ }
+ }
+
+ Partio::endCachedAccess(cloud);
+ cloud->release();
+
+ return count;
+#else
+ return 0;
+#endif
+}
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h
new file mode 100644
index 00000000000..e5003074822
--- /dev/null
+++ b/intern/cycles/kernel/osl/osl_services.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __OSL_SERVICES_H__
+#define __OSL_SERVICES_H__
+
+/* OSL Render Services
+ *
+ * Implementation of OSL render services, to retriever matrices, attributes,
+ * textures and point clouds. In principle this should only be accessing
+ * kernel data, but currently we also reach back into the Scene to retrieve
+ * attributes.
+ */
+
+#include <OSL/oslexec.h>
+#include <OSL/oslclosure.h>
+
+#ifdef WITH_PARTIO
+#include <Partio.h>
+#endif
+
+CCL_NAMESPACE_BEGIN
+
+class Object;
+class Scene;
+class Shader;
+class ShaderData;
+class float3;
+class KernelGlobals;
+
+class OSLRenderServices : public OSL::RendererServices
+{
+public:
+ OSLRenderServices();
+ ~OSLRenderServices();
+
+ void thread_init(KernelGlobals *kernel_globals);
+
+ bool get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform, float time);
+ bool get_inverse_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform, float time);
+ bool get_matrix(OSL::Matrix44 &result, ustring from, float time);
+ bool get_inverse_matrix(OSL::Matrix44 &result, ustring to, float time);
+
+ bool get_array_attribute(void *renderstate, bool derivatives,
+ ustring object, TypeDesc type, ustring name,
+ int index, void *val);
+ bool get_attribute(void *renderstate, bool derivatives, ustring object,
+ TypeDesc type, ustring name, void *val);
+
+ bool get_userdata(bool derivatives, ustring name, TypeDesc type,
+ void *renderstate, void *val);
+ bool has_userdata(ustring name, TypeDesc type, void *renderstate);
+
+ void *get_pointcloud_attr_query(ustring *attr_names,
+ TypeDesc *attr_types, int nattrs);
+ int pointcloud(ustring filename, const OSL::Vec3 &center, float radius,
+ int max_points, void *attr_query, void **attr_outdata);
+
+private:
+ KernelGlobals *kernel_globals;
+
+#ifdef WITH_PARTIO
+ /* OSL gets pointers to this but its definition is private.
+ right now it only caches the types already converted to
+ Partio constants. this is what get_pointcloud_attr_query
+ returns */
+ struct AttrQuery
+ {
+ /* names of the attributes to query */
+ std::vector<ustring> attr_names;
+ /* types as (enum Partio::ParticleAttributeType) of the
+ attributes in the query */
+ std::vector<int> attr_partio_types;
+ /* for sanity checks, capacity of the output arrays */
+ int capacity;
+ };
+
+ Partio::ParticlesData *get_pointcloud(ustring filename);
+
+ /* keep a list so adding elements doesn't invalidate pointers */
+ std::list<AttrQuery> m_attr_queries;
+#endif
+
+ static ustring u_distance;
+ static ustring u_index;
+ static ustring u_camera;
+ static ustring u_screen;
+ static ustring u_raster;
+ static ustring u_ndc;
+ static ustring u_empty;
+};
+
+CCL_NAMESPACE_END
+
+#endif /* __OSL_SERVICES_H__ */
+
diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp
new file mode 100644
index 00000000000..f4ae0248bef
--- /dev/null
+++ b/intern/cycles/kernel/osl/osl_shader.cpp
@@ -0,0 +1,559 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "kernel_compat_cpu.h"
+#include "kernel_types.h"
+#include "kernel_globals.h"
+#include "kernel_object.h"
+
+#include "osl_services.h"
+#include "osl_shader.h"
+
+#include "util_foreach.h"
+
+#include <OSL/oslexec.h>
+#include <oslexec_pvt.h>
+
+CCL_NAMESPACE_BEGIN
+
+tls_ptr(ThreadData, OSLGlobals::thread_data);
+
+/* Threads */
+
+void OSLShader::thread_init(KernelGlobals *kg)
+{
+ OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss;
+
+ OSLGlobals::ThreadData *tdata = new OSLGlobals::ThreadData();
+
+ memset(&tdata->globals, 0, sizeof(OSL::ShaderGlobals));
+ tdata->thread_info = ssi->create_thread_info();
+
+ tls_set(kg->osl.thread_data, tdata);
+
+ ((OSLRenderServices*)ssi->renderer())->thread_init(kg);
+}
+
+void OSLShader::thread_free(KernelGlobals *kg)
+{
+ OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss;
+
+ OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
+
+ ssi->destroy_thread_info(tdata->thread_info);
+
+ delete tdata;
+}
+
+/* Globals */
+
+#define TO_VEC3(v) (*(OSL::Vec3*)&(v))
+#define TO_COLOR3(v) (*(OSL::Color3*)&(v))
+#define TO_FLOAT3(v) make_float3(v[0], v[1], v[2])
+
+static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd,
+ int path_flag, OSL::ShaderGlobals *globals)
+{
+ /* copy from shader data to shader globals */
+ globals->P = TO_VEC3(sd->P);
+ globals->dPdx = TO_VEC3(sd->dP.dx);
+ globals->dPdy = TO_VEC3(sd->dP.dy);
+ globals->I = TO_VEC3(sd->I);
+ globals->dIdx = TO_VEC3(sd->dI.dx);
+ globals->dIdy = TO_VEC3(sd->dI.dy);
+ globals->N = TO_VEC3(sd->N);
+ globals->Ng = TO_VEC3(sd->Ng);
+ globals->u = sd->u;
+ globals->dudx = sd->du.dx;
+ globals->dudy = sd->du.dy;
+ globals->v = sd->v;
+ globals->dvdx = sd->dv.dx;
+ globals->dvdy = sd->dv.dy;
+ globals->dPdu = TO_VEC3(sd->dPdu);
+ globals->dPdv = TO_VEC3(sd->dPdv);
+ globals->surfacearea = (sd->object == ~0)? 1.0f: object_surface_area(kg, sd->object);
+
+ /* booleans */
+ globals->raytype = path_flag;
+ globals->backfacing = (sd->flag & SD_BACKFACING);
+
+ /* don't know yet if we need this */
+ globals->flipHandedness = false;
+
+ /* shader data to be used in services callbacks */
+ globals->renderstate = sd;
+
+ /* hacky, we leave it to services to fetch actual object matrix */
+ globals->shader2common = sd;
+ globals->object2common = sd;
+
+ /* must be set to NULL before execute */
+ globals->Ci = NULL;
+}
+
+/* Surface */
+
+static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
+ const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f))
+{
+ /* OSL gives use a closure tree, we flatten it into arrays per
+ * closure type, for evaluation, sampling, etc later on. */
+
+ if(closure->type == OSL::ClosureColor::COMPONENT) {
+ OSL::ClosureComponent *comp = (OSL::ClosureComponent*)closure;
+ OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive*)comp->data();
+
+ if(prim) {
+ FlatClosure flat;
+ flat.prim = prim;
+ flat.weight = weight;
+
+ switch(prim->category()) {
+ case ClosurePrimitive::BSDF: {
+ if(sd->osl_closure.num_bsdf == MAX_OSL_CLOSURE)
+ return;
+
+ OSL::BSDFClosure *bsdf = (OSL::BSDFClosure*)prim;
+ ustring scattering = bsdf->scattering();
+
+ /* no caustics option */
+ if(no_glossy && scattering == OSL::Labels::GLOSSY)
+ return;
+
+ /* sample weight */
+ float albedo = bsdf->albedo(TO_VEC3(sd->I));
+ float sample_weight = fabsf(average(weight))*albedo;
+ float sample_sum = sd->osl_closure.bsdf_sample_sum + sample_weight;
+
+ flat.sample_weight = sample_weight;
+ sd->osl_closure.bsdf_sample_sum = sample_sum;
+
+ /* scattering flags */
+ if(scattering == OSL::Labels::DIFFUSE)
+ sd->flag |= SD_BSDF_HAS_EVAL;
+ else if(scattering == OSL::Labels::GLOSSY)
+ sd->flag |= SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
+
+ /* add */
+ sd->osl_closure.bsdf[sd->osl_closure.num_bsdf++] = flat;
+ break;
+ }
+ case ClosurePrimitive::Emissive: {
+ if(sd->osl_closure.num_bsdf == MAX_OSL_CLOSURE)
+ return;
+
+ /* sample weight */
+ float sample_weight = fabsf(average(weight));
+ float sample_sum = sd->osl_closure.emissive_sample_sum + sample_weight;
+
+ flat.sample_weight = sample_weight;
+ sd->osl_closure.emissive_sample_sum = sample_sum;
+
+ /* flag */
+ sd->flag |= SD_EMISSION;
+
+ sd->osl_closure.emissive[sd->osl_closure.num_emissive++] = flat;
+ break;
+ }
+ case ClosurePrimitive::BSSRDF:
+ case ClosurePrimitive::Holdout:
+ case ClosurePrimitive::Debug:
+ break; /* not implemented */
+ case ClosurePrimitive::Background:
+ case ClosurePrimitive::Volume:
+ break; /* not relevant */
+ }
+ }
+ }
+ else if(closure->type == OSL::ClosureColor::MUL) {
+ OSL::ClosureMul *mul = (OSL::ClosureMul*)closure;
+ flatten_surface_closure_tree(sd, no_glossy, mul->closure, TO_FLOAT3(mul->weight) * weight);
+ }
+ else if(closure->type == OSL::ClosureColor::ADD) {
+ OSL::ClosureAdd *add = (OSL::ClosureAdd*)closure;
+ flatten_surface_closure_tree(sd, no_glossy, add->closureA, weight);
+ flatten_surface_closure_tree(sd, no_glossy, add->closureB, weight);
+ }
+}
+
+void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag)
+{
+ /* gather pointers */
+ OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss;
+ OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
+ OSL::ShaderGlobals *globals = &tdata->globals;
+ OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info);
+
+ /* setup shader globals from shader data */
+ sd->osl_ctx = ctx;
+ shaderdata_to_shaderglobals(kg, sd, path_flag, globals);
+
+ /* execute shader for this point */
+ if(kg->osl.surface_state[sd->shader])
+ ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.surface_state[sd->shader]), *globals);
+
+ /* flatten closure tree */
+ sd->osl_closure.bsdf_sample_sum = 0.0f;
+ sd->osl_closure.emissive_sample_sum = 0.0f;
+ sd->osl_closure.num_bsdf = 0;
+ sd->osl_closure.num_emissive = 0;
+ sd->osl_closure.randb = randb;
+
+ if(globals->Ci) {
+ bool no_glossy = (path_flag & PATH_RAY_DIFFUSE) && kernel_data.integrator.no_caustics;
+ flatten_surface_closure_tree(sd, no_glossy, globals->Ci);
+ }
+}
+
+/* Background */
+
+static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure)
+{
+ /* OSL gives use a closure tree, if we are shading for background there
+ * is only one supported closure type at the moment, which has no evaluation
+ * functions, so we just sum the weights */
+
+ if(closure->type == OSL::ClosureColor::COMPONENT) {
+ OSL::ClosureComponent *comp = (OSL::ClosureComponent*)closure;
+ OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive*)comp->data();
+
+ if(prim && prim->category() == OSL::ClosurePrimitive::Background)
+ return make_float3(1.0f, 1.0f, 1.0f);
+ }
+ else if(closure->type == OSL::ClosureColor::MUL) {
+ OSL::ClosureMul *mul = (OSL::ClosureMul*)closure;
+
+ return TO_FLOAT3(mul->weight) * flatten_background_closure_tree(mul->closure);
+ }
+ else if(closure->type == OSL::ClosureColor::ADD) {
+ OSL::ClosureAdd *add = (OSL::ClosureAdd*)closure;
+
+ return flatten_background_closure_tree(add->closureA) +
+ flatten_background_closure_tree(add->closureB);
+ }
+
+ return make_float3(0.0f, 0.0f, 0.0f);
+}
+
+float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag)
+{
+ /* gather pointers */
+ OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss;
+ OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
+ OSL::ShaderGlobals *globals = &tdata->globals;
+ OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info);
+
+ /* setup shader globals from shader data */
+ sd->osl_ctx = ctx;
+ shaderdata_to_shaderglobals(kg, sd, path_flag, globals);
+
+ /* execute shader for this point */
+ if(kg->osl.background_state)
+ ctx->execute(OSL::pvt::ShadUseSurface, *kg->osl.background_state, *globals);
+
+ /* return background color immediately */
+ if(globals->Ci)
+ return flatten_background_closure_tree(globals->Ci);
+
+ return make_float3(0.0f, 0.0f, 0.0f);
+}
+
+/* Volume */
+
+static void flatten_volume_closure_tree(ShaderData *sd,
+ const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f))
+{
+ /* OSL gives use a closure tree, we flatten it into arrays per
+ * closure type, for evaluation, sampling, etc later on. */
+
+ if(closure->type == OSL::ClosureColor::COMPONENT) {
+ OSL::ClosureComponent *comp = (OSL::ClosureComponent*)closure;
+ OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive*)comp->data();
+
+ if(prim) {
+ FlatClosure flat;
+ flat.prim = prim;
+ flat.weight = weight;
+
+ switch(prim->category()) {
+ case ClosurePrimitive::Volume: {
+ if(sd->osl_closure.num_bsdf == MAX_OSL_CLOSURE)
+ return;
+
+ /* sample weight */
+ float sample_weight = fabsf(average(weight));
+ float sample_sum = sd->osl_closure.volume_sample_sum + sample_weight;
+
+ flat.sample_weight = sample_weight;
+ sd->osl_closure.volume_sample_sum = sample_sum;
+
+ /* add */
+ sd->osl_closure.volume[sd->osl_closure.num_volume++] = flat;
+ break;
+ }
+ case ClosurePrimitive::Holdout:
+ case ClosurePrimitive::Debug:
+ break; /* not implemented */
+ case ClosurePrimitive::Background:
+ case ClosurePrimitive::BSDF:
+ case ClosurePrimitive::Emissive:
+ case ClosurePrimitive::BSSRDF:
+ break; /* not relevant */
+ }
+ }
+ }
+ else if(closure->type == OSL::ClosureColor::MUL) {
+ OSL::ClosureMul *mul = (OSL::ClosureMul*)closure;
+ flatten_volume_closure_tree(sd, mul->closure, TO_FLOAT3(mul->weight) * weight);
+ }
+ else if(closure->type == OSL::ClosureColor::ADD) {
+ OSL::ClosureAdd *add = (OSL::ClosureAdd*)closure;
+ flatten_volume_closure_tree(sd, add->closureA, weight);
+ flatten_volume_closure_tree(sd, add->closureB, weight);
+ }
+}
+
+void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag)
+{
+ /* gather pointers */
+ OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss;
+ OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
+ OSL::ShaderGlobals *globals = &tdata->globals;
+ OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info);
+
+ /* setup shader globals from shader data */
+ sd->osl_ctx = ctx;
+ shaderdata_to_shaderglobals(kg, sd, path_flag, globals);
+
+ /* execute shader */
+ ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.volume_state[sd->shader]), *globals);
+
+ /* retrieve resulting closures */
+ sd->osl_closure.volume_sample_sum = 0.0f;
+ sd->osl_closure.num_volume = 0;
+ sd->osl_closure.randb = randb;
+
+ if(globals->Ci)
+ flatten_volume_closure_tree(sd, globals->Ci);
+}
+
+/* Displacement */
+
+void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd)
+{
+ /* gather pointers */
+ OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss;
+ OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
+ OSL::ShaderGlobals *globals = &tdata->globals;
+ OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info);
+
+ /* setup shader globals from shader data */
+ sd->osl_ctx = ctx;
+ shaderdata_to_shaderglobals(kg, sd, 0, globals);
+
+ /* execute shader */
+ ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.displacement_state[sd->shader]), *globals);
+
+ /* get back position */
+ sd->P = TO_FLOAT3(globals->P);
+}
+
+void OSLShader::release(KernelGlobals *kg, const ShaderData *sd)
+{
+ OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss;
+ OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
+
+ ssi->release_context((OSL::pvt::ShadingContext*)sd->osl_ctx, tdata->thread_info);
+}
+
+/* BSDF Closure */
+
+int OSLShader::bsdf_sample(const ShaderData *sd, float randu, float randv, float3& eval, float3& omega_in, differential3& domega_in, float& pdf)
+{
+ OSL::BSDFClosure *sample_bsdf = NULL;
+ int label = LABEL_NONE;
+ float r = sd->osl_closure.randb*sd->osl_closure.bsdf_sample_sum;
+ float sample_sum = 0.0f;
+
+ pdf = 0.0f;
+
+ if(sd->osl_closure.bsdf_sample_sum == 0.0f)
+ return LABEL_NONE;
+
+ /* find a closure to sample */
+ for(int i = 0; i < sd->osl_closure.num_bsdf; i++) {
+ const FlatClosure *flat = &sd->osl_closure.bsdf[i];
+ sample_sum += flat->sample_weight;
+
+ if(r > sample_sum)
+ continue;
+
+ /* sample BSDF closure */
+ sample_bsdf = (OSL::BSDFClosure*)flat->prim;
+ ustring ulabel;
+
+ ulabel = sample_bsdf->sample(TO_VEC3(sd->Ng),
+ TO_VEC3(sd->I), TO_VEC3(sd->dI.dx), TO_VEC3(sd->dI.dy),
+ randu, randv,
+ TO_VEC3(omega_in), TO_VEC3(domega_in.dx), TO_VEC3(domega_in.dy),
+ pdf, TO_COLOR3(eval));
+
+ /* convert OSL label */
+ if(ulabel == OSL::Labels::REFLECT)
+ label = LABEL_REFLECT;
+ else if(ulabel == OSL::Labels::TRANSMIT)
+ label = LABEL_TRANSMIT;
+ else
+ return LABEL_NONE; /* sampling failed */
+
+ /* convert scattering to our bitflag label */
+ ustring uscattering = sample_bsdf->scattering();
+
+ if(uscattering == OSL::Labels::DIFFUSE)
+ label |= LABEL_DIFFUSE;
+ else if(uscattering == OSL::Labels::GLOSSY)
+ label |= LABEL_GLOSSY;
+ else if(uscattering == OSL::Labels::SINGULAR)
+ label |= LABEL_SINGULAR;
+ else
+ label |= LABEL_STRAIGHT;
+
+ /* eval + pdf */
+ eval *= flat->weight;
+ pdf *= flat->sample_weight;
+
+ break;
+ }
+
+ if(!sample_bsdf || pdf == 0.0f)
+ return LABEL_NONE;
+
+ /* add eval/pdf from other BSDF closures */
+ for(int i = 0; i < sd->osl_closure.num_bsdf; i++) {
+ const FlatClosure *flat = &sd->osl_closure.bsdf[i];
+ OSL::BSDFClosure *bsdf = (OSL::BSDFClosure*)flat->prim;
+
+ if(bsdf != sample_bsdf) {
+ OSL::Color3 bsdf_eval;
+ float bsdf_pdf = 0.0f;
+
+ if(dot(sd->Ng, omega_in) >= 0.0f)
+ bsdf_eval = bsdf->eval_reflect(TO_VEC3(sd->I), TO_VEC3(omega_in), bsdf_pdf);
+ else
+ bsdf_eval = bsdf->eval_transmit(TO_VEC3(sd->I), TO_VEC3(omega_in), bsdf_pdf);
+
+ if(bsdf_pdf != 0.0f) {
+ eval += TO_FLOAT3(bsdf_eval)*flat->weight;
+ pdf += bsdf_pdf*flat->sample_weight;
+ }
+ }
+ }
+
+ pdf *= 1.0f/(sd->osl_closure.bsdf_sample_sum);
+
+ return label;
+}
+
+float3 OSLShader::bsdf_eval(const ShaderData *sd, const float3& omega_in, float& pdf)
+{
+ float3 eval = make_float3(0.0f, 0.0f, 0.0f);
+
+ pdf = 0.0f;
+
+ for(int i = 0; i < sd->osl_closure.num_bsdf; i++) {
+ const FlatClosure *flat = &sd->osl_closure.bsdf[i];
+ OSL::BSDFClosure *bsdf = (OSL::BSDFClosure*)flat->prim;
+ OSL::Color3 bsdf_eval;
+ float bsdf_pdf = 0.0f;
+
+ if(dot(sd->Ng, omega_in) >= 0.0f)
+ bsdf_eval = bsdf->eval_reflect(TO_VEC3(sd->I), TO_VEC3(omega_in), bsdf_pdf);
+ else
+ bsdf_eval = bsdf->eval_transmit(TO_VEC3(sd->I), TO_VEC3(omega_in), bsdf_pdf);
+
+ if(bsdf_pdf != 0.0f) {
+ eval += TO_FLOAT3(bsdf_eval)*flat->weight;
+ pdf += bsdf_pdf*flat->sample_weight;
+ }
+ }
+
+ pdf *= 1.0f/sd->osl_closure.bsdf_sample_sum;
+
+ return eval;
+}
+
+/* Emissive Closure */
+
+float3 OSLShader::emissive_eval(const ShaderData *sd)
+{
+ float3 eval = make_float3(0.0f, 0.0f, 0.0f);
+
+ for(int i = 0; i < sd->osl_closure.num_emissive; i++) {
+ const FlatClosure *flat = &sd->osl_closure.emissive[i];
+ OSL::EmissiveClosure *emissive = (OSL::EmissiveClosure*)flat->prim;
+ OSL::Color3 emissive_eval = emissive->eval(TO_VEC3(sd->Ng), TO_VEC3(sd->I));
+ eval += TO_FLOAT3(emissive_eval)*flat->weight;
+ }
+
+ return eval;
+}
+
+void OSLShader::emissive_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *I, float *pdf)
+{
+ float r = sd->osl_closure.randb*sd->osl_closure.emissive_sample_sum;
+ float sample_sum = 0.0f;
+
+ *pdf = 0.0f;
+
+ if(sd->osl_closure.emissive_sample_sum == 0.0f)
+ return;
+
+ /* find a closure to sample */
+ for(int i = 0; i < sd->osl_closure.num_emissive; i++) {
+ const FlatClosure *flat = &sd->osl_closure.emissive[i];
+ sample_sum += flat->sample_weight;
+
+ if(r <= sample_sum) {
+ /* sample emissive closure */
+ OSL::EmissiveClosure *emissive = (OSL::EmissiveClosure*)flat->prim;
+ emissive->sample(TO_VEC3(sd->Ng), randu, randv, TO_VEC3(*I), *pdf);
+ *eval = flat->weight;
+ *pdf *= flat->sample_weight/sd->osl_closure.emissive_sample_sum;
+ return;
+ }
+ }
+}
+
+/* Volume Closure */
+
+float3 OSLShader::volume_eval_phase(const ShaderData *sd, const float3 omega_in, const float3 omega_out)
+{
+ float3 eval = make_float3(0.0f, 0.0f, 0.0f);
+
+ for(int i = 0; i < sd->osl_closure.num_volume; i++) {
+ const FlatClosure *flat = &sd->osl_closure.volume[i];
+ OSL::VolumeClosure *volume = (OSL::VolumeClosure*)flat->prim;
+ OSL::Color3 volume_eval = volume->eval_phase(TO_VEC3(omega_in), TO_VEC3(omega_out));
+ eval += TO_FLOAT3(volume_eval)*flat->weight;
+ }
+
+ return eval;
+}
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/osl/osl_shader.h b/intern/cycles/kernel/osl/osl_shader.h
new file mode 100644
index 00000000000..2e5279c12ce
--- /dev/null
+++ b/intern/cycles/kernel/osl/osl_shader.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __OSL_SHADER_H__
+#define __OSL_SHADER_H__
+
+#ifdef WITH_OSL
+
+/* OSL Shader Engine
+ *
+ * Holds all variables to execute and use OSL shaders from the kernel. These
+ * are initialized externally by OSLShaderManager before rendering starts.
+ *
+ * Before/after a thread starts rendering, thread_init/thread_free must be
+ * called, which will store any per thread OSL state in thread local storage.
+ * This means no thread state must be passed along in the kernel itself.
+ */
+
+#include <OSL/oslexec.h>
+#include <OSL/oslclosure.h>
+
+#include "kernel_types.h"
+
+#include "util_map.h"
+#include "util_param.h"
+#include "util_vector.h"
+
+CCL_NAMESPACE_BEGIN
+
+namespace OSL = ::OSL;
+
+class OSLRenderServices;
+class Scene;
+class ShaderData;
+class differential3;
+class KernelGlobals;
+
+class OSLShader {
+public:
+ /* init */
+ static void register_closures(OSL::ShadingSystem *ss);
+
+ /* per thread data */
+ static void thread_init(KernelGlobals *kg);
+ static void thread_free(KernelGlobals *kg);
+
+ /* eval */
+ static void eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag);
+ static float3 eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag);
+ static void eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag);
+ static void eval_displacement(KernelGlobals *kg, ShaderData *sd);
+
+ /* sample & eval */
+ static int bsdf_sample(const ShaderData *sd, float randu, float randv,
+ float3& eval, float3& omega_in, differential3& domega_in, float& pdf);
+ static float3 bsdf_eval(const ShaderData *sd, const float3& omega_in, float& pdf);
+ static float3 emissive_eval(const ShaderData *sd);
+ static void emissive_sample(const ShaderData *sd, float randu, float randv,
+ float3 *eval, float3 *I, float *pdf);
+ static float3 volume_eval_phase(const ShaderData *sd, const float3 omega_in,
+ const float3 omega_out);
+
+ /* release */
+ static void release(KernelGlobals *kg, const ShaderData *sd);
+};
+
+CCL_NAMESPACE_END
+
+#endif
+
+#endif /* __OSL_SHADER_H__ */
+
diff --git a/intern/cycles/kernel/osl/vol_subsurface.cpp b/intern/cycles/kernel/osl/vol_subsurface.cpp
new file mode 100644
index 00000000000..0cd3060051b
--- /dev/null
+++ b/intern/cycles/kernel/osl/vol_subsurface.cpp
@@ -0,0 +1,135 @@
+/*
+ * Adapted from Open Shading Language with this license:
+ *
+ * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
+ * All Rights Reserved.
+ *
+ * Modifications Copyright 2011, Blender Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Sony Pictures Imageworks nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <OpenImageIO/fmath.h>
+
+#include <OSL/genclosure.h>
+
+#include "osl_closures.h"
+
+CCL_NAMESPACE_BEGIN
+
+using namespace OSL;
+
+// Computes scattering properties based on Jensen's reparameterization
+// described in:
+// http://graphics.ucsd.edu/~henrik/papers/fast_bssrdf/
+
+class SubsurfaceClosure : public VolumeClosure {
+public:
+ float m_g;
+ float m_eta;
+ Color3 m_mfp, m_albedo;
+ static float root_find_Rd(const float Rd0, const float A) {
+ // quick exit for trivial cases
+ if (Rd0 <= 0) return 0;
+ const float A43 = A * 4.0f / 3.0f;
+ // Find alpha such that f(alpha) = Rd (see eq.15). A simple bisection
+ // method can be used because this function is monotonicaly increasing.
+ float lo = 0, hi = 1;
+ for (int i = 0; i < 20; i++) { // 2^20 divisions should be sufficient
+ // eval function at midpoint
+ float alpha = 0.5f * (lo + hi);
+ float a1 = sqrtf(3 * (1 - alpha));
+ float e1 = expf(-a1);
+ float e2 = expf(-A43 * a1);
+ float Rd = 0.5f * alpha * (1 + e2) * e1 - Rd0;
+ if (fabsf(Rd) < 1e-6f)
+ return alpha; // close enough
+ else if (Rd > 0)
+ hi = alpha; // root is on left side
+ else
+ lo = alpha; // root is on right side
+ }
+ // didn't quite converge, pick result in the middle of remaining interval
+ return 0.5f * (lo + hi);
+ }
+ SubsurfaceClosure() { }
+
+ void setup()
+ {
+ ior(m_eta);
+
+ if (m_g >= 0.99f) m_g = 0.99f;
+ if (m_g <= -0.99f) m_g = -0.99f;
+
+ // eq.10
+ float inv_eta = 1 / m_eta;
+ float Fdr = -1.440f * inv_eta * inv_eta + 0.710 * inv_eta + 0.668f + 0.0636 * m_eta;
+ float A = (1 + Fdr) / (1 - Fdr);
+ // compute sigma_s, sigma_a (eq.16)
+ Color3 alpha_prime = Color3 (root_find_Rd(m_albedo[0], A),
+ root_find_Rd(m_albedo[1], A),
+ root_find_Rd(m_albedo[2], A));
+ Color3 sigma_t_prime = Color3 (m_mfp.x > 0 ? 1.0f / (m_mfp[0] * sqrtf(3 * (1 - alpha_prime[0]))) : 0.0f,
+ m_mfp.y > 0 ? 1.0f / (m_mfp[1] * sqrtf(3 * (1 - alpha_prime[1]))) : 0.0f,
+ m_mfp.z > 0 ? 1.0f / (m_mfp[2] * sqrtf(3 * (1 - alpha_prime[2]))) : 0.0f);
+ Color3 sigma_s_prime = alpha_prime * sigma_t_prime;
+
+ sigma_s((1.0f / (1 - m_g)) * sigma_s_prime);
+ sigma_a(sigma_t_prime - sigma_s_prime);
+ }
+
+ bool mergeable (const ClosurePrimitive *other) const {
+ const SubsurfaceClosure *comp = (const SubsurfaceClosure *)other;
+ return m_g == comp->m_g && VolumeClosure::mergeable(other);
+ }
+
+ size_t memsize () const { return sizeof(*this); }
+
+ const char *name () const { return "subsurface"; }
+
+ void print_on (std::ostream &out) const {
+ out << name() << " ()";
+ }
+
+ virtual Color3 eval_phase(const Vec3 &omega_in, const Vec3 &omega_out) const {
+ float costheta = omega_in.dot(omega_out);
+ float ph = 0.25f * float(M_1_PI) * ((1 - m_g * m_g) / powf(1 + m_g * m_g - 2.0f * m_g * costheta, 1.5f));
+ return Color3 (ph, ph, ph);
+ }
+};
+
+
+
+ClosureParam closure_subsurface_params[] = {
+ CLOSURE_FLOAT_PARAM (SubsurfaceClosure, m_eta),
+ CLOSURE_FLOAT_PARAM (SubsurfaceClosure, m_g),
+ CLOSURE_COLOR_PARAM (SubsurfaceClosure, m_mfp),
+ CLOSURE_COLOR_PARAM (SubsurfaceClosure, m_albedo),
+ CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_FINISH_PARAM(SubsurfaceClosure) };
+
+CLOSURE_PREPARE(closure_subsurface_prepare, SubsurfaceClosure)
+
+CCL_NAMESPACE_END
+