Fixed a bug in the Disney BSDF that caused specular reflections to be too

bright and diffuse is now reacting to the roughness again

- A normalization for the fresnel was missing which caused the specular
  reflections to become too bright for the single-scatter GGX
- The roughness value for the diffuse BSSRDF part has always been
  overwritten and thus always 0
- Also the performance for refractive materials with roughness=0.0 has
  been improved
This commit is contained in:
2016-09-16 08:47:56 +02:00
parent 7cb37d7119
commit 3cd5eb56cf
7 changed files with 196 additions and 135 deletions

View File

@@ -35,34 +35,39 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct DisneySpecularExtra {
float3 T, baseColor, cspec0;
bool alpha_x, alpha_y, rough_g, ior;
} DisneySpecularExtra;
typedef ccl_addr_space struct DisneySpecularBsdf {
SHADER_CLOSURE_BASE;
float specular, specularTint, roughness, metallic, anisotropic, alpha_x, alpha_y, rough_g;
float3 N, T;
float3 baseColor, cspec0;
float specular, specularTint, roughness, metallic, anisotropic;
float3 N;
DisneySpecularExtra *extra;
} DisneySpecularBsdf;
ccl_device int bsdf_disney_specular_setup(DisneySpecularBsdf *bsdf)
{
float m_cdlum = 0.3f * bsdf->baseColor.x + 0.6f * bsdf->baseColor.y + 0.1f * bsdf->baseColor.z; // luminance approx.
float m_cdlum = 0.3f * bsdf->extra->baseColor.x + 0.6f * bsdf->extra->baseColor.y + 0.1f * bsdf->extra->baseColor.z; // luminance approx.
float3 m_ctint = m_cdlum > 0.0f ? bsdf->baseColor / m_cdlum : make_float3(1.0f, 1.0f, 1.0f); // normalize lum. to isolate hue+sat
float3 m_ctint = m_cdlum > 0.0f ? bsdf->extra->baseColor / m_cdlum : make_float3(1.0f, 1.0f, 1.0f); // normalize lum. to isolate hue+sat
float3 tmp_col = make_float3(1.0f, 1.0f, 1.0f) * (1.0f - bsdf->specularTint) + m_ctint * bsdf->specularTint; // lerp(make_float3(1.0f, 1.0f, 1.0f), m_ctint, sc->data2/*specularTint*/);
bsdf->cspec0 = (bsdf->specular * 0.08f * tmp_col) * (1.0f - bsdf->metallic) + bsdf->baseColor * bsdf->metallic; // lerp(sc->data1/*specular*/ * 0.08f * tmp_col, sc->color0/*baseColor*/, sc->data0/*metallic*/);
bsdf->extra->cspec0 = (bsdf->specular * 0.08f * tmp_col) * (1.0f - bsdf->metallic) + bsdf->extra->baseColor * bsdf->metallic; // lerp(sc->data1/*specular*/ * 0.08f * tmp_col, sc->color0/*baseColor*/, sc->data0/*metallic*/);
float aspect = safe_sqrtf(1.0f - bsdf->anisotropic * 0.9f);
float r2 = sqr(bsdf->roughness);
/* ax */
bsdf->alpha_x = fmaxf(0.001f, r2 / aspect);
bsdf->extra->alpha_x = fmaxf(0.001f, r2 / aspect);
/* ay */
bsdf->alpha_y = fmaxf(0.001f, r2 * aspect);
bsdf->extra->alpha_y = fmaxf(0.001f, r2 * aspect);
/* rough_g */
bsdf->rough_g = sqr(bsdf->roughness * 0.5f + 0.5f);
bsdf->extra->rough_g = sqr(bsdf->roughness * 0.5f + 0.5f);
bsdf->type = CLOSURE_BSDF_DISNEY_SPECULAR_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
@@ -75,7 +80,7 @@ ccl_device float3 bsdf_disney_specular_eval_reflect(const ShaderClosure *sc, con
float3 N = bsdf->N;
if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f)
if (bsdf->extra->alpha_x*bsdf->extra->alpha_y <= 1e-7f)
return make_float3(0.0f, 0.0f, 0.0f);
float cosNO = dot(N, I);
@@ -84,10 +89,10 @@ ccl_device float3 bsdf_disney_specular_eval_reflect(const ShaderClosure *sc, con
if (cosNI > 0 && cosNO > 0) {
/* get half vector */
float3 m = normalize(omega_in + I);
float alpha2 = bsdf->alpha_x * bsdf->alpha_y;
float alpha2 = bsdf->extra->alpha_x * bsdf->extra->alpha_y;
float D, G1o, G1i;
if (bsdf->alpha_x == bsdf->alpha_y) {
if (bsdf->extra->alpha_x == bsdf->extra->alpha_y) {
/* isotropic
* eq. 20: (F*G*D)/(4*in*on)
* eq. 33: first we calculate D(m) */
@@ -104,12 +109,12 @@ ccl_device float3 bsdf_disney_specular_eval_reflect(const ShaderClosure *sc, con
else {
/* anisotropic */
float3 X, Y, Z = N;
make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
make_orthonormals_tangent(Z, bsdf->extra->T, &X, &Y);
// distribution
float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
float slope_x = -local_m.x/(local_m.z*bsdf->alpha_x);
float slope_y = -local_m.y/(local_m.z*bsdf->alpha_y);
float slope_x = -local_m.x/(local_m.z*bsdf->extra->alpha_x);
float slope_y = -local_m.y/(local_m.z*bsdf->extra->alpha_y);
float slope_len = 1 + slope_x*slope_x + slope_y*slope_y;
float cosThetaM = local_m.z;
@@ -123,7 +128,7 @@ ccl_device float3 bsdf_disney_specular_eval_reflect(const ShaderClosure *sc, con
float cosPhiO = dot(I, X);
float sinPhiO = dot(I, Y);
float alphaO2 = (cosPhiO*cosPhiO)*(bsdf->alpha_x*bsdf->alpha_x) + (sinPhiO*sinPhiO)*(bsdf->alpha_y*bsdf->alpha_y);
float alphaO2 = (cosPhiO*cosPhiO)*(bsdf->extra->alpha_x*bsdf->extra->alpha_x) + (sinPhiO*sinPhiO)*(bsdf->extra->alpha_y*bsdf->extra->alpha_y);
alphaO2 /= cosPhiO*cosPhiO + sinPhiO*sinPhiO;
G1o = 2 / (1 + safe_sqrtf(1 + alphaO2 * tanThetaO2));
@@ -132,7 +137,7 @@ ccl_device float3 bsdf_disney_specular_eval_reflect(const ShaderClosure *sc, con
float cosPhiI = dot(omega_in, X);
float sinPhiI = dot(omega_in, Y);
float alphaI2 = (cosPhiI*cosPhiI)*(bsdf->alpha_x*bsdf->alpha_x) + (sinPhiI*sinPhiI)*(bsdf->alpha_y*bsdf->alpha_y);
float alphaI2 = (cosPhiI*cosPhiI)*(bsdf->extra->alpha_x*bsdf->extra->alpha_x) + (sinPhiI*sinPhiI)*(bsdf->extra->alpha_y*bsdf->extra->alpha_y);
alphaI2 /= cosPhiI*cosPhiI + sinPhiI*sinPhiI;
G1i = 2 / (1 + safe_sqrtf(1 + alphaI2 * tanThetaI2));
@@ -144,7 +149,7 @@ ccl_device float3 bsdf_disney_specular_eval_reflect(const ShaderClosure *sc, con
float common = D * 0.25f / cosNO;
float FH = schlick_fresnel(dot(omega_in, m));
float3 F = bsdf->cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; // lerp(sc->custom_color0, make_float3(1.0f, 1.0f, 1.0f), FH);
float3 F = bsdf->extra->cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; // lerp(sc->custom_color0, make_float3(1.0f, 1.0f, 1.0f), FH);
float3 out = F * G * common;
@@ -181,25 +186,23 @@ ccl_device int bsdf_disney_specular_sample(const ShaderClosure *sc,
if(cosNO > 0) {
float3 X, Y, Z = N;
if (bsdf->alpha_x == bsdf->alpha_y)
if (bsdf->extra->alpha_x == bsdf->extra->alpha_y)
make_orthonormals(Z, &X, &Y);
else
make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
make_orthonormals_tangent(Z, bsdf->extra->T, &X, &Y);
/* importance sampling with distribution of visible normals. vectors are
* transformed to local space before and after */
float3 local_I = make_float3(dot(X, I), dot(Y, I), cosNO);
float3 local_m;
float3 m;
float G1o;
local_m = importance_sample_microfacet_stretched(local_I, bsdf->alpha_x, bsdf->alpha_y,
local_m = importance_sample_microfacet_stretched(local_I, bsdf->extra->alpha_x, bsdf->extra->alpha_y,
randu, randv, false, &G1o);
m = X*local_m.x + Y*local_m.y + Z*local_m.z;
float3 m = X*local_m.x + Y*local_m.y + Z*local_m.z;
float cosThetaM = local_m.z;
/* reflection or refraction? */
float cosMO = dot(m, I);
if(cosMO > 0) {
@@ -207,7 +210,7 @@ ccl_device int bsdf_disney_specular_sample(const ShaderClosure *sc,
*omega_in = 2 * cosMO * m - I;
if(dot(Ng, *omega_in) > 0) {
if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f) {
if (bsdf->extra->alpha_x*bsdf->extra->alpha_y <= 1e-7f) {
/* some high number for MIS */
*pdf = 1e6f;
*eval = make_float3(1e6f, 1e6f, 1e6f);
@@ -215,10 +218,10 @@ ccl_device int bsdf_disney_specular_sample(const ShaderClosure *sc,
else {
/* microfacet normal is visible to this ray */
/* eq. 33 */
float alpha2 = bsdf->alpha_x * bsdf->alpha_y;
float alpha2 = bsdf->extra->alpha_x * bsdf->extra->alpha_y;
float D, G1i;
if (bsdf->alpha_x == bsdf->alpha_y) {
if (bsdf->extra->alpha_x == bsdf->extra->alpha_y) {
float cosThetaM2 = cosThetaM * cosThetaM;
float cosThetaM4 = cosThetaM2 * cosThetaM2;
float tanThetaM2 = 1/(cosThetaM2) - 1;
@@ -232,8 +235,8 @@ ccl_device int bsdf_disney_specular_sample(const ShaderClosure *sc,
}
else {
/* anisotropic distribution */
float slope_x = -local_m.x / (local_m.z*bsdf->alpha_x);
float slope_y = -local_m.y / (local_m.z*bsdf->alpha_y);
float slope_x = -local_m.x / (local_m.z*bsdf->extra->alpha_x);
float slope_y = -local_m.y / (local_m.z*bsdf->extra->alpha_y);
float slope_len = 1 + slope_x*slope_x + slope_y*slope_y;
float cosThetaM = local_m.z;
@@ -249,7 +252,7 @@ ccl_device int bsdf_disney_specular_sample(const ShaderClosure *sc,
float cosPhiI = dot(*omega_in, X);
float sinPhiI = dot(*omega_in, Y);
float alphaI2 = (cosPhiI*cosPhiI)*(bsdf->alpha_x*bsdf->alpha_x) + (sinPhiI*sinPhiI)*(bsdf->alpha_y*bsdf->alpha_y);
float alphaI2 = (cosPhiI*cosPhiI)*(bsdf->extra->alpha_x*bsdf->extra->alpha_x) + (sinPhiI*sinPhiI)*(bsdf->extra->alpha_y*bsdf->extra->alpha_y);
alphaI2 /= cosPhiI*cosPhiI + sinPhiI*sinPhiI;
G1i = 2 / (1 + safe_sqrtf(1 + alphaI2 * tanThetaI2));
@@ -259,8 +262,9 @@ ccl_device int bsdf_disney_specular_sample(const ShaderClosure *sc,
float common = (G1o * D) * 0.25f / cosNO;
*pdf = common;
float FH = schlick_fresnel(dot(*omega_in, m));
float3 F = bsdf->cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; // lerp(sc->custom_color0, make_float3(1.0f, 1.0f, 1.0f), FH);
float FH = fresnel_dielectric_cos(dot(*omega_in, m), bsdf->extra->ior);
//float FH = schlick_fresnel(dot(*omega_in, m));
float3 F = bsdf->extra->cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; // lerp(sc->custom_color0, make_float3(1.0f, 1.0f, 1.0f), FH);
*eval = G1i * common * F;
}

View File

@@ -410,9 +410,17 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
float3 F = make_float3(1.0f, 1.0f, 1.0f);
if (bsdf->extra) {
if (bsdf->extra->use_fresnel) {
float FH = fresnel_dielectric_cos(dot(omega_in, m), bsdf->ior);
/* Calculate the fresnel interpolation factor
* The value from fresnel_dielectric_cos(...) has to be normalized because
* the cspec0 keeps the F0 color
*/
float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
float F0_norm = 1.0f / (1.0f - F0);
float FH = (fresnel_dielectric_cos(dot(omega_in, m), bsdf->ior) - F0) * F0_norm;
//float FH = schlick_fresnel(dot(omega_in, m));
F = bsdf->extra->cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; // lerp(sc->custom_color0, make_float3(1.0f, 1.0f, 1.0f), FH);
/* Blend between white and a specular color with respect to the fresnel */
F = bsdf->extra->cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH;
}
}
@@ -485,9 +493,17 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, con
float3 F = make_float3(1.0f, 1.0f, 1.0f);
if (bsdf->extra) {
if (bsdf->extra->use_fresnel) {
float FH = fresnel_dielectric_cos(dot(omega_in, Ht), bsdf->ior);
/* Calculate the fresnel interpolation factor
* The value from fresnel_dielectric_cos(...) has to be normalized because
* the cspec0 keeps the F0 color
*/
float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
float F0_norm = 1.0f / (1.0f - F0);
float FH = (fresnel_dielectric_cos(dot(omega_in, Ht), bsdf->ior) - F0) * F0_norm;
//float FH = schlick_fresnel(dot(omega_in, Ht));
F = bsdf->extra->cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; // lerp(sc->custom_color0, make_float3(1.0f, 1.0f, 1.0f), FH);
/* Blend between white and a specular color with respect to the fresnel */
F = bsdf->extra->cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH;
}
}
@@ -599,9 +615,17 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
float3 F = make_float3(1.0f, 1.0f, 1.0f);
if (bsdf->extra) {
if (bsdf->extra->use_fresnel) {
float FH = fresnel_dielectric_cos(dot(*omega_in, m), bsdf->ior);
/* Calculate the fresnel interpolation factor
* The value from fresnel_dielectric_cos(...) has to be normalized because
* the cspec0 keeps the F0 color
*/
float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
float F0_norm = 1.0f / (1.0f - F0);
float FH = (fresnel_dielectric_cos(dot(*omega_in, m), bsdf->ior) - F0) * F0_norm;
//float FH = schlick_fresnel(dot(*omega_in, m));
F = bsdf->extra->cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; // lerp(sc->custom_color0, make_float3(1.0f, 1.0f, 1.0f), FH);
/* Blend between white and a specular color with respect to the fresnel */
F = bsdf->extra->cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH;
}
}
@@ -670,9 +694,17 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
float3 F = make_float3(1.0f, 1.0f, 1.0f);
if (bsdf->extra) {
if (bsdf->extra->use_fresnel) {
float FH = fresnel_dielectric_cos(dot(*omega_in, m), bsdf->ior);
/* Calculate the fresnel interpolation factor
* The value from fresnel_dielectric_cos(...) has to be normalized because
* the cspec0 keeps the F0 color
*/
float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
float F0_norm = 1.0f / (1.0f - F0);
float FH = (fresnel_dielectric_cos(dot(*omega_in, m), bsdf->ior) - F0) * F0_norm;
//float FH = schlick_fresnel(dot(*omega_in, m));
F = bsdf->extra->cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; // lerp(sc->custom_color0, make_float3(1.0f, 1.0f, 1.0f), FH);
/* Blend between white and a specular color with respect to the fresnel */
F = bsdf->extra->cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH;
}
}

View File

@@ -37,8 +37,11 @@ CCL_NAMESPACE_BEGIN
/* REFLECTION */
ccl_device int bsdf_reflection_setup(MicrofacetBsdf *bsdf)
ccl_device int bsdf_reflection_setup(MicrofacetBsdf *bsdf, bool use_fresnel = false)
{
if (bsdf->extra) {
bsdf->extra->use_fresnel = use_fresnel;
}
bsdf->type = CLOSURE_BSDF_REFLECTION_ID;
return SD_BSDF;
}
@@ -70,6 +73,17 @@ ccl_device int bsdf_reflection_sample(const ShaderClosure *sc, float3 Ng, float3
/* Some high number for MIS. */
*pdf = 1e6f;
*eval = make_float3(1e6f, 1e6f, 1e6f);
if (bsdf->extra) {
if (bsdf->extra->use_fresnel) {
*pdf = 1.0f;
float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
float F0_norm = 1.0f / (1.0f - F0);
float FH = (fresnel_dielectric_cos(dot(I, normalize(I + *omega_in)), bsdf->ior) - F0) * F0_norm;
*eval = bsdf->extra->cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH;
}
}
}
}
return LABEL_REFLECT|LABEL_SINGULAR;

View File

@@ -364,10 +364,19 @@ ccl_device int bssrdf_setup(Bssrdf *bssrdf, ClosureType type)
/* revert to diffuse BSDF if radius too small */
int flag;
if (type == CLOSURE_BSSRDF_DISNEY_ID) {
float roughness = bssrdf->roughness;
float3 baseColor = bssrdf->baseColor;
float3 N = bssrdf->N;
float3 weight = bssrdf->weight;
float sample_weight = bssrdf->sample_weight;
DisneyDiffuseBsdf *bsdf = (DisneyDiffuseBsdf*)bssrdf;
bsdf->N = bssrdf->N;
bsdf->roughness = bssrdf->roughness;
bsdf->baseColor = bssrdf->baseColor;
bsdf->N = N;
bsdf->roughness = roughness;
bsdf->baseColor = baseColor;
bsdf->weight = weight;
bsdf->sample_weight = sample_weight;
flag = bsdf_disney_diffuse_setup(bsdf);
bsdf->type = CLOSURE_BSDF_BSSRDF_DISNEY_ID;
}

View File

@@ -192,16 +192,16 @@ BSDF_CLOSURE_CLASS_BEGIN(DisneySheen, disney_sheen, DisneySheenBsdf, LABEL_DIFFU
CLOSURE_FLOAT_PARAM(DisneySheenClosure, params.sheenTint),
BSDF_CLOSURE_CLASS_END(DisneySheen, disney_sheen)
BSDF_CLOSURE_CLASS_BEGIN(DisneySpecular, disney_specular, DisneySpecularBsdf, LABEL_GLOSSY | LABEL_REFLECT)
/*BSDF_CLOSURE_CLASS_BEGIN(DisneySpecular, disney_specular, DisneySpecularBsdf, LABEL_GLOSSY | LABEL_REFLECT)
CLOSURE_FLOAT3_PARAM(DisneySpecularClosure, params.N),
CLOSURE_FLOAT3_PARAM(DisneySpecularClosure, params.T),
CLOSURE_FLOAT3_PARAM(DisneySpecularClosure, params.baseColor),
CLOSURE_FLOAT3_PARAM(DisneySpecularClosure, params.extra->baseColor),
CLOSURE_FLOAT_PARAM(DisneySpecularClosure, params.metallic),
CLOSURE_FLOAT_PARAM(DisneySpecularClosure, params.specular),
CLOSURE_FLOAT_PARAM(DisneySpecularClosure, params.specularTint),
CLOSURE_FLOAT_PARAM(DisneySpecularClosure, params.roughness),
CLOSURE_FLOAT_PARAM(DisneySpecularClosure, params.anisotropic),
BSDF_CLOSURE_CLASS_END(DisneySpecular, disney_specular)
BSDF_CLOSURE_CLASS_END(DisneySpecular, disney_specular)*/
BSDF_CLOSURE_CLASS_BEGIN(DisneyClearcoat, disney_clearcoat, DisneyClearcoatBsdf, LABEL_GLOSSY|LABEL_REFLECT)
CLOSURE_FLOAT3_PARAM(DisneyClearcoatClosure, params.N),
@@ -363,59 +363,49 @@ CCLOSURE_PREPARE(bsdf_disney_sheen_prepare, DisneySheenClosure)
*/
/* DISNEY SPECULAR */
/*class DisneySpecularClosure : public CBSDFClosure {
class DisneySpecularClosure : public CBSDFClosure {
public:
DisneySpecularClosure() : CBSDFClosure(LABEL_REFLECT | LABEL_GLOSSY)
{}
DisneySpecularBsdf params;
void setup()
DisneySpecularBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
{
sc.prim = this;
m_shaderdata_flag = bsdf_disney_specular_setup(&sc);
if (!skip(sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
DisneySpecularBsdf *bsdf = (DisneySpecularBsdf*)bsdf_alloc_osl(sd, sizeof(DisneySpecularBsdf), weight, &params);
DisneySpecularExtra *extra = (DisneySpecularExtra*)closure_alloc_extra(sd, sizeof(DisneySpecularExtra));
if (bsdf && extra) {
bsdf->extra = extra;
return bsdf;
}
}
return NULL;
}
void blur(float roughness)
void setup(ShaderData *sd, int path_flag, float3 weight)
{
}
float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const
{
return bsdf_disney_specular_eval_reflect(&sc, omega_out, omega_in, &pdf);
}
float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float& pdf) const
{
return bsdf_disney_specular_eval_transmit(&sc, omega_out, omega_in, &pdf);
}
int sample(const float3 &Ng, const float3 &omega_out, const float3 &domega_out_dx,
const float3 &domega_out_dy, float randu, float randv, float3 &omega_in,
float3 &domega_in_dx, float3 &domega_in_dy, float &pdf, float3 &eval) const
{
return bsdf_disney_specular_sample(&sc, Ng, omega_out, domega_out_dx, domega_out_dy,
randu, randv, &eval, &omega_in, &domega_in_dx, &domega_in_dy, &pdf);
DisneySpecularBsdf *bsdf = alloc(sd, path_flag, weight);
sd->flag |= (bsdf) ? bsdf_disney_specular_setup(bsdf) : 0;
}
};
ClosureParam *bsdf_disney_specular_params()
ClosureParam *closure_bsdf_disney_specular_params()
{
static ClosureParam params[] = {
CLOSURE_FLOAT3_PARAM(DisneySpecularClosure, sc.N),
CLOSURE_FLOAT3_PARAM(DisneySpecularClosure, sc.T),
CLOSURE_FLOAT3_PARAM(DisneySpecularClosure, sc.color0), // base color
CLOSURE_FLOAT_PARAM(DisneySpecularClosure, sc.data0), // metallic
CLOSURE_FLOAT_PARAM(DisneySpecularClosure, sc.data1), // specular
CLOSURE_FLOAT_PARAM(DisneySpecularClosure, sc.data2), // specularTint
CLOSURE_FLOAT_PARAM(DisneySpecularClosure, sc.data3), // roughness
CLOSURE_FLOAT_PARAM(DisneySpecularClosure, sc.data4), // anisotropic
CLOSURE_FLOAT3_PARAM(DisneySpecularClosure, params.N),
CLOSURE_FLOAT3_PARAM(DisneySpecularClosure, params.extra->T),
CLOSURE_FLOAT3_PARAM(DisneySpecularClosure, params.extra->baseColor),
CLOSURE_FLOAT_PARAM(DisneySpecularClosure, params.metallic),
CLOSURE_FLOAT_PARAM(DisneySpecularClosure, params.specular),
CLOSURE_FLOAT_PARAM(DisneySpecularClosure, params.specularTint),
CLOSURE_FLOAT_PARAM(DisneySpecularClosure, params.roughness),
CLOSURE_FLOAT_PARAM(DisneySpecularClosure, params.anisotropic),
CLOSURE_STRING_KEYPARAM(DisneySpecularClosure, label, "label"),
CLOSURE_FINISH_PARAM(DisneySpecularClosure)
};
return params;
}
CCLOSURE_PREPARE(closure_bsdf_disney_specular_prepare, DisneySpecularClosure);
CCLOSURE_PREPARE(bsdf_disney_specular_prepare, DisneySpecularClosure)
*/
/* Registration */
@@ -487,7 +477,7 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
register_closure(ss, "disney_sheen", id++,
bsdf_disney_sheen_params(), bsdf_disney_sheen_prepare);
register_closure(ss, "disney_specular", id++,
bsdf_disney_specular_params(), bsdf_disney_specular_prepare);
closure_bsdf_disney_specular_params(), closure_bsdf_disney_specular_prepare);
register_closure(ss, "disney_clearcoat", id++,
bsdf_disney_clearcoat_params(), bsdf_disney_clearcoat_prepare);

View File

@@ -62,6 +62,7 @@ OSL::ClosureParam *closure_bsdf_microfacet_ggx_aniso_fresnel_params();
OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_fresnel_params();
OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_glass_fresnel_params();
OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_aniso_fresnel_params();
OSL::ClosureParam *closure_bsdf_disney_specular_params();
void closure_emission_prepare(OSL::RendererServices *, int id, void *data);
void closure_background_prepare(OSL::RendererServices *, int id, void *data);
@@ -83,6 +84,7 @@ void closure_bsdf_microfacet_ggx_aniso_fresnel_prepare(OSL::RendererServices *,
void closure_bsdf_microfacet_multi_ggx_fresnel_prepare(OSL::RendererServices *, int id, void *data);
void closure_bsdf_microfacet_multi_ggx_glass_fresnel_prepare(OSL::RendererServices *, int id, void *data);
void closure_bsdf_microfacet_multi_ggx_aniso_fresnel_prepare(OSL::RendererServices *, int id, void *data);
void closure_bsdf_disney_specular_prepare(OSL::RendererServices *, int id, void *data);
#define CCLOSURE_PREPARE(name, classname) \
void name(RendererServices *, int id, void *data) \

View File

@@ -265,7 +265,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
bsdf->extra->color = baseColor;
/* setup bsdf */
if (distribution == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)
if (distribution == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID && roughness > 0.075f)
ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_aniso_setup(bsdf, true);
else
ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_aniso_setup(bsdf, true);
@@ -284,7 +284,66 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
float3 cspec0 = baseColor * specularTint + make_float3(1.0f, 1.0f, 1.0f) * (1.0f - specularTint);
bool frontfacing = (ccl_fetch(sd, flag) & SD_BACKFACING) == 0;
if (distribution == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID) {
if (roughness <= 5e-2f || distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID) {
float refl_roughness = roughness;
if (roughness <= 1e-2f)
refl_roughness = 0.0f;
/* reflection */
#ifdef __CAUSTICS_TRICKS__
if (kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0)
#endif
{
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), glass_weight*fresnel);
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if (bsdf && extra) {
bsdf->N = N;
bsdf->extra = extra;
bsdf->alpha_x = refl_roughness * refl_roughness;
bsdf->alpha_y = refl_roughness * refl_roughness;
bsdf->ior = ior;
bsdf->extra->color = baseColor;
bsdf->extra->cspec0 = cspec0;
if (refl_roughness == 0.0f)
ccl_fetch(sd, flag) |= bsdf_reflection_setup(bsdf, true);
else
ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_setup(bsdf, true);
}
}
/* refraction */
#ifdef __CAUSTICS_TRICKS__
if (kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0)
#endif
{
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), baseColor*glass_weight*(1.0f - fresnel));
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if (bsdf && extra) {
bsdf->N = N;
bsdf->extra = extra;
if (distribution == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)
refraction_roughness = roughness;
else
refraction_roughness = 1.0f - (1.0f - roughness) * (1.0f - refraction_roughness);
bsdf->alpha_x = refraction_roughness * refraction_roughness;
bsdf->alpha_y = refraction_roughness * refraction_roughness;
bsdf->ior = ior;
bsdf->extra->color = baseColor;
bsdf->extra->cspec0 = cspec0;
ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_refraction_setup(bsdf);
}
}
}
else {
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), glass_weight);
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
@@ -304,55 +363,6 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_glass_setup(bsdf, true, frontfacing);
}
}
else {
/* reflection */
#ifdef __CAUSTICS_TRICKS__
if (kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0)
#endif
{
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), glass_weight*fresnel);
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if (bsdf && extra) {
bsdf->N = N;
bsdf->extra = extra;
bsdf->alpha_x = roughness * roughness;
bsdf->alpha_y = roughness * roughness;
bsdf->ior = ior;
bsdf->extra->color = baseColor;
bsdf->extra->cspec0 = cspec0;
ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_setup(bsdf, true);
}
}
/* refraction */
#ifdef __CAUSTICS_TRICKS__
if (kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0)
#endif
{
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), glass_weight*(1.0f - fresnel));
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if (bsdf && extra) {
bsdf->N = N;
bsdf->extra = extra;
refraction_roughness = 1.0f - (1.0f - roughness) * (1.0f - refraction_roughness);
bsdf->alpha_x = refraction_roughness * refraction_roughness;
bsdf->alpha_y = refraction_roughness * refraction_roughness;
bsdf->ior = ior;
bsdf->extra->color = baseColor;
bsdf->extra->cspec0 = cspec0;
ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_refraction_setup(bsdf, true);
}
}
}
}
#ifdef __CAUSTICS_TRICKS__
}