From da376e0237517543aa21740ee2363234ee1c20ae Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Wed, 27 Apr 2011 11:58:34 +0000 Subject: Cycles render engine, initial commit. This is the engine itself, blender modifications and build instructions will follow later. Cycles uses code from some great open source projects, many thanks them: * BVH building and traversal code from NVidia's "Understanding the Efficiency of Ray Traversal on GPUs": http://code.google.com/p/understanding-the-efficiency-of-ray-traversal-on-gpus/ * Open Shading Language for a large part of the shading system: http://code.google.com/p/openshadinglanguage/ * Blender for procedural textures and a few other nodes. * Approximate Catmull Clark subdivision from NVidia Mesh tools: http://code.google.com/p/nvidia-mesh-tools/ * Sobol direction vectors from: http://web.maths.unsw.edu.au/~fkuo/sobol/ * Film response functions from: http://www.cs.columbia.edu/CAVE/software/softlib/dorf.php --- intern/cycles/kernel/osl/CMakeLists.txt | 33 ++ intern/cycles/kernel/osl/background.cpp | 100 ++++ intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp | 175 +++++++ intern/cycles/kernel/osl/bsdf_diffuse.cpp | 181 +++++++ intern/cycles/kernel/osl/bsdf_microfacet.cpp | 533 ++++++++++++++++++++ intern/cycles/kernel/osl/bsdf_reflection.cpp | 108 ++++ intern/cycles/kernel/osl/bsdf_refraction.cpp | 120 +++++ intern/cycles/kernel/osl/bsdf_transparent.cpp | 97 ++++ intern/cycles/kernel/osl/bsdf_ward.cpp | 222 ++++++++ intern/cycles/kernel/osl/bsdf_westin.cpp | 239 +++++++++ intern/cycles/kernel/osl/bssrdf.cpp | 105 ++++ intern/cycles/kernel/osl/debug.cpp | 80 +++ intern/cycles/kernel/osl/emissive.cpp | 107 ++++ intern/cycles/kernel/osl/nodes/CMakeLists.txt | 69 +++ .../cycles/kernel/osl/nodes/node_add_closure.osl | 28 ++ intern/cycles/kernel/osl/nodes/node_attribute.osl | 43 ++ intern/cycles/kernel/osl/nodes/node_background.osl | 28 ++ .../cycles/kernel/osl/nodes/node_blend_texture.osl | 78 +++ intern/cycles/kernel/osl/nodes/node_bump.osl | 46 ++ .../kernel/osl/nodes/node_clouds_texture.osl | 42 ++ .../kernel/osl/nodes/node_convert_from_color.osl | 33 ++ .../kernel/osl/nodes/node_convert_from_float.osl | 33 ++ .../kernel/osl/nodes/node_convert_from_normal.osl | 33 ++ .../kernel/osl/nodes/node_convert_from_point.osl | 33 ++ .../kernel/osl/nodes/node_convert_from_vector.osl | 33 ++ .../cycles/kernel/osl/nodes/node_diffuse_bsdf.osl | 28 ++ .../osl/nodes/node_distorted_noise_texture.osl | 46 ++ intern/cycles/kernel/osl/nodes/node_emission.osl | 32 ++ .../kernel/osl/nodes/node_environment_texture.osl | 28 ++ intern/cycles/kernel/osl/nodes/node_fresnel.h | 21 + intern/cycles/kernel/osl/nodes/node_fresnel.osl | 30 ++ intern/cycles/kernel/osl/nodes/node_geometry.osl | 50 ++ intern/cycles/kernel/osl/nodes/node_glass_bsdf.osl | 41 ++ .../cycles/kernel/osl/nodes/node_glossy_bsdf.osl | 45 ++ .../cycles/kernel/osl/nodes/node_image_texture.osl | 28 ++ intern/cycles/kernel/osl/nodes/node_light_path.osl | 36 ++ .../cycles/kernel/osl/nodes/node_magic_texture.osl | 103 ++++ intern/cycles/kernel/osl/nodes/node_mapping.osl | 28 ++ .../kernel/osl/nodes/node_marble_texture.osl | 58 +++ intern/cycles/kernel/osl/nodes/node_math.osl | 84 ++++ intern/cycles/kernel/osl/nodes/node_mix.osl | 388 ++++++++++++++ .../cycles/kernel/osl/nodes/node_mix_closure.osl | 30 ++ .../kernel/osl/nodes/node_musgrave_texture.osl | 218 ++++++++ .../cycles/kernel/osl/nodes/node_noise_texture.osl | 36 ++ .../kernel/osl/nodes/node_output_displacement.osl | 25 + .../kernel/osl/nodes/node_output_surface.osl | 25 + .../cycles/kernel/osl/nodes/node_output_volume.osl | 25 + .../cycles/kernel/osl/nodes/node_sky_texture.osl | 162 ++++++ .../kernel/osl/nodes/node_stucci_texture.osl | 49 ++ intern/cycles/kernel/osl/nodes/node_texture.h | 251 +++++++++ .../kernel/osl/nodes/node_texture_coordinate.osl | 66 +++ .../kernel/osl/nodes/node_translucent_bsdf.osl | 28 ++ .../kernel/osl/nodes/node_transparent_bsdf.osl | 28 ++ intern/cycles/kernel/osl/nodes/node_value.osl | 33 ++ .../cycles/kernel/osl/nodes/node_vector_math.osl | 53 ++ .../cycles/kernel/osl/nodes/node_velvet_bsdf.osl | 40 ++ .../kernel/osl/nodes/node_voronoi_texture.osl | 82 +++ intern/cycles/kernel/osl/nodes/node_ward_bsdf.osl | 30 ++ .../cycles/kernel/osl/nodes/node_wood_texture.osl | 63 +++ intern/cycles/kernel/osl/nodes/stdosl.h | 471 +++++++++++++++++ intern/cycles/kernel/osl/osl_closures.cpp | 93 ++++ intern/cycles/kernel/osl/osl_closures.h | 114 +++++ intern/cycles/kernel/osl/osl_globals.h | 74 +++ intern/cycles/kernel/osl/osl_services.cpp | 424 ++++++++++++++++ intern/cycles/kernel/osl/osl_services.h | 111 ++++ intern/cycles/kernel/osl/osl_shader.cpp | 559 +++++++++++++++++++++ intern/cycles/kernel/osl/osl_shader.h | 87 ++++ intern/cycles/kernel/osl/vol_subsurface.cpp | 135 +++++ 68 files changed, 6957 insertions(+) create mode 100644 intern/cycles/kernel/osl/CMakeLists.txt create mode 100644 intern/cycles/kernel/osl/background.cpp create mode 100644 intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp create mode 100644 intern/cycles/kernel/osl/bsdf_diffuse.cpp create mode 100644 intern/cycles/kernel/osl/bsdf_microfacet.cpp create mode 100644 intern/cycles/kernel/osl/bsdf_reflection.cpp create mode 100644 intern/cycles/kernel/osl/bsdf_refraction.cpp create mode 100644 intern/cycles/kernel/osl/bsdf_transparent.cpp create mode 100644 intern/cycles/kernel/osl/bsdf_ward.cpp create mode 100644 intern/cycles/kernel/osl/bsdf_westin.cpp create mode 100644 intern/cycles/kernel/osl/bssrdf.cpp create mode 100644 intern/cycles/kernel/osl/debug.cpp create mode 100644 intern/cycles/kernel/osl/emissive.cpp create mode 100644 intern/cycles/kernel/osl/nodes/CMakeLists.txt create mode 100644 intern/cycles/kernel/osl/nodes/node_add_closure.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_attribute.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_background.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_blend_texture.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_bump.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_clouds_texture.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_convert_from_color.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_convert_from_float.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_convert_from_normal.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_convert_from_point.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_convert_from_vector.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_diffuse_bsdf.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_distorted_noise_texture.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_emission.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_environment_texture.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_fresnel.h create mode 100644 intern/cycles/kernel/osl/nodes/node_fresnel.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_geometry.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_glass_bsdf.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_glossy_bsdf.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_image_texture.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_light_path.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_magic_texture.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_mapping.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_marble_texture.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_math.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_mix.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_mix_closure.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_musgrave_texture.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_noise_texture.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_output_displacement.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_output_surface.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_output_volume.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_sky_texture.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_stucci_texture.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_texture.h create mode 100644 intern/cycles/kernel/osl/nodes/node_texture_coordinate.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_translucent_bsdf.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_transparent_bsdf.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_value.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_vector_math.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_velvet_bsdf.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_voronoi_texture.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_ward_bsdf.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_wood_texture.osl create mode 100644 intern/cycles/kernel/osl/nodes/stdosl.h create mode 100644 intern/cycles/kernel/osl/osl_closures.cpp create mode 100644 intern/cycles/kernel/osl/osl_closures.h create mode 100644 intern/cycles/kernel/osl/osl_globals.h create mode 100644 intern/cycles/kernel/osl/osl_services.cpp create mode 100644 intern/cycles/kernel/osl/osl_services.h create mode 100644 intern/cycles/kernel/osl/osl_shader.cpp create mode 100644 intern/cycles/kernel/osl/osl_shader.h create mode 100644 intern/cycles/kernel/osl/vol_subsurface.cpp (limited to 'intern/cycles/kernel/osl') 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 + +#include + +#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 + +#include + +#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 + +#include + +#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 + +#include + +#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 +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 +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 + +#include + +#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 + +#include + +#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 + +#include + +#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 + +#include + +#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 + +#include + +#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 + +#include + +#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 + static inline T pow3 (const T &x) { return x * x * x; } + + template + 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 + +#include + +#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 + +#include + +#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 +#include + +#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 +#include +#include + +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 + +#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 surface_state; + vector volume_state; + vector displacement_state; + OSL::ShadingAttribStateRef background_state; + + /* attributes */ + struct Attribute { + TypeDesc type; + AttributeElement elem; + int offset; + ParamValue value; + }; + + typedef unordered_map AttributeMap; + typedef unordered_map ObjectNameMap; + + vector 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 + +#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 ¢er, 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 indices; + std::vector dist2; + + Partio::beginCachedAccess(cloud); + + /* finally, do the lookup */ + cloud->findNPoints((const float *)¢er, 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 +#include + +#ifdef WITH_PARTIO +#include +#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 ¢er, 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 attr_names; + /* types as (enum Partio::ParticleAttributeType) of the + attributes in the query */ + std::vector 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 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 +#include + +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 +#include + +#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 + +#include + +#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 + -- cgit v1.2.3