diff options
author | Karsten Schwenk <macnihilist@gmx.net> | 2014-06-08 14:16:28 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2014-06-14 15:49:57 +0400 |
commit | 8ce1090d4e8160165281be4b0827dbc1ba28dc8a (patch) | |
tree | e65ed8a8bcebab84c50da6a286fa845c6a8ae92e /intern | |
parent | f5cb0cf1a50350e32b6fec5056f23a20606c7ea0 (diff) |
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
Diffstat (limited to 'intern')
-rw-r--r-- | intern/cycles/app/cycles_xml.cpp | 6 | ||||
-rw-r--r-- | intern/cycles/blender/blender_shader.cpp | 16 | ||||
-rw-r--r-- | intern/cycles/kernel/CMakeLists.txt | 1 | ||||
-rw-r--r-- | intern/cycles/kernel/closure/bsdf.h | 14 | ||||
-rw-r--r-- | intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h | 196 | ||||
-rw-r--r-- | intern/cycles/kernel/osl/osl_closures.cpp | 10 | ||||
-rw-r--r-- | intern/cycles/kernel/shaders/CMakeLists.txt | 2 | ||||
-rw-r--r-- | intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl (renamed from intern/cycles/kernel/shaders/node_ward_bsdf.osl) | 8 | ||||
-rw-r--r-- | intern/cycles/kernel/shaders/stdosl.h | 1 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_closure.h | 9 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_types.h | 3 | ||||
-rw-r--r-- | intern/cycles/render/nodes.cpp | 29 | ||||
-rw-r--r-- | intern/cycles/render/nodes.h | 8 |
13 files changed, 285 insertions, 18 deletions
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_ward_bsdf.osl b/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl index 2d360d594f2..3ecf5b46bef 100644 --- a/intern/cycles/kernel/shaders/node_ward_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl @@ -16,8 +16,9 @@ #include "stdosl.h" -shader node_ward_bsdf( +shader node_anisotropic_bsdf( color Color = 0.0, + string distribution = "Ward", float Roughness = 0.0, float Anisotropy = 0.0, float Rotation = 0.0, @@ -44,6 +45,9 @@ shader node_ward_bsdf( RoughnessV = Roughness / (1.0 - aniso); } - BSDF = Color * ward(Normal, T, RoughnessU, RoughnessV); + 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/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); }; |