diff options
Diffstat (limited to 'intern')
-rw-r--r-- | intern/cycles/blender/blender_shader.cpp | 13 | ||||
-rw-r--r-- | intern/cycles/kernel/CMakeLists.txt | 1 | ||||
-rw-r--r-- | intern/cycles/kernel/closure/bsdf.h | 25 | ||||
-rw-r--r-- | intern/cycles/kernel/closure/bsdf_hair.h | 279 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_shader.h | 2 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_types.h | 6 | ||||
-rw-r--r-- | intern/cycles/kernel/osl/osl_closures.cpp | 32 | ||||
-rw-r--r-- | intern/cycles/kernel/osl/osl_shader.cpp | 4 | ||||
-rw-r--r-- | intern/cycles/kernel/shaders/CMakeLists.txt | 1 | ||||
-rw-r--r-- | intern/cycles/kernel/shaders/node_hair_bsdf.osl | 56 | ||||
-rw-r--r-- | intern/cycles/kernel/shaders/stdosl.h | 3 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_closure.h | 40 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_types.h | 8 | ||||
-rw-r--r-- | intern/cycles/render/nodes.cpp | 40 | ||||
-rw-r--r-- | intern/cycles/render/nodes.h | 9 |
15 files changed, 515 insertions, 4 deletions
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 5dfbd97366a..2007171642f 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -395,6 +395,19 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen } node = toon; } + else if (b_node.is_a(&RNA_ShaderNodeBsdfHair)) { + BL::ShaderNodeBsdfHair b_hair_node(b_node); + HairBsdfNode *hair = new HairBsdfNode(); + switch(b_hair_node.component()) { + case BL::ShaderNodeBsdfHair::component_Reflection: + hair->component = ustring("Reflection"); + break; + case BL::ShaderNodeBsdfHair::component_Transmission: + hair->component = ustring("Transmission"); + break; + } + node = hair; + } else if (b_node.is_a(&RNA_ShaderNodeBsdfTranslucent)) { node = new TranslucentBsdfNode(); } diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 9db05693fc3..eaa4e304ebb 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -67,6 +67,7 @@ set(SRC_CLOSURE_HEADERS closure/bsdf_util.h closure/bsdf_ward.h closure/bsdf_westin.h + closure/bsdf_hair.h closure/bssrdf.h closure/emissive.h closure/volume.h diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h index d81bbebd5a8..86fea48760f 100644 --- a/intern/cycles/kernel/closure/bsdf.h +++ b/intern/cycles/kernel/closure/bsdf.h @@ -28,6 +28,7 @@ #endif #include "../closure/bsdf_westin.h" #include "../closure/bsdf_toon.h" +#include "../closure/bsdf_hair.h" #ifdef __SUBSURFACE__ #include "../closure/bssrdf.h" #endif @@ -114,6 +115,14 @@ __device int bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const ShaderCl label = bsdf_westin_sheen_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; + case CLOSURE_BSDF_HAIR_REFLECTION_ID: + label = bsdf_hair_reflection_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + break; + case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: + label = bsdf_hair_transmission_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + break; #endif default: label = LABEL_NONE; @@ -188,6 +197,12 @@ __device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const ShaderC case CLOSURE_BSDF_WESTIN_SHEEN_ID: eval = bsdf_westin_sheen_eval_reflect(sc, sd->I, omega_in, pdf); break; + case CLOSURE_BSDF_HAIR_REFLECTION_ID: + eval = bsdf_hair_reflection_eval_reflect(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: + eval = bsdf_hair_transmission_eval_reflect(sc, sd->I, omega_in, pdf); + break; #endif default: eval = make_float3(0.0f, 0.0f, 0.0f); @@ -244,6 +259,12 @@ __device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const ShaderC case CLOSURE_BSDF_WESTIN_SHEEN_ID: eval = bsdf_westin_sheen_eval_transmit(sc, sd->I, omega_in, pdf); break; + case CLOSURE_BSDF_HAIR_REFLECTION_ID: + eval = bsdf_hair_reflection_eval_transmit(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: + eval = bsdf_hair_transmission_eval_transmit(sc, sd->I, omega_in, pdf); + break; #endif default: eval = make_float3(0.0f, 0.0f, 0.0f); @@ -318,6 +339,10 @@ __device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness) case CLOSURE_BSDF_WESTIN_SHEEN_ID: bsdf_westin_sheen_blur(sc, roughness); break; + case CLOSURE_BSDF_HAIR_REFLECTION_ID: + case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: + bsdf_hair_reflection_blur(sc, roughness); + break; #endif default: break; diff --git a/intern/cycles/kernel/closure/bsdf_hair.h b/intern/cycles/kernel/closure/bsdf_hair.h new file mode 100644 index 00000000000..5791598459c --- /dev/null +++ b/intern/cycles/kernel/closure/bsdf_hair.h @@ -0,0 +1,279 @@ +/* + * 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 __BSDF_HAIR_H__ +#define __BSDF_HAIR_H__ + +CCL_NAMESPACE_BEGIN + + +__device void bsdf_hair_reflection_blur(ShaderClosure *sc, float roughness) +{ +} + +__device void bsdf_hair_transmission_blur(ShaderClosure *sc, float roughness) +{ +} + +__device int bsdf_hair_reflection_setup(ShaderClosure *sc) +{ + sc->type = CLOSURE_BSDF_HAIR_REFLECTION_ID; + sc->data0 = clamp(sc->data0, 0.001f,1.0f); + sc->data1 = clamp(sc->data1, 0.001f,1.0f); + return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; +} + +__device int bsdf_hair_transmission_setup(ShaderClosure *sc) +{ + sc->type = CLOSURE_BSDF_HAIR_TRANSMISSION_ID; + sc->data0 = clamp(sc->data0, 0.001f,1.0f); + sc->data1 = clamp(sc->data1, 0.001f,1.0f); + return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; +} + +__device float3 bsdf_hair_reflection_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +{ +#ifdef __HAIR__ + float offset = sc->offset; + float3 Tg = sc->T; +#else + float offset = 0.0f; + float3 Tg = make_float3(1.0f,0.0f,0.0f); +#endif + float roughness1 = sc->data0; + float roughness2 = sc->data1; + + float Iz = dot(Tg, I); + float3 locy = normalize(I - Tg * Iz); + float3 locx = cross(locy, Tg); + + float theta_r = M_PI_2_F - safe_acosf(Iz); + + float omega_in_z = dot(Tg, omega_in); + float3 omega_in_y = normalize(omega_in - Tg * omega_in_z); + + float theta_i = M_PI_2_F - safe_acosf(omega_in_z); + float cosphi_i = dot(omega_in_y, locy); + + if(M_PI_2_F - fabsf(theta_i) < 0.001f || cosphi_i < 0.0f){ + *pdf = 0.0f; + return make_float3(*pdf, *pdf, *pdf); + } + + float phi_i = safe_acosf(cosphi_i) / roughness2; + phi_i = fabsf(phi_i) < M_PI_F ? phi_i : M_PI_F; + float costheta_i = cosf(theta_i); + + float a_R = atan2f(((M_PI_2_F + theta_r) * 0.5f - offset) / roughness1, 1.0f); + float b_R = atan2f(((-M_PI_2_F + theta_r) * 0.5f - offset) / roughness1, 1.0f); + + float theta_h = (theta_i + theta_r) * 0.5f; + float t = theta_h - offset; + + float phi_pdf = cos(phi_i * 0.5f) * 0.25f / roughness2; + float theta_pdf = roughness1 / (2 * (t*t + roughness1*roughness1) * (a_R - b_R)* costheta_i); + *pdf = phi_pdf * theta_pdf; + + return make_float3(*pdf, *pdf, *pdf); +} + +__device float3 bsdf_hair_transmission_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +{ + return make_float3(0.0f, 0.0f, 0.0f); +} + + +__device float3 bsdf_hair_reflection_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +{ + return make_float3(0.0f, 0.0f, 0.0f); +} + +__device float3 bsdf_hair_transmission_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +{ +#ifdef __HAIR__ + float offset = sc->offset; + float3 Tg = sc->T; +#else + float offset = 0.0f; + float3 Tg = make_float3(1.0f,0.0f,0.0f); +#endif + float roughness1 = sc->data0; + float roughness2 = sc->data1; + float Iz = dot(Tg, I); + float3 locy = normalize(I - Tg * Iz); + float3 locx = cross(locy, Tg); + + float theta_r = M_PI_2_F - safe_acosf(Iz); + + float omega_in_z = dot(Tg, omega_in); + float3 omega_in_y = normalize(omega_in - Tg * omega_in_z); + + float theta_i = M_PI_2_F - safe_acosf(omega_in_z); + float phi_i = safe_acosf(dot(omega_in_y, locy)); + + if(M_PI_2_F - fabsf(theta_i) < 0.001f){ + *pdf = 0.0f; + return make_float3(*pdf, *pdf, *pdf); + } + + float costheta_i = cosf(theta_i); + + float a_TT = atan2f(((M_PI_2_F + theta_r)/2 - offset) / roughness1, 1.0f); + float b_TT = atan2f(((-M_PI_2_F + theta_r)/2 - offset) / roughness1, 1.0f); + float c_TT = 2 * atan2f(M_PI_2_F / roughness2, 1.0f); + + float theta_h = (theta_i + theta_r) / 2; + float t = theta_h - offset; + float phi = fabsf(phi_i); + + float p = M_PI_F - phi; + float theta_pdf = roughness1 / (2 * (t*t + roughness1 * roughness1) * (a_TT - b_TT)*costheta_i); + float phi_pdf = roughness2 / (c_TT * (p * p + roughness2 * roughness2)); + + *pdf = phi_pdf * theta_pdf; + return make_float3(*pdf, *pdf, *pdf); +} + +__device int bsdf_hair_reflection_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +{ +#ifdef __HAIR__ + float offset = sc->offset; + float3 Tg = sc->T; +#else + float offset = 0.0f; + float3 Tg = make_float3(1.0f,0.0f,0.0f); +#endif + float roughness1 = sc->data0; + float roughness2 = sc->data1; + float Iz = dot(Tg, I); + float3 locy = normalize(I - Tg * Iz); + float3 locx = cross(locy, Tg); + float theta_r = M_PI_2_F - safe_acosf(Iz); + + float a_R = atan2f(((M_PI_2_F + theta_r) * 0.5f - offset) / roughness1, 1.0f); + float b_R = atan2f(((-M_PI_2_F + theta_r) * 0.5f - offset) / roughness1, 1.0f); + + float t = roughness1 * tanf(randu * (a_R - b_R) + b_R); + + float theta_h = t + offset; + float theta_i = 2 * theta_h - theta_r; + float costheta_i = cosf(theta_i); + float sintheta_i = sinf(theta_i); + + float phi = 2 * safe_asinf(1 - 2 * randv) * roughness2; + + float phi_pdf = cos(phi * 0.5f) * 0.25f / roughness2; + + float theta_pdf = roughness1 / (2 * (t*t + roughness1*roughness1) * (a_R - b_R)*costheta_i); + + *omega_in =(cosf(phi) * costheta_i) * locy - + (sinf(phi) * costheta_i) * locx + + ( sintheta_i) * Tg; + + //differentials - TODO: find a better approximation for the reflective bounce +#ifdef __RAY_DIFFERENTIALS__ + *domega_in_dx = 2 * dot(locy, dIdx) * locy - dIdx; + *domega_in_dy = 2 * dot(locy, dIdy) * locy - dIdy; +#endif + + *pdf = fabsf(phi_pdf * theta_pdf); + if(M_PI_2_F - fabsf(theta_i) < 0.001f) + *pdf = 0.0f; + + *eval = make_float3(*pdf, *pdf, *pdf); + + if(dot(locy, *omega_in) < 0.0f) { + return LABEL_REFLECT|LABEL_TRANSMIT|LABEL_GLOSSY; + } + + return LABEL_REFLECT|LABEL_GLOSSY; +} + +__device int bsdf_hair_transmission_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +{ +#ifdef __HAIR__ + float offset = sc->offset; + float3 Tg = sc->T; +#else + float offset = 0.0f; + float3 Tg = make_float3(1.0f,0.0f,0.0f); +#endif + float roughness1 = sc->data0; + float roughness2 = sc->data1; + float Iz = dot(Tg, I); + float3 locy = normalize(I - Tg * Iz); + float3 locx = cross(locy, Tg); + float theta_r = M_PI_2_F - safe_acosf(Iz); + + float a_TT = atan2f(((M_PI_2_F + theta_r)/2 - offset) / roughness1, 1.0f); + float b_TT = atan2f(((-M_PI_2_F + theta_r)/2 - offset) / roughness1, 1.0f); + float c_TT = 2 * atan2f(M_PI_2_F / roughness2, 1.0f); + + float t = roughness1 * tanf(randu * (a_TT - b_TT) + b_TT); + + float theta_h = t + offset; + float theta_i = 2 * theta_h - theta_r; + float costheta_i = cosf(theta_i); + float sintheta_i = sinf(theta_i); + + float p = roughness2 * tanf(c_TT * (randv - 0.5f)); + float phi = p + M_PI_F; + float theta_pdf = roughness1 / (2 * (t*t + roughness1*roughness1) * (a_TT - b_TT) * costheta_i); + float phi_pdf = roughness2 / (c_TT * (p * p + roughness2 * roughness2)); + + *omega_in =(cosf(phi) * costheta_i) * locy - + (sinf(phi) * costheta_i) * locx + + ( sintheta_i) * Tg; + + //differentials - TODO: find a better approximation for the transmission bounce +#ifdef __RAY_DIFFERENTIALS__ + *domega_in_dx = 2 * dot(locy, dIdx) * locy - dIdx; + *domega_in_dy = 2 * dot(locy, dIdy) * locy - dIdy; +#endif + + *pdf = fabsf(phi_pdf * theta_pdf); + if(M_PI_2_F - fabsf(theta_i) < 0.001f){ + *pdf = 0.0f; + } + + *eval = make_float3(*pdf, *pdf, *pdf); + + if(dot(locy, *omega_in) < 0.0f) + return LABEL_TRANSMIT|LABEL_GLOSSY; + + return LABEL_GLOSSY; +} + +CCL_NAMESPACE_END + +#endif /* __BSDF_HAIR_H__ */ + diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index e8e9af64df6..bcc4c42c9cc 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -272,7 +272,7 @@ void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, #ifdef __INSTANCING__ sd->object = object; #endif - /* currently no access to bvh prim index for strand sd->prim - this will cause errors with needs fixing*/ + /* currently no access to bvh prim index for strand sd->prim*/ sd->prim = prim; #ifdef __UV__ sd->u = u; diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 98594df8b10..d039b708bd4 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -462,10 +462,14 @@ typedef struct ShaderClosure { float data1; float3 N; -#if defined(__ANISOTROPIC__) || defined(__SUBSURFACE__) +#if defined(__ANISOTROPIC__) || defined(__SUBSURFACE__) || defined(__HAIR__) float3 T; #endif +#ifdef __HAIR__ + float offset; +#endif + #ifdef __OSL__ void *prim; #endif diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp index 6a3f27fb7b1..221406a1716 100644 --- a/intern/cycles/kernel/osl/osl_closures.cpp +++ b/intern/cycles/kernel/osl/osl_closures.cpp @@ -54,6 +54,7 @@ #include "closure/bsdf_ward.h" #include "closure/bsdf_westin.h" #include "closure/bsdf_toon.h" +#include "closure/bsdf_hair.h" CCL_NAMESPACE_BEGIN @@ -142,6 +143,32 @@ BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannRefraction, microfacet_beckmann_refra CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, sc.data1), BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction) +BSDF_CLOSURE_CLASS_BEGIN(HairReflection, hair_reflection, hair_reflection, LABEL_GLOSSY) + CLOSURE_FLOAT3_PARAM(HairReflectionClosure, sc.N), + CLOSURE_FLOAT_PARAM(HairReflectionClosure, sc.data0), + CLOSURE_FLOAT_PARAM(HairReflectionClosure, sc.data1), +#ifdef __HAIR__ + CLOSURE_FLOAT3_PARAM(HairReflectionClosure, sc.T), + CLOSURE_FLOAT_PARAM(HairReflectionClosure, sc.offset), +#else + CLOSURE_FLOAT3_PARAM(HairReflectionClosure, sc.N), + CLOSURE_FLOAT_PARAM(HairReflectionClosure, sc.data1), +#endif +BSDF_CLOSURE_CLASS_END(HairReflection, hair_reflection) + +BSDF_CLOSURE_CLASS_BEGIN(HairTransmission, hair_transmission, hair_transmission, LABEL_GLOSSY) + CLOSURE_FLOAT3_PARAM(HairTransmissionClosure, sc.N), + CLOSURE_FLOAT_PARAM(HairTransmissionClosure, sc.data0), + CLOSURE_FLOAT_PARAM(HairTransmissionClosure, sc.data1), +#ifdef __HAIR__ + CLOSURE_FLOAT3_PARAM(HairReflectionClosure, sc.T), + CLOSURE_FLOAT_PARAM(HairReflectionClosure, sc.offset), +#else + CLOSURE_FLOAT3_PARAM(HairReflectionClosure, sc.N), + CLOSURE_FLOAT_PARAM(HairReflectionClosure, sc.data1), +#endif +BSDF_CLOSURE_CLASS_END(HairTransmission, hair_transmission) + /* Registration */ static void generic_closure_setup(OSL::RendererServices *, int id, void *data) @@ -225,6 +252,11 @@ void OSLShader::register_closures(OSLShadingSystem *ss_) closure_bssrdf_cubic_extended_params(), closure_bssrdf_cubic_prepare); register_closure(ss, "bssrdf_gaussian", id++, closure_bssrdf_gaussian_extended_params(), closure_bssrdf_gaussian_prepare); + + register_closure(ss, "hair_reflection", id++, + bsdf_hair_reflection_params(), bsdf_hair_reflection_prepare); + register_closure(ss, "hair_transmission", id++, + bsdf_hair_transmission_params(), bsdf_hair_transmission_prepare); } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index 9ff3797b50f..625ad263f7f 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -180,6 +180,10 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag, sc.data1 = bsdf->sc.data1; sc.prim = bsdf->sc.prim; +#ifdef __HAIR__ + sc.offset = bsdf->sc.offset; +#endif + /* add */ if(sc.sample_weight > 1e-5f && sd->num_closure < MAX_CLOSURE) { sd->closure[sd->num_closure++] = sc; diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt index 660cfbce528..0f8542b0546 100644 --- a/intern/cycles/kernel/shaders/CMakeLists.txt +++ b/intern/cycles/kernel/shaders/CMakeLists.txt @@ -74,6 +74,7 @@ set(SRC_OSL node_blackbody.osl node_wave_texture.osl node_wireframe.osl + node_hair_bsdf.osl ) set(SRC_OSL_HEADERS diff --git a/intern/cycles/kernel/shaders/node_hair_bsdf.osl b/intern/cycles/kernel/shaders/node_hair_bsdf.osl new file mode 100644 index 00000000000..d1d7d0fb6a6 --- /dev/null +++ b/intern/cycles/kernel/shaders/node_hair_bsdf.osl @@ -0,0 +1,56 @@ +/* + * 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_hair_bsdf( + color Color = 0.8, + string component = "Reflection", + float Offset = 0.0, + float RoughnessU = 0.1, + float RoughnessV = 1.0, + normal Normal = Ng, + output closure color BSDF = 0) +{ + float IsStrand; + float roughnessh = clamp(RoughnessU, 0.001,1.0); + float roughnessv = clamp(RoughnessV, 0.001,1.0); + getattribute("geom:is_curve", IsStrand); + + if (!IsStrand) { + if (backfacing()) + BSDF = transparent(); + else { + if (component == "Reflection") + BSDF = Color * hair_reflection(Normal, roughnessh, roughnessv, normalize(dPdv), 0.0); + else + BSDF = Color * hair_transmission(Normal, roughnessh, roughnessv, normalize(dPdv), 0.0); + } + } + else { + if (backfacing()) + BSDF = transparent(); + else { + if (component == "Reflection") + BSDF = Color * hair_reflection(Normal, roughnessh, roughnessv, dPdu, -Offset); + else + BSDF = Color * hair_transmission(Normal, roughnessh, roughnessv, dPdu, -Offset); + } + } +} + diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h index 3ad2bbc0588..424ca335903 100644 --- a/intern/cycles/kernel/shaders/stdosl.h +++ b/intern/cycles/kernel/shaders/stdosl.h @@ -468,6 +468,9 @@ closure color ambient_occlusion() BUILTIN; closure color bssrdf_cubic(normal N, vector radius, float texture_blur, float sharpness) BUILTIN; closure color bssrdf_gaussian(normal N, vector radius, float texture_blur) BUILTIN; +closure color hair_reflection(normal N, float roughnessu, float roughnessv, vector T, float offset) BUILTIN; +closure color hair_transmission(normal N, float roughnessu, float roughnessv, vector T, float offset) BUILTIN; + // Backwards compatibility closure color bssrdf_cubic(normal N, vector radius) BUILTIN; closure color bssrdf_gaussian(normal N, vector radius) BUILTIN; diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h index 9a9aefa5b29..6d9c4e215e6 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -337,6 +337,46 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st } break; } +#ifdef __HAIR__ + case CLOSURE_BSDF_HAIR_REFLECTION_ID: + case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: { + + if(sd->flag & SD_BACKFACING && sd->segment != ~0) { + ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); + if(sc) { + sc->weight = make_float3(1.0f,1.0f,1.0f); + sc->N = N; + sd->flag |= bsdf_transparent_setup(sc); + } + } + else { + ShaderClosure *sc = &sd->closure[sd->num_closure]; + sc = svm_node_closure_get_bsdf(sd, mix_weight); + + if(sc) { + sc->N = N; + sc->data0 = param1; + sc->data1 = param2; + sc->offset = -stack_load_float(stack, data_node.z); + if(sd->segment == ~0) { + sc->T = normalize(sd->dPdv); + sc->offset = 0.0f; + } + else + sc->T = sd->dPdu; + if(type == CLOSURE_BSDF_HAIR_REFLECTION_ID) { + sd->flag |= bsdf_hair_reflection_setup(sc); + } + else { + sd->flag |= bsdf_hair_transmission_setup(sc); + } + } + } + + break; + } +#endif + #ifdef __SUBSURFACE__ case CLOSURE_BSSRDF_COMPATIBLE_ID: case CLOSURE_BSSRDF_CUBIC_ID: diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index e2b299e661d..50daf159f26 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -357,6 +357,8 @@ typedef enum ClosureType { CLOSURE_BSDF_WESTIN_BACKSCATTER_ID, CLOSURE_BSDF_PHONG_RAMP_ID, CLOSURE_BSDF_GLOSSY_TOON_ID, + CLOSURE_BSDF_HAIR_REFLECTION_ID, + /* Transmission */ CLOSURE_BSDF_TRANSMISSION_ID, @@ -367,6 +369,8 @@ typedef enum ClosureType { CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID, CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID, CLOSURE_BSDF_SHARP_GLASS_ID, + CLOSURE_BSDF_HAIR_TRANSMISSION_ID, + /* Special cases */ CLOSURE_BSDF_BSSRDF_ID, @@ -395,8 +399,8 @@ typedef enum ClosureType { /* watch this, being lazy with memory usage */ #define CLOSURE_IS_BSDF(type) (type <= CLOSURE_BSDF_TRANSPARENT_ID) #define CLOSURE_IS_BSDF_DIFFUSE(type) (type >= CLOSURE_BSDF_DIFFUSE_ID && type <= CLOSURE_BSDF_DIFFUSE_TOON_ID) -#define CLOSURE_IS_BSDF_GLOSSY(type) (type >= CLOSURE_BSDF_GLOSSY_ID && type <= CLOSURE_BSDF_GLOSSY_TOON_ID) -#define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSMISSION_ID && type <= CLOSURE_BSDF_SHARP_GLASS_ID) +#define CLOSURE_IS_BSDF_GLOSSY(type) (type >= CLOSURE_BSDF_GLOSSY_ID && type <= CLOSURE_BSDF_HAIR_REFLECTION_ID) +#define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSMISSION_ID && type <= CLOSURE_BSDF_HAIR_TRANSMISSION_ID) #define CLOSURE_IS_BSDF_BSSRDF(type) (type == CLOSURE_BSDF_BSSRDF_ID) #define CLOSURE_IS_BSSRDF(type) (type >= CLOSURE_BSSRDF_COMPATIBLE_ID && type <= CLOSURE_BSSRDF_GAUSSIAN_ID) #define CLOSURE_IS_VOLUME(type) (type >= CLOSURE_VOLUME_ID && type <= CLOSURE_VOLUME_ISOTROPIC_ID) diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 30f51728e1b..70cb5613e61 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1950,6 +1950,46 @@ void IsotropicVolumeNode::compile(OSLCompiler& compiler) compiler.add(this, "node_isotropic_volume"); } +/* Hair BSDF Closure */ + +static ShaderEnum hair_component_init() +{ + ShaderEnum enm; + + enm.insert("Reflection", CLOSURE_BSDF_HAIR_REFLECTION_ID); + enm.insert("Transmission", CLOSURE_BSDF_HAIR_TRANSMISSION_ID); + + + return enm; +} + +ShaderEnum HairBsdfNode::component_enum = hair_component_init(); + +HairBsdfNode::HairBsdfNode() +{ + component = ustring("Reflection"); + + add_input("Offset", SHADER_SOCKET_FLOAT); + add_input("RoughnessU", SHADER_SOCKET_FLOAT); + add_input("RoughnessV", SHADER_SOCKET_FLOAT); + +} + +void HairBsdfNode::compile(SVMCompiler& compiler) +{ + closure = (ClosureType)component_enum[component]; + + BsdfNode::compile(compiler, input("RoughnessU"), input("RoughnessV"), input("Offset")); +} + +void HairBsdfNode::compile(OSLCompiler& compiler) +{ + compiler.parameter("component", component); + + compiler.add(this, "node_hair_bsdf"); + +} + /* Geometry */ GeometryNode::GeometryNode() diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 50338ddd5c0..d58c6633a41 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -321,6 +321,15 @@ public: SHADER_NODE_CLASS(IsotropicVolumeNode) }; +class HairBsdfNode : public BsdfNode { +public: + SHADER_NODE_CLASS(HairBsdfNode) + + ustring component; + static ShaderEnum component_enum; + +}; + class GeometryNode : public ShaderNode { public: SHADER_NODE_CLASS(GeometryNode) |