Cycles: glossy and anisotropic BSDF changes

* Anisotropic BSDF now supports GGX and Beckmann distributions, Ward has been
  removed because other distributions are superior.
* GGX is now the default distribution for all glossy and anisotropic nodes,
  since it looks good, has low noise and is fast to evaluate.
* Ashikhmin-Shirley is now available in the Glossy BSDF.
This commit is contained in:
2014-06-08 12:46:12 +02:00
parent ceb68e809e
commit b12151eceb
20 changed files with 149 additions and 274 deletions

View File

@@ -323,13 +323,18 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
switch (b_aniso_node.distribution())
{
case BL::ShaderNodeBsdfAnisotropic::distribution_SHARP:
aniso->distribution = ustring("Sharp");
break;
case BL::ShaderNodeBsdfAnisotropic::distribution_BECKMANN:
aniso->distribution = ustring("Beckmann");
break;
case BL::ShaderNodeBsdfAnisotropic::distribution_GGX:
aniso->distribution = ustring("GGX");
break;
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;
@@ -367,6 +372,9 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
case BL::ShaderNodeBsdfGlossy::distribution_GGX:
glossy->distribution = ustring("GGX");
break;
case BL::ShaderNodeBsdfGlossy::distribution_ASHIKHMIN_SHIRLEY:
glossy->distribution = ustring("Ashikhmin-Shirley");
break;
}
node = glossy;
}

View File

@@ -60,7 +60,6 @@ set(SRC_CLOSURE_HEADERS
closure/bsdf_toon.h
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

View File

@@ -24,7 +24,6 @@
#include "../closure/bsdf_refraction.h"
#include "../closure/bsdf_transparent.h"
#ifdef __ANISOTROPIC__
#include "../closure/bsdf_ward.h"
#include "../closure/bsdf_ashikhmin_shirley.h"
#endif
#include "../closure/bsdf_westin.h"
@@ -84,21 +83,20 @@ ccl_device int bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const Shader
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
label = bsdf_microfacet_ggx_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_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
label = bsdf_microfacet_beckmann_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;
#ifdef __ANISOTROPIC__
case CLOSURE_BSDF_WARD_ID:
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:
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_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;
@@ -183,18 +181,18 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade
eval = bsdf_transparent_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
eval = bsdf_microfacet_ggx_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf);
break;
#ifdef __ANISOTROPIC__
case CLOSURE_BSDF_WARD_ID:
eval = bsdf_ward_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
eval = bsdf_ashikhmin_shirley_eval_reflect(sc, sd->I, omega_in, pdf);
break;
#endif
@@ -253,18 +251,18 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade
eval = bsdf_transparent_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
eval = bsdf_microfacet_ggx_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf);
break;
#ifdef __ANISOTROPIC__
case CLOSURE_BSDF_WARD_ID:
eval = bsdf_ward_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
eval = bsdf_ashikhmin_shirley_eval_transmit(sc, sd->I, omega_in, pdf);
break;
#endif
@@ -341,18 +339,18 @@ ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness)
bsdf_transparent_blur(sc, roughness);
break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
bsdf_microfacet_ggx_blur(sc, roughness);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
bsdf_microfacet_beckmann_blur(sc, roughness);
break;
#ifdef __ANISOTROPIC__
case CLOSURE_BSDF_WARD_ID:
bsdf_ward_blur(sc, roughness);
break;
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
bsdf_ashikhmin_shirley_blur(sc, roughness);
break;
#endif

View File

@@ -31,16 +31,28 @@ 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. */
/* store roughness. could already convert to exponent to save some cycles
* in eval, but this is more consistent with other bsdfs and shader_blur. */
sc->data0 = clamp(sc->data0, 1e-4f, 1.0f);
sc->data1 = sc->data0;
sc->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID;
return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_GLOSSY;
}
ccl_device int bsdf_ashikhmin_shirley_aniso_setup(ShaderClosure *sc)
{
/* store roughness. could already convert to exponent to save some cycles
* in eval, but this is more consistent with other bsdfs and shader_blur. */
sc->data0 = clamp(sc->data0, 1e-4f, 1.0f);
sc->data1 = clamp(sc->data1, 1e-4f, 1.0f);
sc->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_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 */
@@ -55,7 +67,6 @@ ccl_device_inline float bsdf_ashikhmin_shirley_roughness_to_exponent(float rough
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 ;) */
@@ -85,7 +96,7 @@ ccl_device float3 bsdf_ashikhmin_shirley_eval_reflect(const ShaderClosure *sc, c
}
else { /* => ANisotropic case */
float3 X, Y;
make_orthonormals_tangent(N, T, &X, &Y);
make_orthonormals_tangent(N, sc->T, &X, &Y);
float HdotX = dot(H, X);
float HdotY = dot(H, Y);
@@ -117,7 +128,6 @@ ccl_device_inline void bsdf_ashikhmin_shirley_sample_first_quadrant(float n_x, f
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) {
@@ -127,7 +137,11 @@ ccl_device int bsdf_ashikhmin_shirley_sample(const ShaderClosure *sc, float3 Ng,
/* get x,y basis on the surface for anisotropy */
float3 X, Y;
make_orthonormals_tangent(N, T, &X, &Y);
if(n_x == n_y)
make_orthonormals(N, &X, &Y);
else
make_orthonormals_tangent(N, sc->T, &X, &Y);
/* sample spherical coords for h in tangent space */
float phi;

View File

@@ -365,7 +365,7 @@ ccl_device int bsdf_microfacet_ggx_aniso_setup(ShaderClosure *sc)
sc->data0 = clamp(sc->data0, 0.0f, 1.0f); /* alpha_x */
sc->data1 = clamp(sc->data1, 0.0f, 1.0f); /* alpha_y */
sc->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
sc->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
}
@@ -713,7 +713,7 @@ ccl_device int bsdf_microfacet_beckmann_aniso_setup(ShaderClosure *sc)
sc->data0 = clamp(sc->data0, 0.0f, 1.0f); /* alpha_x */
sc->data1 = clamp(sc->data1, 0.0f, 1.0f); /* alpha_y */
sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
}

View File

@@ -1,189 +0,0 @@
/*
* 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_WARD_H__
#define __BSDF_WARD_H__
CCL_NAMESPACE_BEGIN
/* WARD */
ccl_device int bsdf_ward_setup(ShaderClosure *sc)
{
sc->data0 = clamp(sc->data0, 1e-4f, 1.0f); /* m_ax */
sc->data1 = clamp(sc->data1, 1e-4f, 1.0f); /* m_ay */
sc->type = CLOSURE_BSDF_WARD_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
}
ccl_device void bsdf_ward_blur(ShaderClosure *sc, float roughness)
{
sc->data0 = fmaxf(roughness, sc->data0); /* m_ax */
sc->data1 = fmaxf(roughness, sc->data1); /* m_ay */
}
ccl_device float3 bsdf_ward_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float m_ax = sc->data0;
float m_ay = sc->data1;
float3 N = sc->N;
float3 T = sc->T;
float cosNO = dot(N, I);
float cosNI = dot(N, omega_in);
if(cosNI > 0.0f && cosNO > 0.0f) {
cosNO = max(cosNO, 1e-4f);
cosNI = max(cosNI, 1e-4f);
// get half vector and get x,y basis on the surface for anisotropy
float3 H = normalize(omega_in + I); // normalize needed for pdf
float3 X, Y;
make_orthonormals_tangent(N, T, &X, &Y);
// eq. 4
float dotx = dot(H, X) / m_ax;
float doty = dot(H, Y) / m_ay;
float dotn = dot(H, N);
float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn);
float denom = (M_4PI_F * m_ax * m_ay * sqrtf(cosNO * cosNI));
float exp_val = expf(-exp_arg);
float out = cosNI * exp_val / denom;
float oh = dot(H, I);
denom = M_4PI_F * m_ax * m_ay * oh * dotn * dotn * dotn;
*pdf = exp_val / denom;
return make_float3 (out, out, out);
}
return make_float3 (0, 0, 0);
}
ccl_device float3 bsdf_ward_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 int bsdf_ward_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)
{
float m_ax = sc->data0;
float m_ay = sc->data1;
float3 N = sc->N;
float3 T = sc->T;
float cosNO = dot(N, I);
if(cosNO > 0.0f) {
// get x,y basis on the surface for anisotropy
float3 X, Y;
make_orthonormals_tangent(N, T, &X, &Y);
// generate random angles for the half vector
// eq. 7 (taking care around discontinuities to keep
//ttoutput angle in the right quadrant)
// we take advantage of cos(atan(x)) == 1/sqrt(1+x^2)
//tttt 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(M_PI_2_F * val);
cosPhi = 1 / sqrtf(1 + tanPhi * tanPhi);
sinPhi = tanPhi * cosPhi;
}
else if(randu < 0.5f) {
float val = 1 - 4 * (0.5f - randu);
float tanPhi = alphaRatio * tanf(M_PI_2_F * val);
// phi = M_PI_F - 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(M_PI_2_F * val);
//phi = M_PI_F + phi;
cosPhi = -1 / sqrtf(1 + tanPhi * tanPhi);
sinPhi = tanPhi * cosPhi;
}
else {
float val = 1 - 4 * (1 - randu);
float tanPhi = alphaRatio * tanf(M_PI_2_F * val);
// phi = M_2PI_F - phi;
cosPhi = 1 / sqrtf(1 + tanPhi * tanPhi);
sinPhi = -tanPhi * cosPhi;
}
// eq. 6
// we take advantage of cos(atan(x)) == 1/sqrt(1+x^2)
//tttt 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);
float3 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 * N;
// generate the final sample
float oh = dot(h, I);
*omega_in = 2.0f * oh * h - I;
if(dot(Ng, *omega_in) > 0) {
float cosNI = dot(N, *omega_in);
if(cosNI > 0) {
cosNO = max(cosNO, 1e-4f);
cosNI = max(cosNI, 1e-4f);
// eq. 9
float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn);
float denom = M_4PI_F * m_ax * m_ay * oh * dotn * dotn * dotn;
*pdf = expf(-exp_arg) / denom;
// compiler will reuse expressions already computed
denom = (M_4PI_F * m_ax * m_ay * sqrtf(cosNO * cosNI));
float power = cosNI * expf(-exp_arg) / denom;
*eval = make_float3(power, power, power);
#ifdef __RAY_DIFFERENTIALS__
*domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
*domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy;
#endif
}
}
}
return LABEL_REFLECT|LABEL_GLOSSY;
}
CCL_NAMESPACE_END
#endif /* __BSDF_WARD_H__ */

View File

@@ -51,7 +51,6 @@
#include "closure/bsdf_reflection.h"
#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"
@@ -104,19 +103,12 @@ BSDF_CLOSURE_CLASS_BEGIN(AshikhminVelvet, ashikhmin_velvet, ashikhmin_velvet, LA
CLOSURE_FLOAT_PARAM(AshikhminVelvetClosure, sc.data0),
BSDF_CLOSURE_CLASS_END(AshikhminVelvet, ashikhmin_velvet)
BSDF_CLOSURE_CLASS_BEGIN(Ward, ward, ward, LABEL_GLOSSY)
CLOSURE_FLOAT3_PARAM(WardClosure, sc.N),
CLOSURE_FLOAT3_PARAM(WardClosure, sc.T),
CLOSURE_FLOAT_PARAM(WardClosure, sc.data0),
CLOSURE_FLOAT_PARAM(WardClosure, sc.data1),
BSDF_CLOSURE_CLASS_END(Ward, ward)
BSDF_CLOSURE_CLASS_BEGIN(AshikhminShirley, ashikhmin_shirley, ashikhmin_shirley, LABEL_GLOSSY)
BSDF_CLOSURE_CLASS_BEGIN(AshikhminShirley, ashikhmin_shirley_aniso, 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_END(AshikhminShirley, ashikhmin_shirley_aniso)
BSDF_CLOSURE_CLASS_BEGIN(DiffuseToon, diffuse_toon, diffuse_toon, LABEL_DIFFUSE)
CLOSURE_FLOAT3_PARAM(DiffuseToonClosure, sc.N),
@@ -135,11 +127,25 @@ BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGX, microfacet_ggx, microfacet_ggx, LABEL_GL
CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure, sc.data0),
BSDF_CLOSURE_CLASS_END(MicrofacetGGX, microfacet_ggx)
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXAniso, microfacet_ggx_aniso, microfacet_ggx, LABEL_GLOSSY)
CLOSURE_FLOAT3_PARAM(MicrofacetGGXAnisoClosure, sc.N),
CLOSURE_FLOAT3_PARAM(MicrofacetGGXAnisoClosure, sc.T),
CLOSURE_FLOAT_PARAM(MicrofacetGGXAnisoClosure, sc.data0),
CLOSURE_FLOAT_PARAM(MicrofacetGGXAnisoClosure, sc.data1),
BSDF_CLOSURE_CLASS_END(MicrofacetGGXAniso, microfacet_ggx_aniso)
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmann, microfacet_beckmann, microfacet_beckmann, LABEL_GLOSSY)
CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannClosure, sc.N),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure, sc.data0),
BSDF_CLOSURE_CLASS_END(MicrofacetBeckmann, microfacet_beckmann)
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannAniso, microfacet_beckmann_aniso, microfacet_beckmann, LABEL_GLOSSY)
CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannAnisoClosure, sc.N),
CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannAnisoClosure, sc.T),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannAnisoClosure, sc.data0),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannAnisoClosure, sc.data1),
BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannAniso, microfacet_beckmann_aniso)
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXRefraction, microfacet_ggx_refraction, microfacet_ggx, LABEL_GLOSSY)
CLOSURE_FLOAT3_PARAM(MicrofacetGGXRefractionClosure, sc.N),
CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, sc.data0),
@@ -218,16 +224,18 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
bsdf_transparent_params(), bsdf_transparent_prepare);
register_closure(ss, "microfacet_ggx", id++,
bsdf_microfacet_ggx_params(), bsdf_microfacet_ggx_prepare);
register_closure(ss, "microfacet_ggx_aniso", id++,
bsdf_microfacet_ggx_aniso_params(), bsdf_microfacet_ggx_aniso_prepare);
register_closure(ss, "microfacet_ggx_refraction", id++,
bsdf_microfacet_ggx_refraction_params(), bsdf_microfacet_ggx_refraction_prepare);
register_closure(ss, "microfacet_beckmann", id++,
bsdf_microfacet_beckmann_params(), bsdf_microfacet_beckmann_prepare);
register_closure(ss, "microfacet_beckmann_aniso", id++,
bsdf_microfacet_beckmann_aniso_params(), bsdf_microfacet_beckmann_aniso_prepare);
register_closure(ss, "microfacet_beckmann_refraction", id++,
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);
bsdf_ashikhmin_shirley_aniso_params(), bsdf_ashikhmin_shirley_aniso_prepare);
register_closure(ss, "ashikhmin_velvet", id++,
bsdf_ashikhmin_velvet_params(), bsdf_ashikhmin_velvet_prepare);
register_closure(ss, "diffuse_toon", id++,

View File

@@ -18,7 +18,7 @@
shader node_anisotropic_bsdf(
color Color = 0.0,
string distribution = "Ward",
string distribution = "GGX",
float Roughness = 0.0,
float Anisotropy = 0.0,
float Rotation = 0.0,
@@ -45,9 +45,13 @@ shader node_anisotropic_bsdf(
RoughnessV = Roughness / (1.0 - aniso);
}
if (distribution == "Ashikhmin-Shirley")
BSDF = Color * ashikhmin_shirley(Normal, T, RoughnessU, RoughnessV);
if (distribution == "Sharp")
BSDF = Color * reflection(Normal);
else if (distribution == "Beckmann")
BSDF = Color * microfacet_beckmann_aniso(Normal, T, RoughnessU, RoughnessV);
else if (distribution == "GGX")
BSDF = Color * microfacet_ggx_aniso(Normal, T, RoughnessU, RoughnessV);
else
BSDF = Color * ward(Normal, T, RoughnessU, RoughnessV);
BSDF = Color * ashikhmin_shirley(Normal, T, RoughnessU, RoughnessV);
}

View File

@@ -19,7 +19,7 @@
shader node_glossy_bsdf(
color Color = 0.8,
string distribution = "Beckmann",
string distribution = "GGX",
float Roughness = 0.2,
normal Normal = N,
output closure color BSDF = 0)
@@ -30,6 +30,8 @@ shader node_glossy_bsdf(
BSDF = Color * microfacet_beckmann(Normal, Roughness);
else if (distribution == "GGX")
BSDF = Color * microfacet_ggx(Normal, Roughness);
else
BSDF = Color * ashikhmin_shirley(Normal, vector(0, 0, 0), Roughness, Roughness);
}

View File

@@ -483,11 +483,12 @@ closure color reflection(normal N) BUILTIN;
closure color refraction(normal N, float eta) BUILTIN;
closure color transparent() BUILTIN;
closure color microfacet_ggx(normal N, float ag) BUILTIN;
closure color microfacet_ggx_aniso(normal N, vector T, float ax, float ay) 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_aniso(normal N, vector T, float ax, float ay) 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;
closure color background() BUILTIN;

View File

@@ -176,7 +176,8 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
}
case CLOSURE_BSDF_REFLECTION_ID:
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: {
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: {
#ifdef __CAUSTICS_TRICKS__
if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
break;
@@ -194,8 +195,10 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
sd->flag |= bsdf_reflection_setup(sc);
else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID)
sd->flag |= bsdf_microfacet_beckmann_setup(sc);
else
else if(type == CLOSURE_BSDF_MICROFACET_GGX_ID)
sd->flag |= bsdf_microfacet_ggx_setup(sc);
else
sd->flag |= bsdf_ashikhmin_shirley_setup(sc);
}
break;
@@ -279,8 +282,9 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
break;
}
case CLOSURE_BSDF_WARD_ID:
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: {
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID: {
#ifdef __CAUSTICS_TRICKS__
if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
break;
@@ -314,10 +318,12 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
sc->data2 = 0.0f;
if (type == CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID)
sd->flag |= bsdf_ashikhmin_shirley_setup(sc);
if (type == CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID)
sd->flag |= bsdf_microfacet_beckmann_aniso_setup(sc);
else if (type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID)
sd->flag |= bsdf_microfacet_ggx_aniso_setup(sc);
else
sd->flag |= bsdf_ward_setup(sc);
sd->flag |= bsdf_ashikhmin_shirley_aniso_setup(sc);
#else
sd->flag |= bsdf_diffuse_setup(sc);
#endif

View File

@@ -357,8 +357,10 @@ typedef enum ClosureType {
CLOSURE_BSDF_REFLECTION_ID,
CLOSURE_BSDF_MICROFACET_GGX_ID,
CLOSURE_BSDF_MICROFACET_BECKMANN_ID,
CLOSURE_BSDF_WARD_ID,
CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID,
CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID,
CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID,
CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID,
CLOSURE_BSDF_ASHIKHMIN_VELVET_ID,
CLOSURE_BSDF_WESTIN_BACKSCATTER_ID,
CLOSURE_BSDF_PHONG_RAMP_ID,
@@ -404,7 +406,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 && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID)
#define CLOSURE_IS_BSDF_ANISOTROPIC(type) (type >= CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_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)

View File

@@ -1585,21 +1585,23 @@ void BsdfNode::compile(OSLCompiler& compiler)
/* Anisotropic BSDF Closure */
static ShaderEnum anisotropic_distribution_init()
static ShaderEnum aniso_distribution_init()
{
ShaderEnum enm;
enm.insert("Ward", CLOSURE_BSDF_WARD_ID);
enm.insert("Ashikhmin-Shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID);
enm.insert("Sharp", CLOSURE_BSDF_REFLECTION_ID);
enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID);
enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID);
enm.insert("Ashikhmin-Shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID);
return enm;
}
ShaderEnum AnisotropicBsdfNode::distribution_enum = anisotropic_distribution_init();
ShaderEnum AnisotropicBsdfNode::distribution_enum = aniso_distribution_init();
AnisotropicBsdfNode::AnisotropicBsdfNode()
{
distribution = ustring("Ward");
distribution = ustring("GGX");
add_input("Tangent", SHADER_SOCKET_VECTOR, ShaderInput::TANGENT);
@@ -1642,6 +1644,7 @@ static ShaderEnum glossy_distribution_init()
enm.insert("Sharp", CLOSURE_BSDF_REFLECTION_ID);
enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ID);
enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ID);
enm.insert("Ashikhmin-Shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID);
return enm;
}
@@ -1650,7 +1653,7 @@ ShaderEnum GlossyBsdfNode::distribution_enum = glossy_distribution_init();
GlossyBsdfNode::GlossyBsdfNode()
{
distribution = ustring("Beckmann");
distribution = ustring("GGX");
add_input("Roughness", SHADER_SOCKET_FLOAT, 0.2f);
}

View File

@@ -873,14 +873,11 @@ 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
#define SHD_GLOSSY_GGX 2
#define SHD_GLOSSY_ASHIKHMIN_SHIRLEY 3
/* vector transform */
#define SHD_VECT_TRANSFORM_TYPE_VECTOR 0

View File

@@ -2949,12 +2949,14 @@ static EnumPropertyItem node_glossy_items[] = {
{SHD_GLOSSY_SHARP, "SHARP", 0, "Sharp", ""},
{SHD_GLOSSY_BECKMANN, "BECKMANN", 0, "Beckmann", ""},
{SHD_GLOSSY_GGX, "GGX", 0, "GGX", ""},
{SHD_GLOSSY_ASHIKHMIN_SHIRLEY, "ASHIKHMIN_SHIRLEY", 0, "Ashikhmin-Shirley", ""},
{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", ""},
static EnumPropertyItem node_glass_items[] = {
{SHD_GLOSSY_SHARP, "SHARP", 0, "Sharp", ""},
{SHD_GLOSSY_BECKMANN, "BECKMANN", 0, "Beckmann", ""},
{SHD_GLOSSY_GGX, "GGX", 0, "GGX", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -3705,13 +3707,13 @@ static void def_glossy(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_anisotropic(StructRNA *srna)
static void def_glass(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_enum_items(prop, node_glass_items);
RNA_def_property_ui_text(prop, "Distribution", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}

View File

@@ -77,11 +77,11 @@ 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, def_anisotropic, "BSDF_ANISOTROPIC", BsdfAnisotropic, "Anisotropic BSDF", "" )
DefNode( ShaderNode, SH_NODE_BSDF_ANISOTROPIC, def_glossy, "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", "" )
DefNode( ShaderNode, SH_NODE_BSDF_REFRACTION, def_glossy, "BSDF_REFRACTION", BsdfRefraction, "Refraction BSDF", "" )
DefNode( ShaderNode, SH_NODE_BSDF_GLASS, def_glass, "BSDF_GLASS", BsdfGlass, "Glass BSDF", "" )
DefNode( ShaderNode, SH_NODE_BSDF_REFRACTION, def_glass, "BSDF_REFRACTION", BsdfRefraction, "Refraction BSDF", "" )
DefNode( ShaderNode, SH_NODE_BSDF_TRANSLUCENT, 0, "BSDF_TRANSLUCENT", BsdfTranslucent, "Translucent BSDF", "" )
DefNode( ShaderNode, SH_NODE_BSDF_TRANSPARENT, 0, "BSDF_TRANSPARENT", BsdfTransparent, "Transparent BSDF", "" )
DefNode( ShaderNode, SH_NODE_BSDF_VELVET, 0, "BSDF_VELVET", BsdfVelvet, "Velvet BSDF", "" )

View File

@@ -44,6 +44,11 @@ static bNodeSocketTemplate sh_node_bsdf_anisotropic_out[] = {
{ -1, 0, "" }
};
static void node_shader_init_anisotropic(bNodeTree *UNUSED(ntree), bNode *node)
{
node->custom1 = SHD_GLOSSY_GGX;
}
static int node_shader_gpu_bsdf_anisotropic(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[3].link)
@@ -61,7 +66,7 @@ void register_node_type_sh_bsdf_anisotropic(void)
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bsdf_anisotropic_in, sh_node_bsdf_anisotropic_out);
node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
node_type_init(&ntype, NULL);
node_type_init(&ntype, node_shader_init_anisotropic);
node_type_storage(&ntype, "", NULL, NULL);
node_type_gpu(&ntype, node_shader_gpu_bsdf_anisotropic);

View File

@@ -42,6 +42,11 @@ static bNodeSocketTemplate sh_node_bsdf_glass_out[] = {
{ -1, 0, "" }
};
static void node_shader_init_glass(bNodeTree *UNUSED(ntree), bNode *node)
{
node->custom1 = SHD_GLOSSY_BECKMANN;
}
static int node_shader_gpu_bsdf_glass(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[3].link)
@@ -59,7 +64,7 @@ void register_node_type_sh_bsdf_glass(void)
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bsdf_glass_in, sh_node_bsdf_glass_out);
node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
node_type_init(&ntype, NULL);
node_type_init(&ntype, node_shader_init_glass);
node_type_storage(&ntype, "", NULL, NULL);
node_type_gpu(&ntype, node_shader_gpu_bsdf_glass);

View File

@@ -41,6 +41,11 @@ static bNodeSocketTemplate sh_node_bsdf_glossy_out[] = {
{ -1, 0, "" }
};
static void node_shader_init_glossy(bNodeTree *UNUSED(ntree), bNode *node)
{
node->custom1 = SHD_GLOSSY_GGX;
}
static int node_shader_gpu_bsdf_glossy(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[2].link)
@@ -58,7 +63,7 @@ void register_node_type_sh_bsdf_glossy(void)
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bsdf_glossy_in, sh_node_bsdf_glossy_out);
node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
node_type_init(&ntype, NULL);
node_type_init(&ntype, node_shader_init_glossy);
node_type_storage(&ntype, "", NULL, NULL);
node_type_gpu(&ntype, node_shader_gpu_bsdf_glossy);

View File

@@ -42,6 +42,11 @@ static bNodeSocketTemplate sh_node_bsdf_refraction_out[] = {
{ -1, 0, "" }
};
static void node_shader_init_refraction(bNodeTree *UNUSED(ntree), bNode *node)
{
node->custom1 = SHD_GLOSSY_BECKMANN;
}
static int node_shader_gpu_bsdf_refraction(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[3].link)
@@ -59,7 +64,7 @@ void register_node_type_sh_bsdf_refraction(void)
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bsdf_refraction_in, sh_node_bsdf_refraction_out);
node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
node_type_init(&ntype, NULL);
node_type_init(&ntype, node_shader_init_refraction);
node_type_storage(&ntype, "", NULL, NULL);
node_type_gpu(&ntype, node_shader_gpu_bsdf_refraction);