From 8ce1090d4e8160165281be4b0827dbc1ba28dc8a Mon Sep 17 00:00:00 2001 From: Karsten Schwenk Date: Sun, 8 Jun 2014 12:16:28 +0200 Subject: Cycles: Ashikhmin-Shirley anisotropic BSDF * Ashikhmin-Shirley anisotropic BSDF was added as closure * Anisotropic BSDF node now has two distributions Reviewers: brecht, dingto Differential Revision: https://developer.blender.org/D549 --- intern/cycles/app/cycles_xml.cpp | 6 +- intern/cycles/blender/blender_shader.cpp | 16 +- intern/cycles/kernel/CMakeLists.txt | 1 + intern/cycles/kernel/closure/bsdf.h | 14 ++ .../cycles/kernel/closure/bsdf_ashikhmin_shirley.h | 196 +++++++++++++++++++++ intern/cycles/kernel/osl/osl_closures.cpp | 10 ++ intern/cycles/kernel/shaders/CMakeLists.txt | 2 +- .../kernel/shaders/node_anisotropic_bsdf.osl | 53 ++++++ intern/cycles/kernel/shaders/node_ward_bsdf.osl | 49 ------ intern/cycles/kernel/shaders/stdosl.h | 1 + intern/cycles/kernel/svm/svm_closure.h | 9 +- intern/cycles/kernel/svm/svm_types.h | 3 +- intern/cycles/render/nodes.cpp | 29 ++- intern/cycles/render/nodes.h | 8 +- source/blender/editors/space_node/drawnode.c | 8 + source/blender/makesdna/DNA_node_types.h | 4 + source/blender/makesrna/intern/rna_nodetree.c | 17 ++ source/blender/nodes/NOD_static_types.h | 2 +- 18 files changed, 362 insertions(+), 66 deletions(-) create mode 100644 intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h create mode 100644 intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl delete mode 100644 intern/cycles/kernel/shaders/node_ward_bsdf.osl diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp index f50a952676f..915ef96a517 100644 --- a/intern/cycles/app/cycles_xml.cpp +++ b/intern/cycles/app/cycles_xml.cpp @@ -509,8 +509,10 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug else if(string_iequals(node.name(), "mapping")) { snode = new MappingNode(); } - else if(string_iequals(node.name(), "ward_bsdf")) { - snode = new WardBsdfNode(); + else if(string_iequals(node.name(), "anisotropic_bsdf")) { + AnisotropicBsdfNode *aniso = new AnisotropicBsdfNode(); + xml_read_enum(&aniso->distribution, AnisotropicBsdfNode::distribution_enum, node, "distribution"); + snode = aniso; } else if(string_iequals(node.name(), "diffuse_bsdf")) { snode = new DiffuseBsdfNode(); diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 3b783d36b1e..226e7a76dda 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -318,7 +318,21 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen node = new HoldoutNode(); } else if (b_node.is_a(&RNA_ShaderNodeBsdfAnisotropic)) { - node = new WardBsdfNode(); + BL::ShaderNodeBsdfAnisotropic b_aniso_node(b_node); + AnisotropicBsdfNode *aniso = new AnisotropicBsdfNode(); + + switch (b_aniso_node.distribution()) + { + case BL::ShaderNodeBsdfAnisotropic::distribution_ASHIKHMIN_SHIRLEY: + aniso->distribution = ustring("Ashikhmin-Shirley"); + break; + case BL::ShaderNodeBsdfAnisotropic::distribution_WARD: + default: + aniso->distribution = ustring("Ward"); + break; + } + + node = aniso; } else if (b_node.is_a(&RNA_ShaderNodeBsdfDiffuse)) { node = new DiffuseBsdfNode(); diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index d34a045e4f3..6b6fcb10ba8 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -61,6 +61,7 @@ set(SRC_CLOSURE_HEADERS closure/bsdf_transparent.h closure/bsdf_util.h closure/bsdf_ward.h + closure/bsdf_ashikhmin_shirley.h closure/bsdf_westin.h closure/bsdf_hair.h closure/bssrdf.h diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h index 24b54cd9d9e..371d0bfa8ea 100644 --- a/intern/cycles/kernel/closure/bsdf.h +++ b/intern/cycles/kernel/closure/bsdf.h @@ -25,6 +25,7 @@ #include "../closure/bsdf_transparent.h" #ifdef __ANISOTROPIC__ #include "../closure/bsdf_ward.h" +#include "../closure/bsdf_ashikhmin_shirley.h" #endif #include "../closure/bsdf_westin.h" #include "../closure/bsdf_toon.h" @@ -97,6 +98,10 @@ ccl_device int bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const Shader label = bsdf_ward_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_ASHIKHMIN_SHIRLEY_ID: + label = bsdf_ashikhmin_shirley_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 case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: label = bsdf_ashikhmin_velvet_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, @@ -189,6 +194,9 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade case CLOSURE_BSDF_WARD_ID: eval = bsdf_ward_eval_reflect(sc, sd->I, omega_in, pdf); break; + case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: + eval = bsdf_ashikhmin_shirley_eval_reflect(sc, sd->I, omega_in, pdf); + break; #endif case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: eval = bsdf_ashikhmin_velvet_eval_reflect(sc, sd->I, omega_in, pdf); @@ -256,6 +264,9 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade case CLOSURE_BSDF_WARD_ID: eval = bsdf_ward_eval_transmit(sc, sd->I, omega_in, pdf); break; + case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: + eval = bsdf_ashikhmin_shirley_eval_transmit(sc, sd->I, omega_in, pdf); + break; #endif case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: eval = bsdf_ashikhmin_velvet_eval_transmit(sc, sd->I, omega_in, pdf); @@ -341,6 +352,9 @@ ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness) case CLOSURE_BSDF_WARD_ID: bsdf_ward_blur(sc, roughness); break; + case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: + bsdf_ashikhmin_shirley_blur(sc, roughness); + break; #endif case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: bsdf_ashikhmin_velvet_blur(sc, roughness); diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h new file mode 100644 index 00000000000..ea5b610ae56 --- /dev/null +++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h @@ -0,0 +1,196 @@ +/* + * Copyright 2011-2013 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#ifndef __BSDF_ASHIKHMIN_SHIRLEY_H__ +#define __BSDF_ASHIKHMIN_SHIRLEY_H__ + +/* +ASHIKHMIN SHIRLEY BSDF + +Implementation of +Michael Ashikhmin and Peter Shirley: "An Anisotropic Phong BRDF Model" (2000) + +The Fresnel factor is missing to get a separable bsdf (intensity*color), as is +the case with all other microfacet-based BSDF implementations in Cycles. + +Other than that, the implementation directly follows the paper. +*/ + +CCL_NAMESPACE_BEGIN + + +ccl_device int bsdf_ashikhmin_shirley_setup(ShaderClosure *sc) +{ + sc->data0 = clamp(sc->data0, 1e-4f, 1.0f); /* store roughness. could already convert to exponent to save some cycles in eval, */ + sc->data1 = clamp(sc->data1, 1e-4f, 1.0f); /* but this is more consistent with other bsdfs and shader_blur. */ + + sc->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID; + return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_GLOSSY; +} + +ccl_device void bsdf_ashikhmin_shirley_blur(ShaderClosure *sc, float roughness) +{ + sc->data0 = fmaxf(roughness, sc->data0); /* clamp roughness */ + sc->data1 = fmaxf(roughness, sc->data1); +} + +ccl_device_inline float bsdf_ashikhmin_shirley_roughness_to_exponent(float roughness) +{ + return 2.0f / (roughness*roughness) - 2.0f; +} + +ccl_device float3 bsdf_ashikhmin_shirley_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +{ + float3 N = sc->N; + float3 T = sc->T; + + float NdotI = dot(N, I); /* in Cycles/OSL convention I is omega_out */ + float NdotO = dot(N, omega_in); /* and consequently we use for O omaga_in ;) */ + + float out = 0.0f; + + if (NdotI > 0.0f && NdotO > 0.0f) { + NdotI = fmaxf(NdotI, 1e-6f); + NdotO = fmaxf(NdotO, 1e-6f); + float3 H = normalize(omega_in + I); + float HdotI = fmaxf(dot(H, I), 1e-6f); + float HdotN = fmaxf(dot(H, N), 1e-6f); + + float pump = 1.0f / fmaxf(1e-6f, (HdotI*fmaxf(NdotO, NdotI))); /* pump from original paper (first derivative disc., but cancels the HdotI in the pdf nicely) */ + /*float pump = 1.0f / fmaxf(1e-4f, ((NdotO + NdotI) * (NdotO*NdotI))); */ /* pump from d-brdf paper */ + + float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(sc->data0); + float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(sc->data1); + + if (n_x == n_y) { /* => isotropic case */ + float e = n_x; + float lobe = powf(HdotN, e); + float norm = (n_x + 1.0f) / (8.0f * M_PI_F); + + out = NdotO * norm * lobe * pump; + *pdf = norm * lobe / HdotI; /* this is p_h / 4(H.I) (conversion from 'wh measure' to 'wi measure', eq. 8 in paper) */ + } + else { /* => ANisotropic case */ + float3 X, Y; + make_orthonormals_tangent(N, T, &X, &Y); + + float HdotX = dot(H, X); + float HdotY = dot(H, Y); + float e = (n_x * HdotX*HdotX + n_y * HdotY*HdotY) / (1.0f - HdotN*HdotN); + float lobe = powf(HdotN, e); + float norm = sqrtf((n_x + 1.0f)*(n_y + 1.0f)) / (8.0f * M_PI_F); + + out = NdotO * norm * lobe * pump; + *pdf = norm * lobe / HdotI; + } + } + + return make_float3(out, out, out); +} + +ccl_device float3 bsdf_ashikhmin_shirley_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +{ + return make_float3(0.0f, 0.0f, 0.0f); +} + +ccl_device_inline void bsdf_ashikhmin_shirley_sample_first_quadrant(float n_x, float n_y, float randu, float randv, float *phi, float *cos_theta) +{ + *phi = atanf(sqrtf((n_x + 1.0f) / (n_y + 1.0f)) * tanf(M_PI_2_F * randu)); + float cos_phi = cosf(*phi); + float sin_phi = sinf(*phi); + *cos_theta = powf(randv, 1.0f / (n_x * cos_phi*cos_phi + n_y * sin_phi*sin_phi + 1.0f)); +} + +ccl_device int bsdf_ashikhmin_shirley_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) +{ + float3 N = sc->N; + float3 T = sc->T; + + float NdotI = dot(N, I); + if (NdotI > 0.0f) { + + float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(sc->data0); + float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(sc->data1); + + /* get x,y basis on the surface for anisotropy */ + float3 X, Y; + make_orthonormals_tangent(N, T, &X, &Y); + + /* sample spherical coords for h in tangent space */ + float phi; + float cos_theta; + if (n_x == n_y) { /* => simple isotropic sampling */ + phi = M_2PI_F * randu; + cos_theta = powf(randv, 1.0f / (n_x + 1.0f)); + } + else { /* => more complex anisotropic sampling */ + if (randu < 0.25f) { /* first quadrant */ + float remapped_randu = 4.0f * randu; + bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, remapped_randu, randv, &phi, &cos_theta); + } + else if (randu < 0.5f) { /* second quadrant */ + float remapped_randu = 4.0f * (.5f - randu); + bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, remapped_randu, randv, &phi, &cos_theta); + phi = M_PI_F - phi; + } + else if (randu < 0.75f) { /* third quadrant */ + float remapped_randu = 4.0f * (randu - 0.5f); + bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, remapped_randu, randv, &phi, &cos_theta); + phi = M_PI_F + phi; + } + else { /* fourth quadrant */ + float remapped_randu = 4.0f * (1.0f - randu); + bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, remapped_randu, randv, &phi, &cos_theta); + phi = 2.0f * M_PI_F - phi; + } + } + + /* get half vector in tangent space */ + float sin_theta = sqrtf(fmaxf(0.0f, 1.0f - cos_theta*cos_theta)); + float cos_phi = cosf(phi); + float sin_phi = sinf(phi); /* no sqrt(1-cos^2) here b/c it causes artifacts */ + float3 h = make_float3( + sin_theta * cos_phi, + sin_theta * sin_phi, + cos_theta + ); + + /* half vector to world space */ + float3 H = h.x*X + h.y*Y + h.z*N; + float HdotI = dot(H, I); + if (HdotI < 0.0f) H = -H; + + /* reflect I on H to get omega_in */ + *omega_in = -I + (2.0f * HdotI) * H; + + /* leave the rest to eval_reflect */ + /* (could maybe optimize a few things by manual inlining, but I doubt it would make much difference) */ + *eval = bsdf_ashikhmin_shirley_eval_reflect(sc, I, *omega_in, pdf); + +#ifdef __RAY_DIFFERENTIALS__ + /* just do the reflection thing for now */ + *domega_in_dx = (2.0f * dot(N, dIdx)) * N - dIdx; + *domega_in_dy = (2.0f * dot(N, dIdy)) * N - dIdy; +#endif + } + + return LABEL_REFLECT | LABEL_GLOSSY; +} + + +CCL_NAMESPACE_END + +#endif /* __BSDF_ASHIKHMIN_SHIRLEY_H__ */ diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp index a96c0e2b1fb..9a1819ca116 100644 --- a/intern/cycles/kernel/osl/osl_closures.cpp +++ b/intern/cycles/kernel/osl/osl_closures.cpp @@ -52,6 +52,7 @@ #include "closure/bsdf_refraction.h" #include "closure/bsdf_transparent.h" #include "closure/bsdf_ward.h" +#include "closure/bsdf_ashikhmin_shirley.h" #include "closure/bsdf_westin.h" #include "closure/bsdf_toon.h" #include "closure/bsdf_hair.h" @@ -110,6 +111,13 @@ BSDF_CLOSURE_CLASS_BEGIN(Ward, ward, ward, LABEL_GLOSSY) CLOSURE_FLOAT_PARAM(WardClosure, sc.data1), BSDF_CLOSURE_CLASS_END(Ward, ward) +BSDF_CLOSURE_CLASS_BEGIN(AshikhminShirley, ashikhmin_shirley, ashikhmin_shirley, LABEL_GLOSSY) + CLOSURE_FLOAT3_PARAM(AshikhminShirleyClosure, sc.N), + CLOSURE_FLOAT3_PARAM(AshikhminShirleyClosure, sc.T), + CLOSURE_FLOAT_PARAM(AshikhminShirleyClosure, sc.data0), + CLOSURE_FLOAT_PARAM(AshikhminShirleyClosure, sc.data1), +BSDF_CLOSURE_CLASS_END(AshikhminShirley, ashikhmin_shirley) + BSDF_CLOSURE_CLASS_BEGIN(DiffuseToon, diffuse_toon, diffuse_toon, LABEL_DIFFUSE) CLOSURE_FLOAT3_PARAM(DiffuseToonClosure, sc.N), CLOSURE_FLOAT_PARAM(DiffuseToonClosure, sc.data0), @@ -218,6 +226,8 @@ void OSLShader::register_closures(OSLShadingSystem *ss_) bsdf_microfacet_beckmann_refraction_params(), bsdf_microfacet_beckmann_refraction_prepare); register_closure(ss, "ward", id++, bsdf_ward_params(), bsdf_ward_prepare); + register_closure(ss, "ashikhmin_shirley", id++, + bsdf_ashikhmin_shirley_params(), bsdf_ashikhmin_shirley_prepare); register_closure(ss, "ashikhmin_velvet", id++, bsdf_ashikhmin_velvet_params(), bsdf_ashikhmin_velvet_prepare); register_closure(ss, "diffuse_toon", id++, diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt index b164c2a03f7..0b735ede701 100644 --- a/intern/cycles/kernel/shaders/CMakeLists.txt +++ b/intern/cycles/kernel/shaders/CMakeLists.txt @@ -4,6 +4,7 @@ set(SRC_OSL node_add_closure.osl node_ambient_occlusion.osl + node_anisotropic_bsdf.osl node_attribute.osl node_background.osl node_brick_texture.osl @@ -73,7 +74,6 @@ set(SRC_OSL node_vector_transform.osl node_velvet_bsdf.osl node_voronoi_texture.osl - node_ward_bsdf.osl node_wavelength.osl node_blackbody.osl node_wave_texture.osl diff --git a/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl b/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl new file mode 100644 index 00000000000..3ecf5b46bef --- /dev/null +++ b/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl @@ -0,0 +1,53 @@ +/* + * Copyright 2011-2013 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#include "stdosl.h" + +shader node_anisotropic_bsdf( + color Color = 0.0, + string distribution = "Ward", + float Roughness = 0.0, + float Anisotropy = 0.0, + float Rotation = 0.0, + normal Normal = N, + normal Tangent = normalize(dPdu), + output closure color BSDF = 0) +{ + /* rotate tangent around normal */ + vector T = Tangent; + + if (Rotation != 0.0) + T = rotate(T, Rotation * M_2PI, point(0.0, 0.0, 0.0), Normal); + + /* compute roughness */ + float RoughnessU, RoughnessV; + float aniso = clamp(Anisotropy, -0.99, 0.99); + + if (aniso < 0.0) { + RoughnessU = Roughness / (1.0 + aniso); + RoughnessV = Roughness * (1.0 + aniso); + } + else { + RoughnessU = Roughness * (1.0 - aniso); + RoughnessV = Roughness / (1.0 - aniso); + } + + if (distribution == "Ashikhmin-Shirley") + BSDF = Color * ashikhmin_shirley(Normal, T, RoughnessU, RoughnessV); + else + BSDF = Color * ward(Normal, T, RoughnessU, RoughnessV); +} + diff --git a/intern/cycles/kernel/shaders/node_ward_bsdf.osl b/intern/cycles/kernel/shaders/node_ward_bsdf.osl deleted file mode 100644 index 2d360d594f2..00000000000 --- a/intern/cycles/kernel/shaders/node_ward_bsdf.osl +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2011-2013 Blender Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -#include "stdosl.h" - -shader node_ward_bsdf( - color Color = 0.0, - float Roughness = 0.0, - float Anisotropy = 0.0, - float Rotation = 0.0, - normal Normal = N, - normal Tangent = normalize(dPdu), - output closure color BSDF = 0) -{ - /* rotate tangent around normal */ - vector T = Tangent; - - if (Rotation != 0.0) - T = rotate(T, Rotation * M_2PI, point(0.0, 0.0, 0.0), Normal); - - /* compute roughness */ - float RoughnessU, RoughnessV; - float aniso = clamp(Anisotropy, -0.99, 0.99); - - if (aniso < 0.0) { - RoughnessU = Roughness / (1.0 + aniso); - RoughnessV = Roughness * (1.0 + aniso); - } - else { - RoughnessU = Roughness * (1.0 - aniso); - RoughnessV = Roughness / (1.0 - aniso); - } - - BSDF = Color * ward(Normal, T, RoughnessU, RoughnessV); -} - diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h index 6f824ea8ebd..20ee4a3df32 100644 --- a/intern/cycles/kernel/shaders/stdosl.h +++ b/intern/cycles/kernel/shaders/stdosl.h @@ -486,6 +486,7 @@ 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 ashikhmin_shirley(normal N, vector T,float ax, float ay) BUILTIN; closure color ward(normal N, vector T,float ax, float ay) BUILTIN; closure color ashikhmin_velvet(normal N, float sigma) BUILTIN; closure color emission() BUILTIN; diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h index a7982c64c49..d68b9371061 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -269,7 +269,8 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * break; } - case CLOSURE_BSDF_WARD_ID: { + case CLOSURE_BSDF_WARD_ID: + case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: { #ifdef __CAUSTICS_TRICKS__ if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE)) break; @@ -301,7 +302,11 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * sc->data1 = roughness/(1.0f - anisotropy); } - sd->flag |= bsdf_ward_setup(sc); + if (type == CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID) + sd->flag |= bsdf_ashikhmin_shirley_setup(sc); + else + sd->flag |= bsdf_ward_setup(sc); + #else sd->flag |= bsdf_diffuse_setup(sc); #endif diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 20c799e1805..87c56b3ea82 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -358,6 +358,7 @@ typedef enum ClosureType { CLOSURE_BSDF_MICROFACET_GGX_ID, CLOSURE_BSDF_MICROFACET_BECKMANN_ID, CLOSURE_BSDF_WARD_ID, + CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID, CLOSURE_BSDF_ASHIKHMIN_VELVET_ID, CLOSURE_BSDF_WESTIN_BACKSCATTER_ID, CLOSURE_BSDF_PHONG_RAMP_ID, @@ -403,7 +404,7 @@ typedef enum ClosureType { #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_BSDF_ANISOTROPIC(type) (type == CLOSURE_BSDF_WARD_ID) +#define CLOSURE_IS_BSDF_ANISOTROPIC(type) (type >= CLOSURE_BSDF_WARD_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID) #define CLOSURE_IS_BSDF_OR_BSSRDF(type) (type <= CLOSURE_BSSRDF_GAUSSIAN_ID) #define CLOSURE_IS_BSSRDF(type) (type >= CLOSURE_BSSRDF_CUBIC_ID && type <= CLOSURE_BSSRDF_GAUSSIAN_ID) #define CLOSURE_IS_VOLUME(type) (type >= CLOSURE_VOLUME_ID && type <= CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID) diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index a38de8a5cec..8976f958b58 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1583,11 +1583,23 @@ void BsdfNode::compile(OSLCompiler& compiler) assert(0); } -/* Ward BSDF Closure */ +/* Anisotropic BSDF Closure */ -WardBsdfNode::WardBsdfNode() +static ShaderEnum anisotropic_distribution_init() { - closure = CLOSURE_BSDF_WARD_ID; + ShaderEnum enm; + + enm.insert("Ward", CLOSURE_BSDF_WARD_ID); + enm.insert("Ashikhmin-Shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID); + + return enm; +} + +ShaderEnum AnisotropicBsdfNode::distribution_enum = anisotropic_distribution_init(); + +AnisotropicBsdfNode::AnisotropicBsdfNode() +{ + distribution = ustring("Ward"); add_input("Tangent", SHADER_SOCKET_VECTOR, ShaderInput::TANGENT); @@ -1596,7 +1608,7 @@ WardBsdfNode::WardBsdfNode() add_input("Rotation", SHADER_SOCKET_FLOAT, 0.0f); } -void WardBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes) +void AnisotropicBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes) { if(shader->has_surface) { ShaderInput *tangent_in = input("Tangent"); @@ -1608,14 +1620,17 @@ void WardBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes) ShaderNode::attributes(shader, attributes); } -void WardBsdfNode::compile(SVMCompiler& compiler) +void AnisotropicBsdfNode::compile(SVMCompiler& compiler) { + closure = (ClosureType)distribution_enum[distribution]; + BsdfNode::compile(compiler, input("Roughness"), input("Anisotropy"), input("Rotation")); } -void WardBsdfNode::compile(OSLCompiler& compiler) +void AnisotropicBsdfNode::compile(OSLCompiler& compiler) { - compiler.add(this, "node_ward_bsdf"); + compiler.parameter("distribution", distribution); + compiler.add(this, "node_anisotropic_bsdf"); } /* Glossy BSDF Closure */ diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index cf89bdadaa2..31b6f4e50c4 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -218,9 +218,13 @@ public: bool scattering; }; -class WardBsdfNode : public BsdfNode { +class AnisotropicBsdfNode : public BsdfNode { public: - SHADER_NODE_CLASS(WardBsdfNode) + SHADER_NODE_CLASS(AnisotropicBsdfNode) + + ustring distribution; + static ShaderEnum distribution_enum; + void attributes(Shader *shader, AttributeRequestSet *attributes); }; diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 953777ff329..4e709046f45 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -930,6 +930,11 @@ static void node_shader_buts_glossy(uiLayout *layout, bContext *UNUSED(C), Point uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE); } +static void node_shader_buts_anisotropic(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE); +} + static void node_shader_buts_subsurface(uiLayout *layout, bContext *C, PointerRNA *ptr) { /* SSS does not work on GPU yet */ @@ -1096,6 +1101,9 @@ static void node_shader_set_butfunc(bNodeType *ntype) case SH_NODE_BSDF_REFRACTION: ntype->draw_buttons = node_shader_buts_glossy; break; + case SH_NODE_BSDF_ANISOTROPIC: + ntype->draw_buttons = node_shader_buts_anisotropic; + break; case SH_NODE_SUBSURFACE_SCATTERING: ntype->draw_buttons = node_shader_buts_subsurface; break; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index e13d53934cb..2241803610c 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -873,6 +873,10 @@ typedef struct NodeShaderUVMap { #define CMP_NODE_CHANNEL_MATTE_CS_YUV 3 #define CMP_NODE_CHANNEL_MATTE_CS_YCC 4 +/* anisotropic distributions */ +#define SHD_ANISOTROPIC_WARD 0 +#define SHD_ANISOTROPIC_ASHIKHMIN_SHIRLEY 1 + /* glossy distributions */ #define SHD_GLOSSY_BECKMANN 0 #define SHD_GLOSSY_SHARP 1 diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index c39d3826d8b..b1a2f12d781 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -2952,6 +2952,12 @@ static EnumPropertyItem node_glossy_items[] = { {0, NULL, 0, NULL, NULL} }; +static EnumPropertyItem node_anisotropic_items[] = { + {SHD_ANISOTROPIC_WARD, "WARD", 0, "Ward", ""}, + {SHD_ANISOTROPIC_ASHIKHMIN_SHIRLEY, "ASHIKHMIN_SHIRLEY", 0, "Ashikhmin-Shirley", ""}, + {0, NULL, 0, NULL, NULL} +}; + static EnumPropertyItem node_toon_items[] = { {SHD_TOON_DIFFUSE, "DIFFUSE", 0, "Diffuse", ""}, {SHD_TOON_GLOSSY, "GLOSSY", 0, "Glossy", ""}, @@ -3699,6 +3705,17 @@ static void def_glossy(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } +static void def_anisotropic(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "distribution", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, node_anisotropic_items); + RNA_def_property_ui_text(prop, "Distribution", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); +} + static void def_toon(StructRNA *srna) { PropertyRNA *prop; diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 3e5de09ff6c..08dffd0ac92 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -77,7 +77,7 @@ DefNode( ShaderNode, SH_NODE_ATTRIBUTE, def_sh_attribute, "AT DefNode( ShaderNode, SH_NODE_AMBIENT_OCCLUSION, 0, "AMBIENT_OCCLUSION", AmbientOcclusion, "Ambient Occlusion", "" ) DefNode( ShaderNode, SH_NODE_BACKGROUND, 0, "BACKGROUND", Background, "Background", "" ) DefNode( ShaderNode, SH_NODE_HOLDOUT, 0, "HOLDOUT", Holdout, "Holdout", "" ) -DefNode( ShaderNode, SH_NODE_BSDF_ANISOTROPIC, 0, "BSDF_ANISOTROPIC", BsdfAnisotropic, "Anisotropic BSDF", "" ) +DefNode( ShaderNode, SH_NODE_BSDF_ANISOTROPIC, def_anisotropic, "BSDF_ANISOTROPIC", BsdfAnisotropic, "Anisotropic BSDF", "" ) DefNode( ShaderNode, SH_NODE_BSDF_DIFFUSE, 0, "BSDF_DIFFUSE", BsdfDiffuse, "Diffuse BSDF", "" ) DefNode( ShaderNode, SH_NODE_BSDF_GLOSSY, def_glossy, "BSDF_GLOSSY", BsdfGlossy, "Glossy BSDF", "" ) DefNode( ShaderNode, SH_NODE_BSDF_GLASS, def_glossy, "BSDF_GLASS", BsdfGlass, "Glass BSDF", "" ) -- cgit v1.2.3