Compare commits
79 Commits
tmp-gpu-co
...
cycles_dis
Author | SHA1 | Date | |
---|---|---|---|
5d4b4da184 | |||
f80dcb4f34 | |||
521d4335ef | |||
732db8a57f | |||
c58a54bbf2 | |||
3ed1e08f66 | |||
5ff822140f | |||
0103659f5e | |||
0aa68f5335 | |||
f5897a9494 | |||
3dfc240e61 | |||
a2dd0c5faf | |||
9817375912 | |||
bbc5d9d452 | |||
d52d8f2813 | |||
8f3d927385 | |||
d93f680db9 | |||
c708c3e53b | |||
dfbfff9c38 | |||
e5a748ced1 | |||
75992bebc1 | |||
4dfcf455f7 | |||
243a0e3eb8 | |||
2a5ac50922 | |||
e1fa862391 | |||
d0530a8af0 | |||
3f4fc826bd | |||
4d3a0032ec | |||
3cd5eb56cf | |||
7cb37d7119 | |||
cdd29d06bb | |||
02c315aeb0 | |||
5f880293ae | |||
630b80e08b | |||
0d9f4d7acb | |||
9eed34c7d9 | |||
ef29aaee1a | |||
88567af085 | |||
cc267e52f2 | |||
81f6c06b1f | |||
ece5a08e0d | |||
e3aff6849e | |||
b3ca6d8a2f | |||
d68729300e | |||
cb6e500b12 | |||
bfb9cb11b5 | |||
642c0fdad1 | |||
c10b484dca | |||
462bba3f97 | |||
32d348577d | |||
dbad91ca6d | |||
50ea5e3e34 | |||
10974cc826 | |||
218202c090 | |||
dd139ead7e | |||
11160fa4e1 | |||
cee4fe0cc9 | |||
4f955d0523 | |||
1f5c41874b | |||
d4b814e930 | |||
b86a1f5ba5 | |||
585b886236 | |||
f91a286398 | |||
30da91c9c5 | |||
30d41da0f0 | |||
1f099fce24 | |||
00a1378b98 | |||
6baa7a7eb7 | |||
d8fa169bf3 | |||
6b5bab6cec | |||
f6499c2676 | |||
7100640b65 | |||
419ee54411 | |||
6006f91e87 | |||
0ed0895914 | |||
0630b742d7 | |||
9f3d39744b | |||
9b26206376 | |||
4711a3927d |
@@ -517,6 +517,27 @@ static ShaderNode *add_node(Scene *scene,
|
||||
}
|
||||
node = hair;
|
||||
}
|
||||
else if(b_node.is_a(&RNA_ShaderNodeBsdfDisney)) {
|
||||
BL::ShaderNodeBsdfDisney b_disney_node(b_node);
|
||||
DisneyBsdfNode *disney = new DisneyBsdfNode();
|
||||
switch (b_disney_node.distribution()) {
|
||||
case BL::ShaderNodeBsdfDisney::distribution_GGX:
|
||||
disney->distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
|
||||
break;
|
||||
case BL::ShaderNodeBsdfDisney::distribution_MULTI_GGX:
|
||||
disney->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
|
||||
break;
|
||||
}
|
||||
switch (b_disney_node.surface_type()) {
|
||||
case BL::ShaderNodeBsdfDisney::surface_type_THIN_SURFACE:
|
||||
disney->surface_type = THIN_SURFACE;
|
||||
break;
|
||||
case BL::ShaderNodeBsdfDisney::surface_type_SOLID_SURFACE:
|
||||
disney->surface_type = SOLID_SURFACE;
|
||||
break;
|
||||
}
|
||||
node = disney;
|
||||
}
|
||||
else if(b_node.is_a(&RNA_ShaderNodeBsdfTranslucent)) {
|
||||
node = new TranslucentBsdfNode();
|
||||
}
|
||||
|
@@ -108,6 +108,8 @@ set(SRC_CLOSURE_HEADERS
|
||||
closure/bssrdf.h
|
||||
closure/emissive.h
|
||||
closure/volume.h
|
||||
closure/bsdf_disney_diffuse.h
|
||||
closure/bsdf_disney_sheen.h
|
||||
)
|
||||
|
||||
set(SRC_SVM_HEADERS
|
||||
|
@@ -27,6 +27,8 @@
|
||||
#include "../closure/bsdf_ashikhmin_shirley.h"
|
||||
#include "../closure/bsdf_toon.h"
|
||||
#include "../closure/bsdf_hair.h"
|
||||
#include "../closure/bsdf_disney_diffuse.h"
|
||||
#include "../closure/bsdf_disney_sheen.h"
|
||||
#ifdef __SUBSURFACE__
|
||||
# include "../closure/bssrdf.h"
|
||||
#endif
|
||||
@@ -86,16 +88,22 @@ ccl_device_forceinline int bsdf_sample(KernelGlobals *kg,
|
||||
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID:
|
||||
label = bsdf_microfacet_ggx_sample(kg, sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
|
||||
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
|
||||
label = bsdf_microfacet_multi_ggx_sample(kg, sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
|
||||
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf, &ccl_fetch(sd, lcg_state));
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
|
||||
label = bsdf_microfacet_multi_ggx_glass_sample(kg, sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
|
||||
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf, &ccl_fetch(sd, lcg_state));
|
||||
break;
|
||||
@@ -130,6 +138,20 @@ ccl_device_forceinline int bsdf_sample(KernelGlobals *kg,
|
||||
label = bsdf_hair_transmission_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
|
||||
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_DISNEY_DIFFUSE_ID:
|
||||
case CLOSURE_BSDF_DISNEY_DIFFUSE_TRANSMIT_ID:
|
||||
case CLOSURE_BSDF_BSSRDF_DISNEY_ID:
|
||||
label = bsdf_disney_diffuse_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
|
||||
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_DISNEY_RETRO_REFLECTION_ID:
|
||||
label = bsdf_disney_retro_reflection_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
|
||||
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_DISNEY_SHEEN_ID:
|
||||
label = bsdf_disney_sheen_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
|
||||
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
|
||||
break;
|
||||
#endif
|
||||
#ifdef __VOLUME__
|
||||
case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
|
||||
@@ -188,14 +210,20 @@ float3 bsdf_eval(KernelGlobals *kg,
|
||||
eval = bsdf_transparent_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID:
|
||||
eval = bsdf_microfacet_ggx_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
|
||||
eval = bsdf_microfacet_multi_ggx_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf, &ccl_fetch(sd, lcg_state));
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
|
||||
eval = bsdf_microfacet_multi_ggx_glass_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf, &ccl_fetch(sd, lcg_state));
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
@@ -222,6 +250,17 @@ float3 bsdf_eval(KernelGlobals *kg,
|
||||
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
|
||||
eval = bsdf_hair_transmission_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_DISNEY_DIFFUSE_ID:
|
||||
case CLOSURE_BSDF_DISNEY_DIFFUSE_TRANSMIT_ID:
|
||||
case CLOSURE_BSDF_BSSRDF_DISNEY_ID:
|
||||
eval = bsdf_disney_diffuse_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_DISNEY_RETRO_REFLECTION_ID:
|
||||
eval = bsdf_disney_retro_reflection_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_DISNEY_SHEEN_ID:
|
||||
eval = bsdf_disney_sheen_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
|
||||
break;
|
||||
#endif
|
||||
#ifdef __VOLUME__
|
||||
case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
|
||||
@@ -256,14 +295,20 @@ float3 bsdf_eval(KernelGlobals *kg,
|
||||
eval = bsdf_transparent_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID:
|
||||
eval = bsdf_microfacet_ggx_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
|
||||
eval = bsdf_microfacet_multi_ggx_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf, &ccl_fetch(sd, lcg_state));
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
|
||||
eval = bsdf_microfacet_multi_ggx_glass_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf, &ccl_fetch(sd, lcg_state));
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
@@ -290,6 +335,17 @@ float3 bsdf_eval(KernelGlobals *kg,
|
||||
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
|
||||
eval = bsdf_hair_transmission_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_DISNEY_DIFFUSE_ID:
|
||||
case CLOSURE_BSDF_DISNEY_DIFFUSE_TRANSMIT_ID:
|
||||
case CLOSURE_BSDF_BSSRDF_DISNEY_ID:
|
||||
eval = bsdf_disney_diffuse_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_DISNEY_RETRO_REFLECTION_ID:
|
||||
eval = bsdf_disney_retro_reflection_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_DISNEY_SHEEN_ID:
|
||||
eval = bsdf_disney_sheen_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
|
||||
break;
|
||||
#endif
|
||||
#ifdef __VOLUME__
|
||||
case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
|
||||
@@ -311,12 +367,18 @@ ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness)
|
||||
#ifdef __SVM__
|
||||
switch(sc->type) {
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
|
||||
bsdf_microfacet_multi_ggx_blur(sc, roughness);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID:
|
||||
bsdf_microfacet_ggx_blur(sc, roughness);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
@@ -349,10 +411,16 @@ ccl_device bool bsdf_merge(ShaderClosure *a, ShaderClosure *b)
|
||||
case CLOSURE_BSDF_REFLECTION_ID:
|
||||
case CLOSURE_BSDF_REFRACTION_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
|
||||
|
244
intern/cycles/kernel/closure/bsdf_disney_diffuse.h
Normal file
244
intern/cycles/kernel/closure/bsdf_disney_diffuse.h
Normal file
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright 2011-2014 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_DISNEY_DIFFUSE_H__
|
||||
#define __BSDF_DISNEY_DIFFUSE_H__
|
||||
|
||||
/* DISNEY DIFFUSE BRDF
|
||||
*
|
||||
* Shading model by Brent Burley (Disney): "Physically Based Shading at Disney" (2012)
|
||||
*/
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
typedef ccl_addr_space struct DisneyDiffuseBsdf {
|
||||
SHADER_CLOSURE_BASE;
|
||||
|
||||
float roughness, flatness;
|
||||
float3 N;
|
||||
} DisneyDiffuseBsdf;
|
||||
|
||||
|
||||
/* DIFFUSE */
|
||||
|
||||
ccl_device float3 calculate_disney_diffuse_brdf(const DisneyDiffuseBsdf *bsdf,
|
||||
float NdotL, float NdotV, float LdotH)
|
||||
{
|
||||
float FL = schlick_fresnel(NdotL), FV = schlick_fresnel(NdotV);
|
||||
float Fd = (1.0f - 0.5f * FL) * (1.0f - 0.5f * FV);
|
||||
|
||||
float ss = 0.0f;
|
||||
if(bsdf->flatness > 0.0f) {
|
||||
// Based on Hanrahan-Krueger BRDF approximation of isotropic BSSRDF
|
||||
// 1.25 scale is used to (roughly) preserve albedo
|
||||
// Fss90 used to "flatten" retro-reflection based on roughness
|
||||
float Fss90 = LdotH*LdotH * bsdf->roughness;
|
||||
float Fss = (1.0f + (Fss90 - 1.0f) * FL) * (1.0f + (Fss90 - 1.0f) * FV);
|
||||
ss = 1.25f * (Fss * (1.0f / (NdotL + NdotV) - 0.5f) + 0.5f);
|
||||
}
|
||||
|
||||
float value = Fd + (ss - Fd) * bsdf->flatness;
|
||||
value *= M_1_PI_F * NdotL;
|
||||
|
||||
return make_float3(value, value, value);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_disney_diffuse_setup(DisneyDiffuseBsdf *bsdf)
|
||||
{
|
||||
bsdf->type = CLOSURE_BSDF_DISNEY_DIFFUSE_ID;
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device int bsdf_disney_diffuse_transmit_setup(DisneyDiffuseBsdf *bsdf)
|
||||
{
|
||||
bsdf->type = CLOSURE_BSDF_DISNEY_DIFFUSE_TRANSMIT_ID;
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_disney_diffuse_eval_reflect(const ShaderClosure *sc, const float3 I,
|
||||
const float3 omega_in, float *pdf)
|
||||
{
|
||||
const DisneyDiffuseBsdf *bsdf = (const DisneyDiffuseBsdf *)sc;
|
||||
bool m_transmittance = bsdf->type == CLOSURE_BSDF_DISNEY_DIFFUSE_TRANSMIT_ID;
|
||||
|
||||
if(m_transmittance)
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
float3 N = bsdf->N;
|
||||
|
||||
if(dot(N, omega_in) > 0.0f) {
|
||||
float3 H = normalize(I + omega_in);
|
||||
|
||||
*pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
|
||||
return calculate_disney_diffuse_brdf(bsdf, fmaxf(dot(N, omega_in), 0.0f), fmaxf(dot(N, I), 0.0f), dot(omega_in, H));
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_disney_diffuse_eval_transmit(const ShaderClosure *sc, const float3 I,
|
||||
const float3 omega_in, float *pdf)
|
||||
{
|
||||
const DisneyDiffuseBsdf *bsdf = (const DisneyDiffuseBsdf *)sc;
|
||||
bool m_transmittance = bsdf->type == CLOSURE_BSDF_DISNEY_DIFFUSE_TRANSMIT_ID;
|
||||
|
||||
if(!m_transmittance)
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
float3 N = bsdf->N;
|
||||
|
||||
if(dot(-N, omega_in) > 0.0f) {
|
||||
float3 H = normalize(I + omega_in);
|
||||
|
||||
*pdf = fmaxf(dot(-N, omega_in), 0.0f) * M_1_PI_F;
|
||||
return calculate_disney_diffuse_brdf(bsdf, fmaxf(dot(-N, omega_in), 0.0f), fmaxf(dot(N, I), 0.0f), dot(omega_in, H));
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device int bsdf_disney_diffuse_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)
|
||||
{
|
||||
const DisneyDiffuseBsdf *bsdf = (const DisneyDiffuseBsdf *)sc;
|
||||
bool m_transmittance = bsdf->type == CLOSURE_BSDF_DISNEY_DIFFUSE_TRANSMIT_ID;
|
||||
|
||||
float3 N = bsdf->N;
|
||||
|
||||
if(m_transmittance) {
|
||||
sample_uniform_hemisphere(-N, randu, randv, omega_in, pdf);
|
||||
}
|
||||
else {
|
||||
sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
|
||||
}
|
||||
|
||||
if(m_transmittance && dot(-Ng, *omega_in) > 0) {
|
||||
float3 I_t = -((2 * dot(N, I)) * N - I);
|
||||
float3 H = normalize(I_t + *omega_in);
|
||||
|
||||
*eval = calculate_disney_diffuse_brdf(bsdf, fmaxf(dot(-N, *omega_in), 0.0f), fmaxf(dot(N, I), 0.0f), dot(*omega_in, H));
|
||||
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
// TODO: find a better approximation for the diffuse bounce
|
||||
*domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx);
|
||||
*domega_in_dy = -((2 * dot(N, dIdy)) * N - dIdy);
|
||||
#endif
|
||||
}
|
||||
else if(!m_transmittance && dot(Ng, *omega_in) > 0) {
|
||||
float3 H = normalize(I + *omega_in);
|
||||
|
||||
*eval = calculate_disney_diffuse_brdf(bsdf, fmaxf(dot(N, *omega_in), 0.0f), fmaxf(dot(N, I), 0.0f), dot(*omega_in, H));
|
||||
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
// TODO: find a better approximation for the diffuse bounce
|
||||
*domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx);
|
||||
*domega_in_dy = -((2 * dot(N, dIdy)) * N - dIdy);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
}
|
||||
|
||||
return (m_transmittance) ? LABEL_TRANSMIT|LABEL_DIFFUSE : LABEL_REFLECT|LABEL_DIFFUSE;
|
||||
}
|
||||
|
||||
|
||||
/* RETRO-REFLECTION */
|
||||
|
||||
ccl_device float3 calculate_retro_reflection(const DisneyDiffuseBsdf *bsdf,
|
||||
float NdotL, float NdotV, float LdotH)
|
||||
{
|
||||
float FL = schlick_fresnel(NdotL), FV = schlick_fresnel(NdotV);
|
||||
float RR = 2.0f * bsdf->roughness * LdotH*LdotH;
|
||||
|
||||
float FRR = RR * (FL + FV + FL * FV * (RR - 1.0f));
|
||||
|
||||
float value = M_1_PI_F * FRR * NdotL;
|
||||
|
||||
return make_float3(value, value, value);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_disney_retro_reflection_setup(DisneyDiffuseBsdf *bsdf)
|
||||
{
|
||||
bsdf->type = CLOSURE_BSDF_DISNEY_RETRO_REFLECTION_ID;
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_disney_retro_reflection_eval_reflect(const ShaderClosure *sc, const float3 I,
|
||||
const float3 omega_in, float *pdf)
|
||||
{
|
||||
const DisneyDiffuseBsdf *bsdf = (const DisneyDiffuseBsdf *)sc;
|
||||
|
||||
float3 N = bsdf->N;
|
||||
|
||||
if(dot(N, omega_in) > 0.0f) {
|
||||
float3 H = normalize(I + omega_in);
|
||||
|
||||
*pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
|
||||
return calculate_retro_reflection(bsdf, fmaxf(dot(N, omega_in), 0.0f), fmaxf(dot(N, I), 0.0f), dot(omega_in, H));
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_disney_retro_reflection_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_disney_retro_reflection_sample(const ShaderClosure *sc,
|
||||
float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv,
|
||||
float3 *eval, float3 *omega_in, float3 *domega_in_dx,
|
||||
float3 *domega_in_dy, float *pdf)
|
||||
{
|
||||
const DisneyDiffuseBsdf *bsdf = (const DisneyDiffuseBsdf *)sc;
|
||||
|
||||
float3 N = bsdf->N;
|
||||
|
||||
sample_uniform_hemisphere(N, randu, randv, omega_in, pdf);
|
||||
|
||||
if(dot(Ng, *omega_in) > 0) {
|
||||
float3 H = normalize(I + *omega_in);
|
||||
|
||||
*eval = calculate_retro_reflection(bsdf, fmaxf(dot(N, *omega_in), 0.0f), fmaxf(dot(N, I), 0.0f), dot(*omega_in, H));
|
||||
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
// TODO: find a better approximation for the diffuse bounce
|
||||
*domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx);
|
||||
*domega_in_dy = -((2 * dot(N, dIdy)) * N - dIdy);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
}
|
||||
|
||||
return LABEL_REFLECT|LABEL_DIFFUSE;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __BSDF_DISNEY_DIFFUSE_H__ */
|
||||
|
||||
|
114
intern/cycles/kernel/closure/bsdf_disney_sheen.h
Normal file
114
intern/cycles/kernel/closure/bsdf_disney_sheen.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 2011-2014 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_DISNEY_SHEEN_H__
|
||||
#define __BSDF_DISNEY_SHEEN_H__
|
||||
|
||||
/* DISNEY SHEEN BRDF
|
||||
*
|
||||
* Shading model by Brent Burley (Disney): "Physically Based Shading at Disney" (2012)
|
||||
*/
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
typedef ccl_addr_space struct DisneySheenBsdf {
|
||||
SHADER_CLOSURE_BASE;
|
||||
float3 N;
|
||||
} DisneySheenBsdf;
|
||||
|
||||
ccl_device float3 calculate_disney_sheen_brdf(const DisneySheenBsdf *bsdf,
|
||||
float3 N, float3 V, float3 L, float3 H, float *pdf)
|
||||
{
|
||||
float NdotL = dot(N, L);
|
||||
float NdotV = dot(N, V);
|
||||
|
||||
if(NdotL < 0 || NdotV < 0) {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
float LdotH = dot(L, H);
|
||||
|
||||
float value = schlick_fresnel(LdotH) * NdotL;
|
||||
|
||||
return make_float3(value, value, value);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_disney_sheen_setup(DisneySheenBsdf *bsdf)
|
||||
{
|
||||
bsdf->type = CLOSURE_BSDF_DISNEY_SHEEN_ID;
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_disney_sheen_eval_reflect(const ShaderClosure *sc, const float3 I,
|
||||
const float3 omega_in, float *pdf)
|
||||
{
|
||||
const DisneySheenBsdf *bsdf = (const DisneySheenBsdf *)sc;
|
||||
|
||||
float3 N = bsdf->N;
|
||||
float3 V = I; // outgoing
|
||||
float3 L = omega_in; // incoming
|
||||
float3 H = normalize(L + V);
|
||||
|
||||
if(dot(N, omega_in) > 0.0f) {
|
||||
*pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
|
||||
return calculate_disney_sheen_brdf(bsdf, N, V, L, H, pdf);
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_disney_sheen_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_disney_sheen_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)
|
||||
{
|
||||
const DisneySheenBsdf *bsdf = (const DisneySheenBsdf *)sc;
|
||||
|
||||
float3 N = bsdf->N;
|
||||
|
||||
sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
|
||||
|
||||
if(dot(Ng, *omega_in) > 0) {
|
||||
float3 H = normalize(I + *omega_in);
|
||||
|
||||
*eval = calculate_disney_sheen_brdf(bsdf, N, I, *omega_in, H, pdf);
|
||||
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
// TODO: find a better approximation for the diffuse bounce
|
||||
*domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx);
|
||||
*domega_in_dy = -((2 * dot(N, dIdy)) * N - dIdy);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
}
|
||||
return LABEL_REFLECT|LABEL_DIFFUSE;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __BSDF_DISNEY_SHEEN_H__ */
|
||||
|
||||
|
@@ -36,7 +36,8 @@
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
typedef ccl_addr_space struct MicrofacetExtra {
|
||||
float3 color;
|
||||
float3 color, cspec0;
|
||||
float clearcoat;
|
||||
} MicrofacetExtra;
|
||||
|
||||
typedef ccl_addr_space struct MicrofacetBsdf {
|
||||
@@ -233,6 +234,36 @@ ccl_device_forceinline float3 microfacet_sample_stretched(
|
||||
return normalize(make_float3(-slope_x, -slope_y, 1.0f));
|
||||
}
|
||||
|
||||
/* Calculate the reflection color
|
||||
*
|
||||
* If fresnel is used, the color is an interpolation of the F0 color and white
|
||||
* with respect to the fresnel
|
||||
*
|
||||
* Else it is simply white
|
||||
*/
|
||||
ccl_device_forceinline float3 reflection_color(const MicrofacetBsdf *bsdf, float3 L, float3 H) {
|
||||
float3 F = make_float3(1.0f, 1.0f, 1.0f);
|
||||
bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID
|
||||
|| bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID
|
||||
|| bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID);
|
||||
|
||||
if(use_fresnel) {
|
||||
float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
|
||||
|
||||
F = interpolate_fresnel_color(L, H, bsdf->ior, F0, bsdf->extra->cspec0);
|
||||
}
|
||||
|
||||
return F;
|
||||
}
|
||||
|
||||
ccl_device_forceinline float D_GTR1(float NdotH, float alpha)
|
||||
{
|
||||
if (alpha >= 1.0f) return M_1_PI_F;
|
||||
float alpha2 = alpha*alpha;
|
||||
float t = 1.0f + (alpha2 - 1.0f) * NdotH*NdotH;
|
||||
return (alpha2 - 1.0f) / (M_PI_F * logf(alpha2) * t);
|
||||
}
|
||||
|
||||
/* GGX microfacet with Smith shadow-masking from:
|
||||
*
|
||||
* Microfacet Models for Refraction through Rough Surfaces
|
||||
@@ -248,14 +279,44 @@ ccl_device_forceinline float3 microfacet_sample_stretched(
|
||||
|
||||
ccl_device int bsdf_microfacet_ggx_setup(MicrofacetBsdf *bsdf)
|
||||
{
|
||||
bsdf->extra = NULL;
|
||||
|
||||
bsdf->alpha_x = saturate(bsdf->alpha_x);
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
|
||||
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_ggx_fresnel_setup(MicrofacetBsdf *bsdf)
|
||||
{
|
||||
bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
|
||||
bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
|
||||
bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
|
||||
|
||||
bsdf->alpha_x = saturate(bsdf->alpha_x);
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID;
|
||||
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_ggx_clearcoat_setup(MicrofacetBsdf *bsdf)
|
||||
{
|
||||
bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
|
||||
bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
|
||||
bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
|
||||
|
||||
bsdf->alpha_x = saturate(bsdf->alpha_x);
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID;
|
||||
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device bool bsdf_microfacet_merge(const ShaderClosure *a, const ShaderClosure *b)
|
||||
{
|
||||
const MicrofacetBsdf *bsdf_a = (const MicrofacetBsdf*)a;
|
||||
@@ -273,16 +334,34 @@ ccl_device bool bsdf_microfacet_merge(const ShaderClosure *a, const ShaderClosur
|
||||
|
||||
ccl_device int bsdf_microfacet_ggx_aniso_setup(MicrofacetBsdf *bsdf)
|
||||
{
|
||||
bsdf->extra = NULL;
|
||||
|
||||
bsdf->alpha_x = saturate(bsdf->alpha_x);
|
||||
bsdf->alpha_y = saturate(bsdf->alpha_y);
|
||||
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
|
||||
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf)
|
||||
{
|
||||
bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
|
||||
bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
|
||||
bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
|
||||
|
||||
bsdf->alpha_x = saturate(bsdf->alpha_x);
|
||||
bsdf->alpha_y = saturate(bsdf->alpha_y);
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID;
|
||||
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_ggx_refraction_setup(MicrofacetBsdf *bsdf)
|
||||
{
|
||||
bsdf->extra = NULL;
|
||||
|
||||
bsdf->alpha_x = saturate(bsdf->alpha_x);
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
|
||||
@@ -291,6 +370,18 @@ ccl_device int bsdf_microfacet_ggx_refraction_setup(MicrofacetBsdf *bsdf)
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_ggx_refraction_thin_setup(MicrofacetBsdf *bsdf)
|
||||
{
|
||||
bsdf->extra = NULL;
|
||||
|
||||
bsdf->alpha_x = saturate(bsdf->alpha_x);
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID;
|
||||
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device void bsdf_microfacet_ggx_blur(ShaderClosure *sc, float roughness)
|
||||
{
|
||||
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)sc;
|
||||
@@ -304,7 +395,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
|
||||
const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
|
||||
float alpha_x = bsdf->alpha_x;
|
||||
float alpha_y = bsdf->alpha_y;
|
||||
bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
|
||||
bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID || bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID;
|
||||
float3 N = bsdf->N;
|
||||
|
||||
if(m_refractive || alpha_x*alpha_y <= 1e-7f)
|
||||
@@ -319,6 +410,8 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
|
||||
float alpha2 = alpha_x * alpha_y;
|
||||
float D, G1o, G1i;
|
||||
|
||||
bool is_disney_clearcoat = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID);
|
||||
|
||||
if(alpha_x == alpha_y) {
|
||||
/* isotropic
|
||||
* eq. 20: (F*G*D)/(4*in*on)
|
||||
@@ -327,7 +420,18 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
|
||||
float cosThetaM2 = cosThetaM * cosThetaM;
|
||||
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
||||
float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
|
||||
D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
|
||||
|
||||
if(is_disney_clearcoat) {
|
||||
/* use GTR1 for clearcoat */
|
||||
D = D_GTR1(cosThetaM, bsdf->alpha_x);
|
||||
|
||||
/* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */
|
||||
alpha2 = 0.0625f;
|
||||
}
|
||||
else {
|
||||
/* use GTR2 otherwise */
|
||||
D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
|
||||
}
|
||||
|
||||
/* eq. 34: now calculate G1(i,m) and G1(o,m) */
|
||||
G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
|
||||
@@ -374,7 +478,13 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
|
||||
|
||||
/* eq. 20 */
|
||||
float common = D * 0.25f / cosNO;
|
||||
float out = G * common;
|
||||
|
||||
float3 F = reflection_color(bsdf, omega_in, m);
|
||||
if(is_disney_clearcoat) {
|
||||
F *= 0.25f * bsdf->extra->clearcoat;
|
||||
}
|
||||
|
||||
float3 out = F * G * common;
|
||||
|
||||
/* eq. 2 in distribution of visible normals sampling
|
||||
* pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
|
||||
@@ -384,7 +494,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
|
||||
* pdf = pm * 0.25 / dot(m, I); */
|
||||
*pdf = G1o * common;
|
||||
|
||||
return make_float3(out, out, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
@@ -396,7 +506,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, con
|
||||
float alpha_x = bsdf->alpha_x;
|
||||
float alpha_y = bsdf->alpha_y;
|
||||
float m_eta = bsdf->ior;
|
||||
bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
|
||||
bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID || bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID;
|
||||
float3 N = bsdf->N;
|
||||
|
||||
if(!m_refractive || alpha_x*alpha_y <= 1e-7f)
|
||||
@@ -409,7 +519,15 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, con
|
||||
return make_float3(0.0f, 0.0f, 0.0f); /* vectors on same side -- not possible */
|
||||
|
||||
/* compute half-vector of the refraction (eq. 16) */
|
||||
float3 ht = -(m_eta * omega_in + I);
|
||||
float3 ht;
|
||||
if(bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID) {
|
||||
/* for thin surfaces refraction approximately cancels and thus specular transmission is modelled
|
||||
* using a microfacet distribution which is simply reflected to the other side */
|
||||
ht = -(omega_in + I);
|
||||
}
|
||||
else {
|
||||
ht = -(m_eta * omega_in + I);
|
||||
}
|
||||
float3 Ht = normalize(ht);
|
||||
float cosHO = dot(Ht, I);
|
||||
float cosHI = dot(Ht, omega_in);
|
||||
@@ -438,7 +556,13 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, con
|
||||
|
||||
/* out = fabsf(cosHI * cosHO) * (m_eta * m_eta) * G * D / (cosNO * Ht2)
|
||||
* pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2 */
|
||||
float common = D * (m_eta * m_eta) / (cosNO * Ht2);
|
||||
float common;
|
||||
if(bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID) {
|
||||
common = D * 0.25f / cosNO;
|
||||
}
|
||||
else {
|
||||
common = D * (m_eta * m_eta) / (cosNO * Ht2);
|
||||
}
|
||||
float out = G * fabsf(cosHI * cosHO) * common;
|
||||
*pdf = G1o * fabsf(cosHO * cosHI) * common;
|
||||
|
||||
@@ -450,7 +574,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
|
||||
const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
|
||||
float alpha_x = bsdf->alpha_x;
|
||||
float alpha_y = bsdf->alpha_y;
|
||||
bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
|
||||
bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID || bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID;
|
||||
float3 N = bsdf->N;
|
||||
|
||||
float cosNO = dot(N, I);
|
||||
@@ -487,6 +611,16 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
|
||||
/* some high number for MIS */
|
||||
*pdf = 1e6f;
|
||||
*eval = make_float3(1e6f, 1e6f, 1e6f);
|
||||
|
||||
bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID
|
||||
|| bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID
|
||||
|| bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID);
|
||||
|
||||
/* if fresnel is used, calculate the color with reflection_color(...) */
|
||||
if(use_fresnel) {
|
||||
*pdf = 1.0f;
|
||||
*eval = reflection_color(bsdf, *omega_in, m);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* microfacet normal is visible to this ray */
|
||||
@@ -494,16 +628,32 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
|
||||
float alpha2 = alpha_x * alpha_y;
|
||||
float D, G1i;
|
||||
|
||||
bool is_disney_clearcoat = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID);
|
||||
|
||||
if(alpha_x == alpha_y) {
|
||||
/* isotropic */
|
||||
float cosThetaM2 = cosThetaM * cosThetaM;
|
||||
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
||||
float tanThetaM2 = 1/(cosThetaM2) - 1;
|
||||
D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
|
||||
|
||||
/* eval BRDF*cosNI */
|
||||
float cosNI = dot(N, *omega_in);
|
||||
|
||||
if(is_disney_clearcoat) {
|
||||
/* use GTR1 for clearcoat */
|
||||
D = D_GTR1(cosThetaM, bsdf->alpha_x);
|
||||
|
||||
/* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */
|
||||
alpha2 = 0.0625f;
|
||||
|
||||
/* recalculate G1o */
|
||||
G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
|
||||
}
|
||||
else {
|
||||
/* use GTR2 otherwise */
|
||||
D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
|
||||
}
|
||||
|
||||
/* eq. 34: now calculate G1(i,m) */
|
||||
G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
|
||||
}
|
||||
@@ -535,10 +685,14 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
|
||||
|
||||
/* see eval function for derivation */
|
||||
float common = (G1o * D) * 0.25f / cosNO;
|
||||
float out = G1i * common;
|
||||
*pdf = common;
|
||||
|
||||
*eval = make_float3(out, out, out);
|
||||
float3 F = reflection_color(bsdf, *omega_in, m);
|
||||
if(is_disney_clearcoat) {
|
||||
F *= 0.25f * bsdf->extra->clearcoat;
|
||||
}
|
||||
|
||||
*eval = G1i * common * F;
|
||||
}
|
||||
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
@@ -558,6 +712,10 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
|
||||
float m_eta = bsdf->ior, fresnel;
|
||||
bool inside;
|
||||
|
||||
if(bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID) {
|
||||
m_eta = 1.0f;
|
||||
}
|
||||
|
||||
fresnel = fresnel_dielectric(m_eta, m, I, &R, &T,
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy,
|
||||
@@ -927,7 +1085,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderCl
|
||||
*domega_in_dy = dTdy;
|
||||
#endif
|
||||
|
||||
if(alpha_x*alpha_y <= 1e-7f || fabsf(m_eta - 1.0f) < 1e-4f) {
|
||||
if(alpha_x*alpha_y <= 1e-7f || (fabsf(m_eta - 1.0f) < 1e-4f && bsdf->type != CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID)) {
|
||||
/* some high number for MIS */
|
||||
*pdf = 1e6f;
|
||||
*eval = make_float3(1e6f, 1e6f, 1e6f);
|
||||
@@ -954,7 +1112,13 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderCl
|
||||
Ht2 *= Ht2;
|
||||
|
||||
/* see eval function for derivation */
|
||||
float common = D * (m_eta * m_eta) / (cosNO * Ht2);
|
||||
float common;
|
||||
if(bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID) {
|
||||
common = D * 0.25f / cosNO;
|
||||
}
|
||||
else {
|
||||
common = D * (m_eta * m_eta) / (cosNO * Ht2);
|
||||
}
|
||||
float out = G * fabsf(cosHI * cosHO) * common;
|
||||
*pdf = G1o * cosHO * fabsf(cosHI) * common;
|
||||
|
||||
|
@@ -345,8 +345,9 @@ ccl_device int bsdf_microfacet_multi_ggx_common_setup(MicrofacetBsdf *bsdf)
|
||||
bsdf->extra->color.x = saturate(bsdf->extra->color.x);
|
||||
bsdf->extra->color.y = saturate(bsdf->extra->color.y);
|
||||
bsdf->extra->color.z = saturate(bsdf->extra->color.z);
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
|
||||
bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
|
||||
bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
|
||||
bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
|
||||
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
|
||||
}
|
||||
@@ -356,6 +357,18 @@ ccl_device int bsdf_microfacet_multi_ggx_aniso_setup(MicrofacetBsdf *bsdf)
|
||||
if(is_zero(bsdf->T))
|
||||
bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
|
||||
|
||||
return bsdf_microfacet_multi_ggx_common_setup(bsdf);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_multi_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf)
|
||||
{
|
||||
if(is_zero(bsdf->T))
|
||||
bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID;
|
||||
|
||||
return bsdf_microfacet_multi_ggx_common_setup(bsdf);
|
||||
}
|
||||
|
||||
@@ -363,6 +376,26 @@ ccl_device int bsdf_microfacet_multi_ggx_setup(MicrofacetBsdf *bsdf)
|
||||
{
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
|
||||
|
||||
return bsdf_microfacet_multi_ggx_common_setup(bsdf);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_multi_ggx_fresnel_setup(MicrofacetBsdf *bsdf)
|
||||
{
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID;
|
||||
|
||||
return bsdf_microfacet_multi_ggx_common_setup(bsdf);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_multi_ggx_refraction_setup(MicrofacetBsdf *bsdf)
|
||||
{
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
|
||||
|
||||
return bsdf_microfacet_multi_ggx_common_setup(bsdf);
|
||||
}
|
||||
|
||||
@@ -378,6 +411,8 @@ ccl_device float3 bsdf_microfacet_multi_ggx_eval_reflect(const ShaderClosure *sc
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID);
|
||||
|
||||
bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y);
|
||||
float3 X, Y, Z;
|
||||
Z = bsdf->N;
|
||||
@@ -393,7 +428,7 @@ ccl_device float3 bsdf_microfacet_multi_ggx_eval_reflect(const ShaderClosure *sc
|
||||
*pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
|
||||
else
|
||||
*pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x);
|
||||
return mf_eval_glossy(localI, localO, true, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, NULL, NULL);
|
||||
return mf_eval_glossy(localI, localO, true, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, NULL, NULL, bsdf->ior, use_fresnel, bsdf->extra->cspec0);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals *kg, 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, ccl_addr_space uint *lcg_state)
|
||||
@@ -410,6 +445,8 @@ ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals *kg, const ShaderC
|
||||
return LABEL_REFLECT|LABEL_SINGULAR;
|
||||
}
|
||||
|
||||
bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID);
|
||||
|
||||
bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y);
|
||||
if(is_aniso)
|
||||
make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
|
||||
@@ -419,7 +456,7 @@ ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals *kg, const ShaderC
|
||||
float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
|
||||
float3 localO;
|
||||
|
||||
*eval = mf_sample_glossy(localI, &localO, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, NULL, NULL);
|
||||
*eval = mf_sample_glossy(localI, &localO, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, NULL, NULL, bsdf->ior, use_fresnel, bsdf->extra->cspec0);
|
||||
if(is_aniso)
|
||||
*pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
|
||||
else
|
||||
@@ -450,6 +487,23 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_setup(MicrofacetBsdf *bsdf)
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(MicrofacetBsdf *bsdf)
|
||||
{
|
||||
bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
bsdf->ior = max(0.0f, bsdf->ior);
|
||||
bsdf->extra->color.x = saturate(bsdf->extra->color.x);
|
||||
bsdf->extra->color.y = saturate(bsdf->extra->color.y);
|
||||
bsdf->extra->color.z = saturate(bsdf->extra->color.z);
|
||||
bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
|
||||
bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
|
||||
bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID;
|
||||
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) {
|
||||
const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
|
||||
|
||||
@@ -465,7 +519,7 @@ ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_transmit(const ShaderClos
|
||||
float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
|
||||
|
||||
*pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
|
||||
return mf_eval_glass(localI, localO, false, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior);
|
||||
return mf_eval_glass(localI, localO, false, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, false, bsdf->extra->color);
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) {
|
||||
@@ -475,6 +529,8 @@ ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_reflect(const ShaderClosu
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
|
||||
|
||||
float3 X, Y, Z;
|
||||
Z = bsdf->N;
|
||||
make_orthonormals(Z, &X, &Y);
|
||||
@@ -483,7 +539,7 @@ ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_reflect(const ShaderClosu
|
||||
float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
|
||||
|
||||
*pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
|
||||
return mf_eval_glass(localI, localO, true, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior);
|
||||
return mf_eval_glass(localI, localO, true, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, use_fresnel, bsdf->extra->cspec0);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals *kg, 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, ccl_addr_space uint *lcg_state)
|
||||
@@ -525,12 +581,14 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals *kg, const S
|
||||
}
|
||||
}
|
||||
|
||||
bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
|
||||
|
||||
make_orthonormals(Z, &X, &Y);
|
||||
|
||||
float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
|
||||
float3 localO;
|
||||
|
||||
*eval = mf_sample_glass(localI, &localO, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior);
|
||||
*eval = mf_sample_glass(localI, &localO, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, use_fresnel, bsdf->extra->cspec0);
|
||||
*pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
|
||||
*eval *= *pdf;
|
||||
|
||||
|
@@ -35,8 +35,13 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
|
||||
ccl_addr_space uint *lcg_state
|
||||
#ifdef MF_MULTI_GLASS
|
||||
, const float eta
|
||||
, bool use_fresnel
|
||||
, const float3 cspec0
|
||||
#elif defined(MF_MULTI_GLOSSY)
|
||||
, float3 *n, float3 *k
|
||||
, float3 *n, float3 *k
|
||||
, const float eta
|
||||
, bool use_fresnel
|
||||
, const float3 cspec0
|
||||
#endif
|
||||
)
|
||||
{
|
||||
@@ -71,12 +76,20 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
|
||||
|
||||
/* Analytically compute single scattering for lower noise. */
|
||||
float3 eval;
|
||||
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
|
||||
#ifdef MF_MULTI_GLASS
|
||||
eval = mf_eval_phase_glass(-wi, lambda_r, wo, wo_outside, alpha, eta);
|
||||
if(wo_outside)
|
||||
eval *= -lambda_r / (shadowing_lambda - lambda_r);
|
||||
else
|
||||
eval *= -lambda_r * beta(-lambda_r, shadowing_lambda+1.0f);
|
||||
|
||||
float F0 = fresnel_dielectric_cos(1.0f, eta);
|
||||
if(use_fresnel) {
|
||||
throughput = interpolate_fresnel_color(wi, normalize(wi + wo), eta, F0, cspec0);
|
||||
|
||||
eval *= throughput;
|
||||
}
|
||||
#elif defined(MF_MULTI_DIFFUSE)
|
||||
/* Diffuse has no special closed form for the single scattering bounce */
|
||||
eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
@@ -94,6 +107,13 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
|
||||
else {
|
||||
eval = make_float3(val, val, val);
|
||||
}
|
||||
|
||||
float F0 = fresnel_dielectric_cos(1.0f, eta);
|
||||
if(use_fresnel) {
|
||||
throughput = interpolate_fresnel_color(wi, wh, eta, F0, cspec0);
|
||||
|
||||
eval = throughput * val;
|
||||
}
|
||||
#endif
|
||||
|
||||
float3 wr = -wi;
|
||||
@@ -101,7 +121,6 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
|
||||
float C1_r = 1.0f;
|
||||
float G1_r = 0.0f;
|
||||
bool outside = true;
|
||||
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
|
||||
|
||||
for(int order = 0; order < 10; order++) {
|
||||
/* Sample microfacet height and normal */
|
||||
@@ -116,6 +135,18 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
|
||||
const float G2_G1 = -lambda_r / (shadowing_lambda - lambda_r);
|
||||
eval += throughput * G2_G1 * mf_eval_phase_diffuse(wo, wm);
|
||||
}
|
||||
#endif
|
||||
#ifdef MF_MULTI_GLASS
|
||||
if(order == 0 && use_fresnel) {
|
||||
/* Evaluate amount of scattering towards wo on this microfacet. */
|
||||
float3 phase;
|
||||
if(outside)
|
||||
phase = mf_eval_phase_glass(wr, lambda_r, wo, wo_outside, alpha, eta);
|
||||
else
|
||||
phase = mf_eval_phase_glass(wr, lambda_r, -wo, !wo_outside, alpha, 1.0f / eta);
|
||||
|
||||
eval = throughput * phase * mf_G1(wo_outside ? wo : -wo, mf_C1((outside == wo_outside) ? hr : -hr), shadowing_lambda);
|
||||
}
|
||||
#endif
|
||||
if(order > 0) {
|
||||
/* Evaluate amount of scattering towards wo on this microfacet. */
|
||||
@@ -136,23 +167,39 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
|
||||
/* Bounce from the microfacet. */
|
||||
#ifdef MF_MULTI_GLASS
|
||||
bool next_outside;
|
||||
float3 wi_prev = -wr;
|
||||
wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, lcg_step_float_addrspace(lcg_state), &next_outside);
|
||||
if(!next_outside) {
|
||||
outside = !outside;
|
||||
wr = -wr;
|
||||
hr = -hr;
|
||||
}
|
||||
|
||||
if(use_fresnel && !next_outside) {
|
||||
throughput *= color;
|
||||
}
|
||||
else if(use_fresnel && order > 0) {
|
||||
throughput *= interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0);
|
||||
}
|
||||
#elif defined(MF_MULTI_DIFFUSE)
|
||||
wr = mf_sample_phase_diffuse(wm,
|
||||
lcg_step_float_addrspace(lcg_state),
|
||||
lcg_step_float_addrspace(lcg_state));
|
||||
#else /* MF_MULTI_GLOSSY */
|
||||
if(use_fresnel && order > 0) {
|
||||
throughput *= interpolate_fresnel_color(-wr, wm, eta, F0, cspec0);
|
||||
}
|
||||
wr = mf_sample_phase_glossy(-wr, n, k, &throughput, wm);
|
||||
#endif
|
||||
|
||||
lambda_r = mf_lambda(wr, alpha);
|
||||
|
||||
#if defined(MF_MULTI_GLOSSY) || defined(MF_MULTI_GLASS)
|
||||
if(!use_fresnel)
|
||||
throughput *= color;
|
||||
#else
|
||||
throughput *= color;
|
||||
#endif
|
||||
|
||||
C1_r = mf_C1(hr);
|
||||
G1_r = mf_G1(wr, C1_r, lambda_r);
|
||||
@@ -171,8 +218,13 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
|
||||
ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi, float3 *wo, const float3 color, const float alpha_x, const float alpha_y, ccl_addr_space uint *lcg_state
|
||||
#ifdef MF_MULTI_GLASS
|
||||
, const float eta
|
||||
, bool use_fresnel
|
||||
, const float3 cspec0
|
||||
#elif defined(MF_MULTI_GLOSSY)
|
||||
, float3 *n, float3 *k
|
||||
, const float eta
|
||||
, bool use_fresnel
|
||||
, const float3 cspec0
|
||||
#endif
|
||||
)
|
||||
{
|
||||
@@ -185,6 +237,17 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi, float3
|
||||
float C1_r = 1.0f;
|
||||
float G1_r = 0.0f;
|
||||
bool outside = true;
|
||||
#ifdef MF_MULTI_GLASS
|
||||
float F0 = fresnel_dielectric_cos(1.0f, eta);
|
||||
if(use_fresnel) {
|
||||
throughput = interpolate_fresnel_color(wi, normalize(wi + wr), eta, F0, cspec0);
|
||||
}
|
||||
#elif defined(MF_MULTI_GLOSSY)
|
||||
float F0 = fresnel_dielectric_cos(1.0f, eta);
|
||||
if(use_fresnel) {
|
||||
throughput = interpolate_fresnel_color(wi, normalize(wi + wr), eta, F0, cspec0);
|
||||
}
|
||||
#endif
|
||||
|
||||
int order;
|
||||
for(order = 0; order < 10; order++) {
|
||||
@@ -199,23 +262,51 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi, float3
|
||||
lcg_step_float_addrspace(lcg_state)));
|
||||
|
||||
/* First-bounce color is already accounted for in mix weight. */
|
||||
#if defined(MF_MULTI_GLASS) || defined(MF_MULTI_GLOSSY)
|
||||
if(!use_fresnel && order > 0)
|
||||
throughput *= color;
|
||||
#else
|
||||
if(order > 0)
|
||||
throughput *= color;
|
||||
#endif
|
||||
|
||||
/* Bounce from the microfacet. */
|
||||
#ifdef MF_MULTI_GLASS
|
||||
bool next_outside;
|
||||
float3 wi_prev = -wr;
|
||||
wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, lcg_step_float_addrspace(lcg_state), &next_outside);
|
||||
if(!next_outside) {
|
||||
hr = -hr;
|
||||
wr = -wr;
|
||||
outside = !outside;
|
||||
}
|
||||
|
||||
if(use_fresnel) {
|
||||
if(!next_outside) {
|
||||
throughput *= color;
|
||||
}
|
||||
else {
|
||||
float3 t_color = interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0);
|
||||
|
||||
if(order == 0)
|
||||
throughput = t_color;
|
||||
else
|
||||
throughput *= t_color;
|
||||
}
|
||||
}
|
||||
#elif defined(MF_MULTI_DIFFUSE)
|
||||
wr = mf_sample_phase_diffuse(wm,
|
||||
lcg_step_float_addrspace(lcg_state),
|
||||
lcg_step_float_addrspace(lcg_state));
|
||||
#else /* MF_MULTI_GLOSSY */
|
||||
if(use_fresnel) {
|
||||
float3 t_color = interpolate_fresnel_color(-wr, wm, eta, F0, cspec0);
|
||||
|
||||
if(order == 0)
|
||||
throughput = t_color;
|
||||
else
|
||||
throughput *= t_color;
|
||||
}
|
||||
wr = mf_sample_phase_glossy(-wr, n, k, &throughput, wm);
|
||||
#endif
|
||||
|
||||
|
@@ -124,6 +124,13 @@ ccl_device float3 fresnel_conductor(float cosi, const float3 eta, const float3 k
|
||||
return(Rparl2 + Rperp2) * 0.5f;
|
||||
}
|
||||
|
||||
ccl_device float schlick_fresnel(float u)
|
||||
{
|
||||
float m = clamp(1.0f - u, 0.0f, 1.0f);
|
||||
float m2 = m * m;
|
||||
return m2 * m2 * m; // pow(m, 5)
|
||||
}
|
||||
|
||||
ccl_device float smooth_step(float edge0, float edge1, float x)
|
||||
{
|
||||
float result;
|
||||
@@ -136,6 +143,19 @@ ccl_device float smooth_step(float edge0, float edge1, float x)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Calculate the fresnel color which is a blend between white and the F0 color (cspec0) */
|
||||
ccl_device_forceinline float3 interpolate_fresnel_color(float3 L, float3 H, float ior, float F0, float3 cspec0) {
|
||||
/* Calculate the fresnel interpolation factor
|
||||
* The value from fresnel_dielectric_cos(...) has to be normalized because
|
||||
* the cspec0 keeps the F0 color
|
||||
*/
|
||||
float F0_norm = 1.0f / (1.0f - F0);
|
||||
float FH = (fresnel_dielectric_cos(dot(L, H), ior) - F0) * F0_norm;
|
||||
|
||||
/* Blend between white and a specular color with respect to the fresnel */
|
||||
return cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __BSDF_UTIL_H__ */
|
||||
|
@@ -28,6 +28,7 @@ typedef ccl_addr_space struct Bssrdf {
|
||||
float texture_blur;
|
||||
float albedo;
|
||||
float3 N;
|
||||
float3 base_color;
|
||||
} Bssrdf;
|
||||
|
||||
/* Planar Truncated Gaussian
|
||||
@@ -360,10 +361,28 @@ ccl_device int bssrdf_setup(Bssrdf *bssrdf, ClosureType type)
|
||||
{
|
||||
if(bssrdf->radius < BSSRDF_MIN_RADIUS) {
|
||||
/* revert to diffuse BSDF if radius too small */
|
||||
DiffuseBsdf *bsdf = (DiffuseBsdf*)bssrdf;
|
||||
bsdf->N = bssrdf->N;
|
||||
int flag = bsdf_diffuse_setup(bsdf);
|
||||
bsdf->type = CLOSURE_BSDF_BSSRDF_ID;
|
||||
int flag;
|
||||
if(type == CLOSURE_BSSRDF_DISNEY_ID) {
|
||||
float3 N = bssrdf->N;
|
||||
float3 weight = bssrdf->weight * bssrdf->base_color;
|
||||
float sample_weight = bssrdf->sample_weight;
|
||||
|
||||
DisneyDiffuseBsdf *bsdf = (DisneyDiffuseBsdf*)bssrdf;
|
||||
|
||||
bsdf->N = N;
|
||||
bsdf->flatness = 0.0f;
|
||||
bsdf->weight = weight;
|
||||
bsdf->sample_weight = sample_weight;
|
||||
flag = bsdf_disney_diffuse_setup(bsdf);
|
||||
bsdf->type = CLOSURE_BSDF_BSSRDF_DISNEY_ID;
|
||||
}
|
||||
else {
|
||||
DiffuseBsdf *bsdf = (DiffuseBsdf*)bssrdf;
|
||||
bsdf->N = bssrdf->N;
|
||||
flag = bsdf_diffuse_setup(bsdf);
|
||||
bsdf->type = CLOSURE_BSDF_BSSRDF_ID;
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
else {
|
||||
@@ -371,7 +390,7 @@ ccl_device int bssrdf_setup(Bssrdf *bssrdf, ClosureType type)
|
||||
bssrdf->sharpness = saturate(bssrdf->sharpness);
|
||||
bssrdf->type = type;
|
||||
|
||||
if(type == CLOSURE_BSSRDF_BURLEY_ID) {
|
||||
if(type == CLOSURE_BSSRDF_BURLEY_ID || type == CLOSURE_BSSRDF_DISNEY_ID) {
|
||||
bssrdf_burley_setup(bssrdf);
|
||||
}
|
||||
|
||||
@@ -385,7 +404,7 @@ ccl_device void bssrdf_sample(const ShaderClosure *sc, float xi, float *r, float
|
||||
bssrdf_cubic_sample(sc, xi, r, h);
|
||||
else if(sc->type == CLOSURE_BSSRDF_GAUSSIAN_ID)
|
||||
bssrdf_gaussian_sample(sc, xi, r, h);
|
||||
else /*if(sc->type == CLOSURE_BSSRDF_BURLEY_ID)*/
|
||||
else /*if(sc->type == CLOSURE_BSSRDF_BURLEY_ID || sc->type == CLOSURE_BSSRDF_DISNEY_ID)*/
|
||||
bssrdf_burley_sample(sc, xi, r, h);
|
||||
}
|
||||
|
||||
@@ -395,7 +414,7 @@ ccl_device_forceinline float bssrdf_pdf(const ShaderClosure *sc, float r)
|
||||
return bssrdf_cubic_pdf(sc, r);
|
||||
else if(sc->type == CLOSURE_BSSRDF_GAUSSIAN_ID)
|
||||
return bssrdf_gaussian_pdf(sc, r);
|
||||
else /*if(sc->type == CLOSURE_BSSRDF_BURLEY_ID)*/
|
||||
else /*if(sc->type == CLOSURE_BSSRDF_BURLEY_ID || sc->type == CLOSURE_BSSRDF_DISNEY_ID)*/
|
||||
return bssrdf_burley_pdf(sc, r);
|
||||
}
|
||||
|
||||
|
@@ -140,7 +140,7 @@ ccl_device_inline float3 subsurface_scatter_eval(ShaderData *sd,
|
||||
}
|
||||
|
||||
/* replace closures with a single diffuse bsdf closure after scatter step */
|
||||
ccl_device void subsurface_scatter_setup_diffuse_bsdf(ShaderData *sd, float3 weight, bool hit, float3 N)
|
||||
ccl_device void subsurface_scatter_setup_diffuse_bsdf(ShaderData *sd, ShaderClosure *sc, float3 weight, bool hit, float3 N)
|
||||
{
|
||||
sd->flag &= ~SD_CLOSURE_FLAGS;
|
||||
sd->randb_closure = 0.0f;
|
||||
@@ -148,15 +148,31 @@ ccl_device void subsurface_scatter_setup_diffuse_bsdf(ShaderData *sd, float3 wei
|
||||
sd->num_closure_extra = 0;
|
||||
|
||||
if(hit) {
|
||||
DiffuseBsdf *bsdf = (DiffuseBsdf*)bsdf_alloc(sd, sizeof(DiffuseBsdf), weight);
|
||||
Bssrdf *bssrdf = (Bssrdf *)sc;
|
||||
if(bssrdf->type == CLOSURE_BSSRDF_DISNEY_ID) {
|
||||
DisneyDiffuseBsdf *bsdf = (DisneyDiffuseBsdf*)bsdf_alloc(sd, sizeof(DisneyDiffuseBsdf), weight * bssrdf->base_color);
|
||||
|
||||
if(bsdf) {
|
||||
bsdf->N = N;
|
||||
sd->flag |= bsdf_diffuse_setup(bsdf);
|
||||
if(bsdf) {
|
||||
bsdf->N = N;
|
||||
bsdf->flatness = 0.0f;
|
||||
sd->flag |= bsdf_disney_diffuse_setup(bsdf);
|
||||
|
||||
/* replace CLOSURE_BSDF_DIFFUSE_ID with this special ID so render passes
|
||||
* can recognize it as not being a regular diffuse closure */
|
||||
bsdf->type = CLOSURE_BSDF_BSSRDF_ID;
|
||||
/* replace CLOSURE_BSDF_DISNEY_DIFFUSE_ID with this special ID so render passes
|
||||
* can recognize it as not being a regular Disney diffuse closure */
|
||||
bsdf->type = CLOSURE_BSDF_BSSRDF_DISNEY_ID;
|
||||
}
|
||||
}
|
||||
else {
|
||||
DiffuseBsdf *bsdf = (DiffuseBsdf*)bsdf_alloc(sd, sizeof(DiffuseBsdf), weight);
|
||||
|
||||
if(bsdf) {
|
||||
bsdf->N = N;
|
||||
sd->flag |= bsdf_diffuse_setup(bsdf);
|
||||
|
||||
/* replace CLOSURE_BSDF_DIFFUSE_ID with this special ID so render passes
|
||||
* can recognize it as not being a regular diffuse closure */
|
||||
bsdf->type = CLOSURE_BSDF_BSSRDF_ID;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -373,7 +389,7 @@ ccl_device_noinline void subsurface_scatter_multi_setup(
|
||||
subsurface_color_bump_blur(kg, sd, state, state_flag, &weight, &N);
|
||||
|
||||
/* Setup diffuse BSDF. */
|
||||
subsurface_scatter_setup_diffuse_bsdf(sd, weight, true, N);
|
||||
subsurface_scatter_setup_diffuse_bsdf(sd, sc, weight, true, N);
|
||||
}
|
||||
|
||||
/* subsurface scattering step, from a point on the surface to another nearby point on the same object */
|
||||
@@ -463,7 +479,7 @@ ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, PathS
|
||||
subsurface_color_bump_blur(kg, sd, state, state_flag, &eval, &N);
|
||||
|
||||
/* setup diffuse bsdf */
|
||||
subsurface_scatter_setup_diffuse_bsdf(sd, eval, (ss_isect.num_hits > 0), N);
|
||||
subsurface_scatter_setup_diffuse_bsdf(sd, sc, eval, (ss_isect.num_hits > 0), N);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -39,7 +39,9 @@
|
||||
#include "kernel_montecarlo.h"
|
||||
|
||||
#include "closure/alloc.h"
|
||||
#include "closure/bsdf_util.h"
|
||||
#include "closure/bsdf_diffuse.h"
|
||||
#include "closure/bsdf_disney_diffuse.h"
|
||||
#include "closure/bssrdf.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
@@ -78,6 +80,7 @@ public:
|
||||
bssrdf->albedo = albedo.x;
|
||||
bssrdf->sharpness = sharpness;
|
||||
bssrdf->N = params.N;
|
||||
bssrdf->base_color = params.base_color;
|
||||
ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)type);
|
||||
}
|
||||
|
||||
@@ -89,6 +92,7 @@ public:
|
||||
bssrdf->albedo = albedo.y;
|
||||
bssrdf->sharpness = sharpness;
|
||||
bssrdf->N = params.N;
|
||||
bssrdf->base_color = params.base_color;
|
||||
ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)type);
|
||||
}
|
||||
|
||||
@@ -100,6 +104,7 @@ public:
|
||||
bssrdf->albedo = albedo.z;
|
||||
bssrdf->sharpness = sharpness;
|
||||
bssrdf->N = params.N;
|
||||
bssrdf->base_color = params.base_color;
|
||||
ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)type);
|
||||
}
|
||||
}
|
||||
@@ -180,5 +185,31 @@ ClosureParam *closure_bssrdf_burley_params()
|
||||
|
||||
CCLOSURE_PREPARE(closure_bssrdf_burley_prepare, BurleyBSSRDFClosure)
|
||||
|
||||
/* Disney */
|
||||
|
||||
class DisneyBSSRDFClosure : public CBSSRDFClosure {
|
||||
public:
|
||||
void setup(ShaderData *sd, int path_flag, float3 weight)
|
||||
{
|
||||
alloc(sd, path_flag, weight, CLOSURE_BSSRDF_DISNEY_ID);
|
||||
}
|
||||
};
|
||||
|
||||
ClosureParam *closure_bssrdf_disney_params()
|
||||
{
|
||||
static ClosureParam params[] = {
|
||||
CLOSURE_FLOAT3_PARAM(DisneyBSSRDFClosure, params.N),
|
||||
CLOSURE_FLOAT3_PARAM(DisneyBSSRDFClosure, radius),
|
||||
CLOSURE_FLOAT_PARAM(DisneyBSSRDFClosure, params.texture_blur),
|
||||
CLOSURE_FLOAT3_PARAM(DisneyBSSRDFClosure, params.base_color),
|
||||
CLOSURE_FLOAT3_PARAM(DisneyBSSRDFClosure, albedo),
|
||||
CLOSURE_STRING_KEYPARAM(DisneyBSSRDFClosure, label, "label"),
|
||||
CLOSURE_FINISH_PARAM(DisneyBSSRDFClosure)
|
||||
};
|
||||
return params;
|
||||
}
|
||||
|
||||
CCLOSURE_PREPARE(closure_bssrdf_disney_prepare, DisneyBSSRDFClosure)
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
@@ -59,6 +59,8 @@
|
||||
#include "closure/bsdf_ashikhmin_shirley.h"
|
||||
#include "closure/bsdf_toon.h"
|
||||
#include "closure/bsdf_hair.h"
|
||||
#include "closure/bsdf_disney_diffuse.h"
|
||||
#include "closure/bsdf_disney_sheen.h"
|
||||
#include "closure/volume.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
@@ -175,6 +177,75 @@ VOLUME_CLOSURE_CLASS_END(VolumeHenyeyGreenstein, henyey_greenstein)
|
||||
VOLUME_CLOSURE_CLASS_BEGIN(VolumeAbsorption, absorption, ShaderClosure, LABEL_SINGULAR)
|
||||
VOLUME_CLOSURE_CLASS_END(VolumeAbsorption, absorption)
|
||||
|
||||
BSDF_CLOSURE_CLASS_BEGIN(DisneyDiffuse, disney_diffuse, DisneyDiffuseBsdf, LABEL_DIFFUSE)
|
||||
CLOSURE_FLOAT3_PARAM(DisneyDiffuseClosure, params.N),
|
||||
CLOSURE_FLOAT_PARAM(DisneyDiffuseClosure, params.roughness),
|
||||
CLOSURE_FLOAT_PARAM(DisneyDiffuseClosure, params.flatness),
|
||||
BSDF_CLOSURE_CLASS_END(DisneyDiffuse, disney_diffuse)
|
||||
|
||||
BSDF_CLOSURE_CLASS_BEGIN(DisneyDiffuseTransmit, disney_diffuse_transmit, DisneyDiffuseBsdf, LABEL_DIFFUSE|LABEL_TRANSMIT)
|
||||
CLOSURE_FLOAT3_PARAM(DisneyDiffuseTransmitClosure, params.N),
|
||||
CLOSURE_FLOAT_PARAM(DisneyDiffuseTransmitClosure, params.roughness),
|
||||
CLOSURE_FLOAT_PARAM(DisneyDiffuseTransmitClosure, params.flatness),
|
||||
BSDF_CLOSURE_CLASS_END(DisneyDiffuseTransmit, disney_diffuse_transmit)
|
||||
|
||||
BSDF_CLOSURE_CLASS_BEGIN(DisneyRetroReflection, disney_retro_reflection, DisneyDiffuseBsdf, LABEL_DIFFUSE)
|
||||
CLOSURE_FLOAT3_PARAM(DisneyRetroReflectionClosure, params.N),
|
||||
CLOSURE_FLOAT_PARAM(DisneyRetroReflectionClosure, params.roughness),
|
||||
BSDF_CLOSURE_CLASS_END(DisneyRetroReflection, disney_retro_reflection)
|
||||
|
||||
BSDF_CLOSURE_CLASS_BEGIN(DisneySheen, disney_sheen, DisneySheenBsdf, LABEL_DIFFUSE)
|
||||
CLOSURE_FLOAT3_PARAM(DisneySheenClosure, params.N),
|
||||
BSDF_CLOSURE_CLASS_END(DisneySheen, disney_sheen)
|
||||
|
||||
/* DISNEY CLEARCOAT */
|
||||
class DisneyClearcoatClosure : public CBSDFClosure {
|
||||
public:
|
||||
MicrofacetBsdf params;
|
||||
float clearcoat, clearcoat_gloss;
|
||||
|
||||
MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
|
||||
{
|
||||
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc_osl(sd, sizeof(MicrofacetBsdf), weight, ¶ms);
|
||||
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
|
||||
if(bsdf && extra) {
|
||||
bsdf->extra = extra;
|
||||
|
||||
bsdf->ior = 1.5f;
|
||||
|
||||
bsdf->alpha_x = 0.1f * (1.0f - clearcoat_gloss) + 0.001f * clearcoat_gloss;
|
||||
bsdf->alpha_y = 0.1f * (1.0f - clearcoat_gloss) + 0.001f * clearcoat_gloss;
|
||||
|
||||
bsdf->extra->cspec0 = make_float3(0.04f, 0.04f, 0.04f);
|
||||
bsdf->extra->clearcoat = clearcoat;
|
||||
|
||||
return bsdf;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void setup(ShaderData *sd, int path_flag, float3 weight)
|
||||
{
|
||||
MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
|
||||
sd->flag |= (bsdf) ? bsdf_microfacet_ggx_clearcoat_setup(bsdf) : 0;
|
||||
}
|
||||
};
|
||||
|
||||
ClosureParam *closure_bsdf_disney_clearcoat_params()
|
||||
{
|
||||
static ClosureParam params[] = {
|
||||
CLOSURE_FLOAT3_PARAM(DisneyClearcoatClosure, params.N),
|
||||
CLOSURE_FLOAT_PARAM(DisneyClearcoatClosure, clearcoat),
|
||||
CLOSURE_FLOAT_PARAM(DisneyClearcoatClosure, clearcoat_gloss),
|
||||
CLOSURE_STRING_KEYPARAM(DisneyClearcoatClosure, label, "label"),
|
||||
CLOSURE_FINISH_PARAM(DisneyClearcoatClosure)
|
||||
};
|
||||
return params;
|
||||
}
|
||||
CCLOSURE_PREPARE(closure_bsdf_disney_clearcoat_prepare, DisneyClearcoatClosure)
|
||||
|
||||
|
||||
/* Registration */
|
||||
|
||||
static void register_closure(OSL::ShadingSystem *ss, const char *name, int id, OSL::ClosureParam *params, OSL::PrepareClosureFunc prepare)
|
||||
@@ -214,6 +285,16 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
|
||||
closure_bsdf_microfacet_multi_ggx_glass_params(), closure_bsdf_microfacet_multi_ggx_glass_prepare);
|
||||
register_closure(ss, "microfacet_multi_ggx_aniso", id++,
|
||||
closure_bsdf_microfacet_multi_ggx_aniso_params(), closure_bsdf_microfacet_multi_ggx_aniso_prepare);
|
||||
register_closure(ss, "microfacet_ggx_fresnel", id++,
|
||||
closure_bsdf_microfacet_ggx_fresnel_params(), closure_bsdf_microfacet_ggx_fresnel_prepare);
|
||||
register_closure(ss, "microfacet_ggx_aniso_fresnel", id++,
|
||||
closure_bsdf_microfacet_ggx_aniso_fresnel_params(), closure_bsdf_microfacet_ggx_aniso_fresnel_prepare);
|
||||
register_closure(ss, "microfacet_multi_ggx_fresnel", id++,
|
||||
closure_bsdf_microfacet_multi_ggx_fresnel_params(), closure_bsdf_microfacet_multi_ggx_fresnel_prepare);
|
||||
register_closure(ss, "microfacet_multi_ggx_glass_fresnel", id++,
|
||||
closure_bsdf_microfacet_multi_ggx_glass_fresnel_params(), closure_bsdf_microfacet_multi_ggx_glass_fresnel_prepare);
|
||||
register_closure(ss, "microfacet_multi_ggx_aniso_fresnel", id++,
|
||||
closure_bsdf_microfacet_multi_ggx_aniso_fresnel_params(), closure_bsdf_microfacet_multi_ggx_aniso_fresnel_prepare);
|
||||
register_closure(ss, "microfacet_beckmann", id++,
|
||||
bsdf_microfacet_beckmann_params(), bsdf_microfacet_beckmann_prepare);
|
||||
register_closure(ss, "microfacet_beckmann_aniso", id++,
|
||||
@@ -228,6 +309,16 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
|
||||
bsdf_diffuse_toon_params(), bsdf_diffuse_toon_prepare);
|
||||
register_closure(ss, "glossy_toon", id++,
|
||||
bsdf_glossy_toon_params(), bsdf_glossy_toon_prepare);
|
||||
register_closure(ss, "disney_diffuse", id++,
|
||||
bsdf_disney_diffuse_params(), bsdf_disney_diffuse_prepare);
|
||||
register_closure(ss, "disney_diffuse_transmit", id++,
|
||||
bsdf_disney_diffuse_transmit_params(), bsdf_disney_diffuse_transmit_prepare);
|
||||
register_closure(ss, "disney_retro_reflection", id++,
|
||||
bsdf_disney_retro_reflection_params(), bsdf_disney_retro_reflection_prepare);
|
||||
register_closure(ss, "disney_sheen", id++,
|
||||
bsdf_disney_sheen_params(), bsdf_disney_sheen_prepare);
|
||||
register_closure(ss, "disney_clearcoat", id++,
|
||||
closure_bsdf_disney_clearcoat_params(), closure_bsdf_disney_clearcoat_prepare);
|
||||
|
||||
register_closure(ss, "emission", id++,
|
||||
closure_emission_params(), closure_emission_prepare);
|
||||
@@ -247,6 +338,8 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
|
||||
closure_bssrdf_gaussian_params(), closure_bssrdf_gaussian_prepare);
|
||||
register_closure(ss, "bssrdf_burley", id++,
|
||||
closure_bssrdf_burley_params(), closure_bssrdf_burley_prepare);
|
||||
register_closure(ss, "bssrdf_disney", id++,
|
||||
closure_bssrdf_disney_params(), closure_bssrdf_disney_prepare);
|
||||
|
||||
register_closure(ss, "hair_reflection", id++,
|
||||
bsdf_hair_reflection_params(), bsdf_hair_reflection_prepare);
|
||||
@@ -277,6 +370,86 @@ bool CBSDFClosure::skip(const ShaderData *sd, int path_flag, int scattering)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* GGX closures with Fresnel */
|
||||
|
||||
class MicrofacetFresnelClosure : public CBSDFClosure {
|
||||
public:
|
||||
MicrofacetBsdf params;
|
||||
float3 color;
|
||||
float3 cspec0;
|
||||
|
||||
MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
|
||||
{
|
||||
/* Technically, the MultiGGX Glass closure may also transmit. However,
|
||||
* since this is set statically and only used for caustic flags, this
|
||||
* is probably as good as it gets. */
|
||||
if(!skip(sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
|
||||
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc_osl(sd, sizeof(MicrofacetBsdf), weight, ¶ms);
|
||||
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
|
||||
if(bsdf && extra) {
|
||||
bsdf->extra = extra;
|
||||
bsdf->extra->color = color;
|
||||
bsdf->extra->cspec0 = cspec0;
|
||||
return bsdf;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
class MicrofacetGGXFresnelClosure : public MicrofacetFresnelClosure {
|
||||
public:
|
||||
void setup(ShaderData *sd, int path_flag, float3 weight)
|
||||
{
|
||||
MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
|
||||
sd->flag |= (bsdf) ? bsdf_microfacet_ggx_fresnel_setup(bsdf) : 0;
|
||||
}
|
||||
};
|
||||
|
||||
ClosureParam *closure_bsdf_microfacet_ggx_fresnel_params()
|
||||
{
|
||||
static ClosureParam params[] = {
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, params.N),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.alpha_x),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.ior),
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, color),
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, cspec0),
|
||||
CLOSURE_STRING_KEYPARAM(MicrofacetGGXFresnelClosure, label, "label"),
|
||||
CLOSURE_FINISH_PARAM(MicrofacetGGXFresnelClosure)
|
||||
};
|
||||
return params;
|
||||
}
|
||||
CCLOSURE_PREPARE(closure_bsdf_microfacet_ggx_fresnel_prepare, MicrofacetGGXFresnelClosure);
|
||||
|
||||
class MicrofacetGGXAnisoFresnelClosure : public MicrofacetFresnelClosure {
|
||||
public:
|
||||
void setup(ShaderData *sd, int path_flag, float3 weight)
|
||||
{
|
||||
MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
|
||||
sd->flag |= (bsdf) ? bsdf_microfacet_ggx_aniso_fresnel_setup(bsdf) : 0;
|
||||
}
|
||||
};
|
||||
|
||||
ClosureParam *closure_bsdf_microfacet_ggx_aniso_fresnel_params()
|
||||
{
|
||||
static ClosureParam params[] = {
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, params.N),
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, params.T),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.alpha_x),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.alpha_y),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.ior),
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, color),
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, cspec0),
|
||||
CLOSURE_STRING_KEYPARAM(MicrofacetGGXFresnelClosure, label, "label"),
|
||||
CLOSURE_FINISH_PARAM(MicrofacetGGXFresnelClosure)
|
||||
};
|
||||
return params;
|
||||
}
|
||||
CCLOSURE_PREPARE(closure_bsdf_microfacet_ggx_aniso_fresnel_prepare, MicrofacetGGXAnisoFresnelClosure);
|
||||
|
||||
|
||||
/* Multiscattering GGX closures */
|
||||
|
||||
class MicrofacetMultiClosure : public CBSDFClosure {
|
||||
@@ -286,7 +459,7 @@ public:
|
||||
|
||||
MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
|
||||
{
|
||||
/* Technically, the MultiGGX Glass closure may also transmit. However,
|
||||
/* Technically, the MultiGGX closure may also transmit. However,
|
||||
* since this is set statically and only used for caustic flags, this
|
||||
* is probably as good as it gets. */
|
||||
if(!skip(sd, path_flag, LABEL_GLOSSY|LABEL_REFLECT)) {
|
||||
@@ -374,5 +547,110 @@ ClosureParam *closure_bsdf_microfacet_multi_ggx_glass_params()
|
||||
}
|
||||
CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_glass_prepare, MicrofacetMultiGGXGlassClosure);
|
||||
|
||||
|
||||
/* Multiscattering GGX closures with Fresnel */
|
||||
|
||||
class MicrofacetMultiFresnelClosure : public CBSDFClosure {
|
||||
public:
|
||||
MicrofacetBsdf params;
|
||||
float3 color;
|
||||
float3 cspec0;
|
||||
|
||||
MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
|
||||
{
|
||||
/* Technically, the MultiGGX closure may also transmit. However,
|
||||
* since this is set statically and only used for caustic flags, this
|
||||
* is probably as good as it gets. */
|
||||
if(!skip(sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
|
||||
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc_osl(sd, sizeof(MicrofacetBsdf), weight, ¶ms);
|
||||
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
|
||||
if(bsdf && extra) {
|
||||
bsdf->extra = extra;
|
||||
bsdf->extra->color = color;
|
||||
bsdf->extra->cspec0 = cspec0;
|
||||
return bsdf;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
class MicrofacetMultiGGXFresnelClosure : public MicrofacetMultiFresnelClosure {
|
||||
public:
|
||||
void setup(ShaderData *sd, int path_flag, float3 weight)
|
||||
{
|
||||
MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
|
||||
sd->flag |= (bsdf) ? bsdf_microfacet_multi_ggx_fresnel_setup(bsdf) : 0;
|
||||
}
|
||||
};
|
||||
|
||||
ClosureParam *closure_bsdf_microfacet_multi_ggx_fresnel_params()
|
||||
{
|
||||
static ClosureParam params[] = {
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.N),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_x),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.ior),
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, color),
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, cspec0),
|
||||
CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXFresnelClosure, label, "label"),
|
||||
CLOSURE_FINISH_PARAM(MicrofacetMultiGGXFresnelClosure)
|
||||
};
|
||||
return params;
|
||||
}
|
||||
CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_fresnel_prepare, MicrofacetMultiGGXFresnelClosure);
|
||||
|
||||
class MicrofacetMultiGGXAnisoFresnelClosure : public MicrofacetMultiFresnelClosure {
|
||||
public:
|
||||
void setup(ShaderData *sd, int path_flag, float3 weight)
|
||||
{
|
||||
MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
|
||||
sd->flag |= (bsdf) ? bsdf_microfacet_multi_ggx_aniso_fresnel_setup(bsdf) : 0;
|
||||
}
|
||||
};
|
||||
|
||||
ClosureParam *closure_bsdf_microfacet_multi_ggx_aniso_fresnel_params()
|
||||
{
|
||||
static ClosureParam params[] = {
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.N),
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.T),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_x),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_y),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.ior),
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, color),
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, cspec0),
|
||||
CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXFresnelClosure, label, "label"),
|
||||
CLOSURE_FINISH_PARAM(MicrofacetMultiGGXFresnelClosure)
|
||||
};
|
||||
return params;
|
||||
}
|
||||
CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_aniso_fresnel_prepare, MicrofacetMultiGGXAnisoFresnelClosure);
|
||||
|
||||
class MicrofacetMultiGGXGlassFresnelClosure : public MicrofacetMultiFresnelClosure {
|
||||
public:
|
||||
MicrofacetMultiGGXGlassFresnelClosure() : MicrofacetMultiFresnelClosure() {}
|
||||
|
||||
void setup(ShaderData *sd, int path_flag, float3 weight)
|
||||
{
|
||||
MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
|
||||
sd->flag |= (bsdf) ? bsdf_microfacet_multi_ggx_glass_fresnel_setup(bsdf) : 0;
|
||||
}
|
||||
};
|
||||
|
||||
ClosureParam *closure_bsdf_microfacet_multi_ggx_glass_fresnel_params()
|
||||
{
|
||||
static ClosureParam params[] = {
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.N),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_x),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.ior),
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, color),
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, cspec0),
|
||||
CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXFresnelClosure, label, "label"),
|
||||
CLOSURE_FINISH_PARAM(MicrofacetMultiGGXFresnelClosure)
|
||||
};
|
||||
return params;
|
||||
}
|
||||
CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_glass_fresnel_prepare, MicrofacetMultiGGXGlassFresnelClosure);
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
@@ -51,10 +51,16 @@ OSL::ClosureParam *closure_bsdf_phong_ramp_params();
|
||||
OSL::ClosureParam *closure_bssrdf_cubic_params();
|
||||
OSL::ClosureParam *closure_bssrdf_gaussian_params();
|
||||
OSL::ClosureParam *closure_bssrdf_burley_params();
|
||||
OSL::ClosureParam *closure_bssrdf_disney_params();
|
||||
OSL::ClosureParam *closure_henyey_greenstein_volume_params();
|
||||
OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_params();
|
||||
OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_glass_params();
|
||||
OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_aniso_params();
|
||||
OSL::ClosureParam *closure_bsdf_microfacet_ggx_fresnel_params();
|
||||
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();
|
||||
|
||||
void closure_emission_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void closure_background_prepare(OSL::RendererServices *, int id, void *data);
|
||||
@@ -65,10 +71,16 @@ void closure_bsdf_phong_ramp_prepare(OSL::RendererServices *, int id, void *data
|
||||
void closure_bssrdf_cubic_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void closure_bssrdf_gaussian_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void closure_bssrdf_burley_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void closure_bssrdf_disney_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void closure_henyey_greenstein_volume_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void closure_bsdf_microfacet_multi_ggx_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void closure_bsdf_microfacet_multi_ggx_glass_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void closure_bsdf_microfacet_multi_ggx_aniso_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void closure_bsdf_microfacet_ggx_fresnel_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void closure_bsdf_microfacet_ggx_aniso_fresnel_prepare(OSL::RendererServices *, int id, void *data);
|
||||
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);
|
||||
|
||||
#define CCLOSURE_PREPARE(name, classname) \
|
||||
void name(RendererServices *, int id, void *data) \
|
||||
|
@@ -81,6 +81,7 @@ set(SRC_OSL
|
||||
node_wireframe.osl
|
||||
node_hair_bsdf.osl
|
||||
node_uv_map.osl
|
||||
node_disney_bsdf.osl
|
||||
node_rgb_to_bw.osl
|
||||
)
|
||||
|
||||
|
139
intern/cycles/kernel/shaders/node_disney_bsdf.osl
Normal file
139
intern/cycles/kernel/shaders/node_disney_bsdf.osl
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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"
|
||||
#include "node_fresnel.h"
|
||||
|
||||
shader node_disney_bsdf(
|
||||
string distribution = "Multiscatter GGX",
|
||||
string surface_type = "Solid Surface",
|
||||
color BaseColor = color(0.8, 0.8, 0.8),
|
||||
float Subsurface = 0.0,
|
||||
vector SubsurfaceRadius = vector(1.0, 1.0, 1.0),
|
||||
color SubsurfaceColor = color(0.7, 0.1, 0.1),
|
||||
float Metallic = 0.0,
|
||||
float Specular = 0.5,
|
||||
float SpecularTint = 0.0,
|
||||
float Roughness = 0.5,
|
||||
float Anisotropic = 0.0,
|
||||
float AnisotropicRotation = 0.0,
|
||||
float Sheen = 0.0,
|
||||
float SheenTint = 0.5,
|
||||
float Clearcoat = 0.0,
|
||||
float ClearcoatGloss = 1.0,
|
||||
float SpecularTransmission = 0.0,
|
||||
float IOR = 1.45,
|
||||
float Flatness = 0.0,
|
||||
float DiffuseTransmission = 0.0,
|
||||
float RefractionRoughness = 0.0,
|
||||
normal Normal = N,
|
||||
normal ClearcoatNormal = N,
|
||||
normal Tangent = normalize(dPdu),
|
||||
output closure color BSDF = 0)
|
||||
{
|
||||
float f = max(IOR, 1e-5);
|
||||
float diffuse_weight = (1.0 - clamp(Metallic, 0.0, 1.0)) * (1.0 - clamp(SpecularTransmission, 0.0, 1.0));
|
||||
float transp = clamp(SpecularTransmission, 0.0, 1.0) * (1.0 - clamp(Metallic, 0.0, 1.0));
|
||||
float specular_weight = (1.0 - transp);
|
||||
|
||||
vector T = Tangent;
|
||||
|
||||
float m_cdlum = luminance(BaseColor);
|
||||
color m_ctint = m_cdlum > 0.0 ? BaseColor / m_cdlum : color(0.0, 0.0, 0.0); // normalize lum. to isolate hue+sat
|
||||
|
||||
/* rotate tangent */
|
||||
if (AnisotropicRotation != 0.0)
|
||||
T = rotate(T, AnisotropicRotation * M_2PI, point(0.0, 0.0, 0.0), Normal);
|
||||
|
||||
if (diffuse_weight > 1e-5) {
|
||||
float flat = Flatness;
|
||||
float diff_trans = clamp(DiffuseTransmission, 0.0, 2.0);
|
||||
if (surface_type == "Solid Surface") {
|
||||
flat = 0.0;
|
||||
diff_trans = 0.0;
|
||||
}
|
||||
|
||||
if (Subsurface > 1e-5 && surface_type == "Solid Surface") {
|
||||
BSDF = bssrdf_disney(Normal, Subsurface * SubsurfaceRadius, 0.0, BaseColor, SubsurfaceColor);
|
||||
} else {
|
||||
BSDF = BaseColor * disney_diffuse(Normal, Roughness, flat) * ((2.0 - diff_trans) / 2.0);
|
||||
}
|
||||
|
||||
/* diffuse retro-reflection */
|
||||
BSDF = BSDF + BaseColor * disney_retro_reflection(Normal, Roughness);
|
||||
|
||||
if (diff_trans > 1e-5) {
|
||||
BSDF = BSDF + BaseColor * disney_diffuse_transmit(Normal, Roughness, flat) * (diff_trans / 2.0);
|
||||
}
|
||||
|
||||
if (Sheen > 1e-5) {
|
||||
color sheen_color = color(1.0, 1.0, 1.0) * (1.0 - SheenTint) + m_ctint * SheenTint;
|
||||
|
||||
BSDF = BSDF + sheen_color * Sheen * disney_sheen(Normal);
|
||||
}
|
||||
|
||||
BSDF = BSDF * diffuse_weight;
|
||||
}
|
||||
|
||||
if (specular_weight > 1e-5) {
|
||||
float aspect = sqrt(1.0 - Anisotropic * 0.9);
|
||||
float r2 = Roughness * Roughness;
|
||||
|
||||
float alpha_x = max(0.001, r2 / aspect);
|
||||
float alpha_y = max(0.001, r2 * aspect);
|
||||
|
||||
color tmp_col = color(1.0, 1.0, 1.0) * (1.0 - SpecularTint) + m_ctint * SpecularTint;
|
||||
|
||||
color Cspec0 = (Specular * 0.08 * tmp_col) * (1.0 - Metallic) + BaseColor * Metallic;
|
||||
|
||||
if (distribution == "GGX" || Roughness <= 0.075) {
|
||||
BSDF = BSDF + specular_weight * microfacet_ggx_aniso_fresnel(Normal, T, alpha_x, alpha_y, (2.0 / (1.0 - sqrt(0.08 * Specular))) - 1.0, BaseColor, Cspec0);
|
||||
} else {
|
||||
BSDF = BSDF + specular_weight * microfacet_multi_ggx_aniso_fresnel(Normal, T, alpha_x, alpha_y, (2.0 / (1.0 - sqrt(0.08 * Specular))) - 1.0, BaseColor, Cspec0);
|
||||
}
|
||||
}
|
||||
|
||||
if (transp > 1e-5) {
|
||||
color Cspec0 = BaseColor * SpecularTint + color(1.0, 1.0, 1.0) * (1.0 - SpecularTint);
|
||||
float eta = (backfacing() && (surface_type == "Solid Surface")) ? 1.0 / f : f;
|
||||
|
||||
if (distribution == "GGX" || Roughness <= 5e-2 || surface_type == "Thin Surface") {
|
||||
float cosNO = dot(Normal, I);
|
||||
float Fr = fresnel_dielectric_cos(cosNO, eta);
|
||||
|
||||
float refl_roughness = Roughness;
|
||||
if (Roughness <= 1e-2)
|
||||
refl_roughness = 0.0;
|
||||
|
||||
float refraction_roughness = refl_roughness;
|
||||
if (distribution == "GGX")
|
||||
refraction_roughness = 1.0 - (1.0 - refl_roughness) * (1.0 - RefractionRoughness);
|
||||
|
||||
if (surface_type == "Thin Surface")
|
||||
refraction_roughness = refraction_roughness * (0.65 * eta - 0.35);
|
||||
|
||||
BSDF = BSDF + transp * (Fr * microfacet_ggx_fresnel(Normal, refl_roughness * refl_roughness, eta, BaseColor, Cspec0) +
|
||||
(1.0 - Fr) * BaseColor * microfacet_ggx_refraction(Normal, refraction_roughness * refraction_roughness, eta));
|
||||
} else {
|
||||
BSDF = BSDF + transp * microfacet_multi_ggx_glass_fresnel(Normal, Roughness * Roughness, eta, BaseColor, Cspec0);
|
||||
}
|
||||
}
|
||||
|
||||
if (Clearcoat > 1e-5) {
|
||||
BSDF = BSDF + disney_clearcoat(ClearcoatNormal, Clearcoat, ClearcoatGloss);
|
||||
}
|
||||
}
|
||||
|
@@ -530,6 +530,11 @@ closure color microfacet_ggx_refraction(normal N, float ag, float eta) BUILTIN;
|
||||
closure color microfacet_multi_ggx(normal N, float ag, color C) BUILTIN;
|
||||
closure color microfacet_multi_ggx_aniso(normal N, vector T, float ax, float ay, color C) BUILTIN;
|
||||
closure color microfacet_multi_ggx_glass(normal N, float ag, float eta, color C) BUILTIN;
|
||||
closure color microfacet_ggx_fresnel(normal N, float ag, float eta, color C, color Cspec0) BUILTIN;
|
||||
closure color microfacet_ggx_aniso_fresnel(normal N, vector T, float ax, float ay, float eta, color C, color Cspec0) BUILTIN;
|
||||
closure color microfacet_multi_ggx_fresnel(normal N, float ag, float eta, color C, color Cspec0) BUILTIN;
|
||||
closure color microfacet_multi_ggx_aniso_fresnel(normal N, vector T, float ax, float ay, float eta, color C, color Cspec0) BUILTIN;
|
||||
closure color microfacet_multi_ggx_glass_fresnel(normal N, float ag, float eta, color C, color Cspec0) 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;
|
||||
@@ -539,11 +544,17 @@ closure color emission() BUILTIN;
|
||||
closure color background() BUILTIN;
|
||||
closure color holdout() BUILTIN;
|
||||
closure color ambient_occlusion() BUILTIN;
|
||||
closure color disney_diffuse(normal N, float roughness, float flatness) BUILTIN;
|
||||
closure color disney_diffuse_transmit(normal N, float roughness, float flatness) BUILTIN;
|
||||
closure color disney_retro_reflection(normal N, float roughness) BUILTIN;
|
||||
closure color disney_sheen(normal N) BUILTIN;
|
||||
closure color disney_clearcoat(normal N, float clearcoat, float clearcoat_gloss) BUILTIN;
|
||||
|
||||
// BSSRDF
|
||||
closure color bssrdf_cubic(normal N, vector radius, float texture_blur, float sharpness) BUILTIN;
|
||||
closure color bssrdf_gaussian(normal N, vector radius, float texture_blur) BUILTIN;
|
||||
closure color bssrdf_burley(normal N, vector radius, float texture_blur, color albedo) BUILTIN;
|
||||
closure color bssrdf_disney(normal N, vector radius, float texture_blur, color base_color, color subsurface_color) BUILTIN;
|
||||
|
||||
// Hair
|
||||
closure color hair_reflection(normal N, float roughnessu, float roughnessv, vector T, float offset) BUILTIN;
|
||||
|
@@ -76,6 +76,436 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
|
||||
float param2 = (stack_valid(param2_offset))? stack_load_float(stack, param2_offset): __uint_as_float(node.w);
|
||||
|
||||
switch(type) {
|
||||
case CLOSURE_BSDF_DISNEY_ID: {
|
||||
uint specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset, sheen_offset,
|
||||
sheen_tint_offset, clearcoat_offset, clearcoat_gloss_offset, eta_offset, spec_trans_offset,
|
||||
anisotropic_rotation_offset, refraction_roughness_offset, flatness_offset, diff_trans_offset, invalid0, invalid1;
|
||||
|
||||
uint4 data_node2 = read_node(kg, offset);
|
||||
|
||||
float3 T = stack_load_float3(stack, data_node.y);
|
||||
decode_node_uchar4(data_node.z, &specular_offset, &roughness_offset, &specular_tint_offset, &anisotropic_offset);
|
||||
decode_node_uchar4(data_node.w, &sheen_offset, &sheen_tint_offset, &clearcoat_offset, &clearcoat_gloss_offset);
|
||||
decode_node_uchar4(data_node2.x, &eta_offset, &spec_trans_offset, &anisotropic_rotation_offset, &refraction_roughness_offset);
|
||||
decode_node_uchar4(data_node2.y, &flatness_offset, &diff_trans_offset, &invalid0, &invalid1);
|
||||
|
||||
// get disney parameters
|
||||
float metallic = param1;
|
||||
float subsurface = param2;
|
||||
float specular = stack_load_float(stack, specular_offset);
|
||||
float roughness = stack_load_float(stack, roughness_offset);
|
||||
float specular_tint = stack_load_float(stack, specular_tint_offset);
|
||||
float anisotropic = stack_load_float(stack, anisotropic_offset);
|
||||
float sheen = stack_load_float(stack, sheen_offset);
|
||||
float sheen_tint = stack_load_float(stack, sheen_tint_offset);
|
||||
float clearcoat = stack_load_float(stack, clearcoat_offset);
|
||||
float clearcoat_gloss = stack_load_float(stack, clearcoat_gloss_offset);
|
||||
float spec_trans = stack_load_float(stack, spec_trans_offset);
|
||||
float anisotropic_rotation = stack_load_float(stack, anisotropic_rotation_offset);
|
||||
float refraction_roughness = stack_load_float(stack, refraction_roughness_offset);
|
||||
float eta = fmaxf(stack_load_float(stack, eta_offset), 1e-5f);
|
||||
float flatness = stack_load_float(stack, flatness_offset);
|
||||
float diff_trans = clamp(stack_load_float(stack, diff_trans_offset), 0.0f, 2.0f);
|
||||
|
||||
ClosureType distribution = stack_valid(data_node2.z) ? (ClosureType) data_node2.z : CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
|
||||
SurfaceType surface_type = stack_valid(data_node2.w) ? (SurfaceType) data_node2.w : SOLID_SURFACE;
|
||||
|
||||
/* rotate tangent */
|
||||
if(anisotropic_rotation != 0.0f)
|
||||
T = rotate_around_axis(T, N, anisotropic_rotation * M_2PI_F);
|
||||
|
||||
/* calculate ior */
|
||||
float ior = ((ccl_fetch(sd, flag) & SD_BACKFACING) && (surface_type == SOLID_SURFACE)) ? 1.0f / eta : eta;
|
||||
|
||||
// calculate fresnel for refraction
|
||||
float cosNO = dot(N, ccl_fetch(sd, I));
|
||||
float fresnel = fresnel_dielectric_cos(cosNO, ior);
|
||||
|
||||
// calculate weights of the diffuse and specular part
|
||||
float diffuse_weight = (1.0f - saturate(metallic)) * (1.0f - saturate(spec_trans)); // lerp(1.0f - clamp(metallic, 0.0f, 1.0f), 0.0f, lerp(clamp(spec_trans, 0.0f, 1.0f), 0.0f, clamp(metallic, 0.0f, 1.0f)));
|
||||
|
||||
float spec_transp = saturate(spec_trans) * (1.0f - saturate(metallic)); // lerp(clamp(spec_trans, 0.0f, 1.0f), 0.0f, clamp(metallic, 0.0f, 1.0f));
|
||||
float specular_weight = (1.0f - spec_transp); // + fresnel * spec_transp; // lerp(1.0f, fresnel, spec_transp);
|
||||
|
||||
// get the base color
|
||||
uint4 data_base_color = read_node(kg, offset);
|
||||
float3 base_color = stack_valid(data_base_color.x) ? stack_load_float3(stack, data_base_color.x) :
|
||||
make_float3(__uint_as_float(data_base_color.y), __uint_as_float(data_base_color.z), __uint_as_float(data_base_color.w));
|
||||
|
||||
// get the additional clearcoat normal and subsurface scattering radius
|
||||
uint4 data_cn_ssr = read_node(kg, offset);
|
||||
float3 clearcoat_normal = stack_valid(data_cn_ssr.x) ? stack_load_float3(stack, data_cn_ssr.x) : ccl_fetch(sd, N);
|
||||
float3 subsurface_radius = stack_valid(data_cn_ssr.y) ? stack_load_float3(stack, data_cn_ssr.y) : make_float3(1.0f, 1.0f, 1.0f);
|
||||
|
||||
// get the subsurface color
|
||||
uint4 data_subsurface_color = read_node(kg, offset);
|
||||
float3 subsurface_color = stack_valid(data_subsurface_color.x) ? stack_load_float3(stack, data_subsurface_color.x) :
|
||||
make_float3(__uint_as_float(data_subsurface_color.y), __uint_as_float(data_subsurface_color.z), __uint_as_float(data_subsurface_color.w));
|
||||
|
||||
float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
|
||||
|
||||
if(surface_type == SOLID_SURFACE) {
|
||||
flatness = 0.0f;
|
||||
diff_trans = 0.0f;
|
||||
}
|
||||
|
||||
#ifdef __SUBSURFACE__
|
||||
float3 albedo = subsurface_color;
|
||||
float3 subsurf_weight = weight * diffuse_weight;
|
||||
float subsurf_sample_weight = fabsf(average(subsurf_weight));
|
||||
|
||||
/* disable in case of diffuse ancestor, can't see it well then and
|
||||
* adds considerably noise due to probabilities of continuing path
|
||||
* getting lower and lower */
|
||||
if(path_flag & PATH_RAY_DIFFUSE_ANCESTOR) {
|
||||
subsurface = 0.0f;
|
||||
}
|
||||
|
||||
/* diffuse */
|
||||
if((surface_type == THIN_SURFACE || subsurface < CLOSURE_WEIGHT_CUTOFF) && diffuse_weight > CLOSURE_WEIGHT_CUTOFF && fabsf(average(base_color)) > CLOSURE_WEIGHT_CUTOFF) {
|
||||
float3 diff_weight = weight * base_color * diffuse_weight * ((2.0f - diff_trans) / 2.0f);
|
||||
|
||||
DisneyDiffuseBsdf *bsdf = (DisneyDiffuseBsdf*)bsdf_alloc(sd, sizeof(DisneyDiffuseBsdf), diff_weight);
|
||||
|
||||
if(bsdf) {
|
||||
bsdf->N = N;
|
||||
bsdf->flatness = flatness;
|
||||
bsdf->roughness = roughness;
|
||||
|
||||
/* setup bsdf */
|
||||
ccl_fetch(sd, flag) |= bsdf_disney_diffuse_setup(bsdf);
|
||||
}
|
||||
}
|
||||
else if(surface_type == SOLID_SURFACE && subsurf_sample_weight > CLOSURE_WEIGHT_CUTOFF) {
|
||||
/* radius * scale */
|
||||
float3 radius = subsurface_radius * subsurface;
|
||||
/* sharpness */
|
||||
float sharpness = 0.0f;
|
||||
/* texture color blur */
|
||||
float texture_blur = 0.0f;
|
||||
|
||||
/* create one closure per color channel */
|
||||
Bssrdf *bssrdf = bssrdf_alloc(sd, make_float3(subsurf_weight.x, 0.0f, 0.0f));
|
||||
if(bssrdf) {
|
||||
bssrdf->sample_weight = subsurf_sample_weight;
|
||||
bssrdf->radius = radius.x;
|
||||
bssrdf->texture_blur = texture_blur;
|
||||
bssrdf->albedo = albedo.x;
|
||||
bssrdf->sharpness = sharpness;
|
||||
bssrdf->N = N;
|
||||
bssrdf->base_color = base_color;
|
||||
|
||||
/* setup bsdf */
|
||||
ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)CLOSURE_BSSRDF_DISNEY_ID);
|
||||
}
|
||||
|
||||
bssrdf = bssrdf_alloc(sd, make_float3(0.0f, subsurf_weight.y, 0.0f));
|
||||
if(bssrdf) {
|
||||
bssrdf->sample_weight = subsurf_sample_weight;
|
||||
bssrdf->radius = radius.y;
|
||||
bssrdf->texture_blur = texture_blur;
|
||||
bssrdf->albedo = albedo.y;
|
||||
bssrdf->sharpness = sharpness;
|
||||
bssrdf->N = N;
|
||||
bssrdf->base_color = base_color;
|
||||
|
||||
/* setup bsdf */
|
||||
ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)CLOSURE_BSSRDF_DISNEY_ID);
|
||||
}
|
||||
|
||||
bssrdf = bssrdf_alloc(sd, make_float3(0.0f, 0.0f, subsurf_weight.z));
|
||||
if(bssrdf) {
|
||||
bssrdf->sample_weight = subsurf_sample_weight;
|
||||
bssrdf->radius = radius.z;
|
||||
bssrdf->texture_blur = texture_blur;
|
||||
bssrdf->albedo = albedo.z;
|
||||
bssrdf->sharpness = sharpness;
|
||||
bssrdf->N = N;
|
||||
bssrdf->base_color = base_color;
|
||||
|
||||
/* setup bsdf */
|
||||
ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)CLOSURE_BSSRDF_DISNEY_ID);
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* diffuse */
|
||||
if(diffuse_weight > CLOSURE_WEIGHT_CUTOFF) {
|
||||
float3 diff_weight = weight * base_color * diffuse_weight;
|
||||
|
||||
DisneyDiffuseBsdf *bsdf = (DisneyDiffuseBsdf*)bsdf_alloc(sd, sizeof(DisneyDiffuseBsdf), diff_weight);
|
||||
|
||||
if(bsdf) {
|
||||
bsdf->N = N;
|
||||
bsdf->flatness = flatness;
|
||||
bsdf->roughness = roughness;
|
||||
|
||||
/* setup bsdf */
|
||||
ccl_fetch(sd, flag) |= bsdf_disney_diffuse_setup(bsdf);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* retro reflection */
|
||||
if(diffuse_weight > CLOSURE_WEIGHT_CUTOFF && fabsf(average(base_color)) > CLOSURE_WEIGHT_CUTOFF) {
|
||||
float3 diff_weight = weight * base_color * diffuse_weight;
|
||||
|
||||
DisneyDiffuseBsdf *bsdf = (DisneyDiffuseBsdf*)bsdf_alloc(sd, sizeof(DisneyDiffuseBsdf), diff_weight);
|
||||
|
||||
if(bsdf) {
|
||||
bsdf->N = N;
|
||||
bsdf->roughness = roughness;
|
||||
|
||||
/* setup bsdf */
|
||||
ccl_fetch(sd, flag) |= bsdf_disney_retro_reflection_setup(bsdf);
|
||||
}
|
||||
}
|
||||
|
||||
/* sheen */
|
||||
if(diffuse_weight > CLOSURE_WEIGHT_CUTOFF && sheen > CLOSURE_WEIGHT_CUTOFF) {
|
||||
float m_cdlum = linear_rgb_to_gray(base_color);
|
||||
float3 m_ctint = m_cdlum > 0.0f ? base_color / m_cdlum : make_float3(1.0f, 1.0f, 1.0f); // normalize lum. to isolate hue+sat
|
||||
|
||||
/* color of the sheen component */
|
||||
float3 sheen_color = make_float3(1.0f, 1.0f, 1.0f) * (1.0f - sheen_tint) + m_ctint * sheen_tint;
|
||||
|
||||
float3 sheen_weight = weight * sheen * sheen_color * diffuse_weight;
|
||||
|
||||
DisneySheenBsdf *bsdf = (DisneySheenBsdf*)bsdf_alloc(sd, sizeof(DisneySheenBsdf), sheen_weight);
|
||||
|
||||
if(bsdf) {
|
||||
bsdf->N = N;
|
||||
|
||||
/* setup bsdf */
|
||||
ccl_fetch(sd, flag) |= bsdf_disney_sheen_setup(bsdf);
|
||||
}
|
||||
}
|
||||
|
||||
/* diffuse transmission */
|
||||
if(surface_type == THIN_SURFACE && diff_trans > CLOSURE_WEIGHT_CUTOFF && diffuse_weight > CLOSURE_WEIGHT_CUTOFF) {
|
||||
float3 diff_weight = weight * base_color * diffuse_weight * (diff_trans / 2.0f);
|
||||
|
||||
DisneyDiffuseBsdf *bsdf = (DisneyDiffuseBsdf*)bsdf_alloc(sd, sizeof(DisneyDiffuseBsdf), diff_weight);
|
||||
|
||||
if(bsdf) {
|
||||
bsdf->N = N;
|
||||
|
||||
/* setup bsdf */
|
||||
ccl_fetch(sd, flag) |= bsdf_disney_diffuse_transmit_setup(bsdf);
|
||||
}
|
||||
}
|
||||
|
||||
/* specular reflection */
|
||||
#ifdef __CAUSTICS_TRICKS__
|
||||
if(kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0) {
|
||||
#endif
|
||||
if(specular_weight > CLOSURE_WEIGHT_CUTOFF && (specular > CLOSURE_WEIGHT_CUTOFF || metallic > CLOSURE_WEIGHT_CUTOFF)) {
|
||||
float3 spec_weight = weight * specular_weight;
|
||||
|
||||
///* for roughness values close to 0 handle as a sharp reflection */
|
||||
//if(roughness <= 1e-2f) {
|
||||
// float spec_to_ior = (2.0f / (1.0f - safe_sqrtf(0.08f * specular))) - 1.0f;
|
||||
|
||||
// float m_cdlum = linear_rgb_to_gray(base_color);
|
||||
// float3 m_ctint = m_cdlum > 0.0f ? base_color / m_cdlum : make_float3(0.0f, 0.0f, 0.0f); // normalize lum. to isolate hue+sat
|
||||
// float3 tmp_col = make_float3(1.0f, 1.0f, 1.0f) * (1.0f - specular_tint) + m_ctint * specular_tint;
|
||||
// float3 cspec0 = (specular * 0.08f * tmp_col) * (1.0f - metallic) + base_color * metallic;
|
||||
|
||||
// float F0 = fresnel_dielectric_cos(1.0f, spec_to_ior);
|
||||
// float F0_norm = 1.0f / (1.0f - F0);
|
||||
// float FH = (fresnel_dielectric_cos(cosNO, spec_to_ior) - F0) * F0_norm;
|
||||
|
||||
// /* Blend between white and a specular color with respect to the fresnel */
|
||||
// float3 refl_color = cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH;
|
||||
|
||||
// MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), spec_weight*refl_color);
|
||||
|
||||
// if(bsdf) {
|
||||
// bsdf->N = N;
|
||||
|
||||
// /* setup bsdf */
|
||||
// ccl_fetch(sd, flag) |= bsdf_reflection_setup(bsdf);
|
||||
// }
|
||||
//}
|
||||
//else {
|
||||
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), spec_weight);
|
||||
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
|
||||
|
||||
if(bsdf && extra) {
|
||||
bsdf->N = N;
|
||||
bsdf->ior = (2.0f / (1.0f - safe_sqrtf(0.08f * specular))) - 1.0f;
|
||||
bsdf->T = T;
|
||||
bsdf->extra = extra;
|
||||
|
||||
float aspect = safe_sqrtf(1.0f - anisotropic * 0.9f);
|
||||
float r2 = roughness * roughness;
|
||||
|
||||
bsdf->alpha_x = fmaxf(0.001f, r2 / aspect);
|
||||
bsdf->alpha_y = fmaxf(0.001f, r2 * aspect);
|
||||
|
||||
float m_cdlum = 0.3f * base_color.x + 0.6f * base_color.y + 0.1f * base_color.z; // luminance approx.
|
||||
float3 m_ctint = m_cdlum > 0.0f ? base_color / m_cdlum : make_float3(0.0f, 0.0f, 0.0f); // normalize lum. to isolate hue+sat
|
||||
float3 tmp_col = make_float3(1.0f, 1.0f, 1.0f) * (1.0f - specular_tint) + m_ctint * specular_tint;
|
||||
|
||||
bsdf->extra->cspec0 = (specular * 0.08f * tmp_col) * (1.0f - metallic) + base_color * metallic;
|
||||
bsdf->extra->color = base_color;
|
||||
|
||||
/* setup bsdf */
|
||||
if(distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID || roughness <= 0.075f) /* use single-scatter GGX */
|
||||
ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_aniso_fresnel_setup(bsdf);
|
||||
else /* use multi-scatter GGX */
|
||||
ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_aniso_fresnel_setup(bsdf);
|
||||
}
|
||||
//}
|
||||
}
|
||||
#ifdef __CAUSTICS_TRICKS__
|
||||
}
|
||||
#endif
|
||||
|
||||
/* BSDF */
|
||||
#ifdef __CAUSTICS_TRICKS__
|
||||
if(kernel_data.integrator.caustics_reflective || kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0) {
|
||||
#endif
|
||||
if(spec_transp > CLOSURE_WEIGHT_CUTOFF) {
|
||||
float3 glass_weight = weight * spec_transp;
|
||||
float3 cspec0 = base_color * specular_tint + make_float3(1.0f, 1.0f, 1.0f) * (1.0f - specular_tint);
|
||||
|
||||
if(roughness <= 5e-2f || distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID || surface_type == THIN_SURFACE) { /* use single-scatter GGX */
|
||||
float refl_roughness = roughness;
|
||||
|
||||
/* reflection */
|
||||
#ifdef __CAUSTICS_TRICKS__
|
||||
if(kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0)
|
||||
#endif
|
||||
{
|
||||
/* for roughness values close to 0 handle as a sharp reflection */
|
||||
//if(roughness <= 1e-2f) {
|
||||
// float F0 = fresnel_dielectric_cos(1.0f, ior);
|
||||
// float F0_norm = 1.0f / (1.0f - F0);
|
||||
// float FH = (fresnel - F0) * F0_norm;
|
||||
|
||||
// /* Blend between white and a specular color with respect to the fresnel */
|
||||
// float3 refl_color = cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH;
|
||||
|
||||
// MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), refl_color*glass_weight*fresnel);
|
||||
|
||||
// if(bsdf) {
|
||||
// bsdf->N = N;
|
||||
|
||||
// /* setup bsdf */
|
||||
// ccl_fetch(sd, flag) |= bsdf_reflection_setup(bsdf);
|
||||
// }
|
||||
//}
|
||||
//else {
|
||||
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 = base_color;
|
||||
bsdf->extra->cspec0 = cspec0;
|
||||
|
||||
/* setup bsdf */
|
||||
ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_fresnel_setup(bsdf);
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
/* 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), base_color*glass_weight*(1.0f - fresnel));
|
||||
|
||||
if(bsdf) {
|
||||
bsdf->N = N;
|
||||
|
||||
if(distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID)
|
||||
refraction_roughness = 1.0f - (1.0f - refl_roughness) * (1.0f - refraction_roughness);
|
||||
else
|
||||
refraction_roughness = refl_roughness;
|
||||
|
||||
/* Remap the roughness for thin surfaces as introduced in the 2015 Disney paper:
|
||||
*
|
||||
* Extending the Disney BRDF to a BSDF with Integrated Subsurface Scattering
|
||||
* Burley, Brent (Walt Disney Animation Studios) */
|
||||
if(surface_type == THIN_SURFACE) {
|
||||
refraction_roughness *= 0.65f * ior - 0.35f;
|
||||
//refraction_roughness = safe_sqrtf(refraction_roughness);
|
||||
}
|
||||
else {
|
||||
refraction_roughness *= refraction_roughness;
|
||||
}
|
||||
|
||||
bsdf->alpha_x = refraction_roughness;
|
||||
bsdf->alpha_y = refraction_roughness;
|
||||
bsdf->ior = ior;
|
||||
|
||||
/* setup bsdf */
|
||||
ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_refraction_setup(bsdf);
|
||||
}
|
||||
}
|
||||
}
|
||||
else { /* use multi-scatter GGX */
|
||||
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), glass_weight);
|
||||
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
|
||||
|
||||
if(bsdf && extra) {
|
||||
bsdf->N = N;
|
||||
bsdf->extra = extra;
|
||||
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
bsdf->alpha_x = roughness * roughness;
|
||||
bsdf->alpha_y = roughness * roughness;
|
||||
bsdf->ior = ior;
|
||||
|
||||
bsdf->extra->color = base_color;
|
||||
bsdf->extra->cspec0 = cspec0;
|
||||
|
||||
/* setup bsdf */
|
||||
ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_glass_fresnel_setup(bsdf);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef __CAUSTICS_TRICKS__
|
||||
}
|
||||
#endif
|
||||
|
||||
/* clearcoat */
|
||||
#ifdef __CAUSTICS_TRICKS__
|
||||
if(kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0) {
|
||||
#endif
|
||||
if(clearcoat > CLOSURE_WEIGHT_CUTOFF) {
|
||||
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
|
||||
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
|
||||
|
||||
if(bsdf && extra) {
|
||||
bsdf->N = clearcoat_normal;
|
||||
bsdf->ior = 1.5f;
|
||||
bsdf->extra = extra;
|
||||
|
||||
bsdf->alpha_x = 0.1f * (1.0f - clearcoat_gloss) + 0.001f * clearcoat_gloss;
|
||||
bsdf->alpha_y = 0.1f * (1.0f - clearcoat_gloss) + 0.001f * clearcoat_gloss;
|
||||
|
||||
bsdf->extra->cspec0 = make_float3(0.04f, 0.04f, 0.04f);
|
||||
bsdf->extra->clearcoat = clearcoat;
|
||||
|
||||
/* setup bsdf */
|
||||
ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_clearcoat_setup(bsdf);
|
||||
}
|
||||
}
|
||||
#ifdef __CAUSTICS_TRICKS__
|
||||
}
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
case CLOSURE_BSDF_DIFFUSE_ID: {
|
||||
float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
|
||||
OrenNayarBsdf *bsdf = (OrenNayarBsdf*)bsdf_alloc(sd, sizeof(OrenNayarBsdf), weight);
|
||||
|
@@ -395,17 +395,26 @@ typedef enum ClosureType {
|
||||
CLOSURE_BSDF_DIFFUSE_ID,
|
||||
CLOSURE_BSDF_OREN_NAYAR_ID,
|
||||
CLOSURE_BSDF_DIFFUSE_RAMP_ID,
|
||||
CLOSURE_BSDF_DISNEY_DIFFUSE_ID,
|
||||
CLOSURE_BSDF_DISNEY_DIFFUSE_TRANSMIT_ID,
|
||||
CLOSURE_BSDF_DISNEY_RETRO_REFLECTION_ID,
|
||||
CLOSURE_BSDF_DISNEY_SHEEN_ID,
|
||||
CLOSURE_BSDF_DIFFUSE_TOON_ID,
|
||||
|
||||
/* Glossy */
|
||||
CLOSURE_BSDF_GLOSSY_ID,
|
||||
CLOSURE_BSDF_REFLECTION_ID,
|
||||
CLOSURE_BSDF_MICROFACET_GGX_ID,
|
||||
CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID,
|
||||
CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID,
|
||||
CLOSURE_BSDF_MICROFACET_BECKMANN_ID,
|
||||
CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID,
|
||||
CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID,
|
||||
CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID,
|
||||
CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID,
|
||||
CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID,
|
||||
CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID,
|
||||
CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_FRESNEL_ID,
|
||||
CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID,
|
||||
CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID,
|
||||
CLOSURE_BSDF_ASHIKHMIN_VELVET_ID,
|
||||
@@ -419,19 +428,23 @@ typedef enum ClosureType {
|
||||
CLOSURE_BSDF_REFRACTION_ID,
|
||||
CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID,
|
||||
CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID,
|
||||
CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID,
|
||||
CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID,
|
||||
CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID,
|
||||
CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID,
|
||||
CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID,
|
||||
CLOSURE_BSDF_SHARP_GLASS_ID,
|
||||
CLOSURE_BSDF_HAIR_TRANSMISSION_ID,
|
||||
|
||||
/* Special cases */
|
||||
CLOSURE_BSDF_BSSRDF_ID,
|
||||
CLOSURE_BSDF_BSSRDF_DISNEY_ID,
|
||||
CLOSURE_BSDF_TRANSPARENT_ID,
|
||||
|
||||
/* BSSRDF */
|
||||
CLOSURE_BSSRDF_CUBIC_ID,
|
||||
CLOSURE_BSSRDF_GAUSSIAN_ID,
|
||||
CLOSURE_BSSRDF_DISNEY_ID,
|
||||
CLOSURE_BSSRDF_BURLEY_ID,
|
||||
|
||||
/* Other */
|
||||
@@ -445,6 +458,8 @@ typedef enum ClosureType {
|
||||
CLOSURE_VOLUME_ABSORPTION_ID,
|
||||
CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID,
|
||||
|
||||
CLOSURE_BSDF_DISNEY_ID,
|
||||
|
||||
NBUILTIN_CLOSURES
|
||||
} ClosureType;
|
||||
|
||||
@@ -453,7 +468,7 @@ typedef enum ClosureType {
|
||||
#define CLOSURE_IS_BSDF_DIFFUSE(type) (type >= CLOSURE_BSDF_DIFFUSE_ID && type <= CLOSURE_BSDF_DIFFUSE_TOON_ID)
|
||||
#define CLOSURE_IS_BSDF_GLOSSY(type) (type >= CLOSURE_BSDF_GLOSSY_ID && type <= CLOSURE_BSDF_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_BSSRDF(type) (type == CLOSURE_BSDF_BSSRDF_ID || type == CLOSURE_BSDF_BSSRDF_DISNEY_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_MULTISCATTER(type) (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID ||\
|
||||
type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID || \
|
||||
@@ -467,9 +482,15 @@ typedef enum ClosureType {
|
||||
#define CLOSURE_IS_AMBIENT_OCCLUSION(type) (type == CLOSURE_AMBIENT_OCCLUSION_ID)
|
||||
#define CLOSURE_IS_PHASE(type) (type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID)
|
||||
#define CLOSURE_IS_GLASS(type) (type >= CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID && type <= CLOSURE_BSDF_SHARP_GLASS_ID)
|
||||
#define CLOSURE_IS_DISNEY(type) (type == CLOSURE_BSDF_DISNEY_ID)
|
||||
|
||||
#define CLOSURE_WEIGHT_CUTOFF 1e-5f
|
||||
|
||||
typedef enum SurfaceType {
|
||||
SOLID_SURFACE,
|
||||
THIN_SURFACE
|
||||
} SurfaceType;
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __SVM_TYPES_H__ */
|
||||
|
@@ -979,6 +979,9 @@ int ShaderGraph::get_num_closures()
|
||||
else if(CLOSURE_IS_BSDF_MULTISCATTER(closure_type)) {
|
||||
num_closures += 2;
|
||||
}
|
||||
else if(CLOSURE_IS_DISNEY(closure_type)) {
|
||||
num_closures += 10;
|
||||
}
|
||||
else {
|
||||
++num_closures;
|
||||
}
|
||||
|
@@ -2220,6 +2220,159 @@ void DiffuseBsdfNode::compile(OSLCompiler& compiler)
|
||||
compiler.add(this, "node_diffuse_bsdf");
|
||||
}
|
||||
|
||||
/* Disney BSDF Closure */
|
||||
NODE_DEFINE(DisneyBsdfNode)
|
||||
{
|
||||
NodeType* type = NodeType::add("disney_bsdf", create, NodeType::SHADER);
|
||||
|
||||
static NodeEnum distribution_enum;
|
||||
distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
|
||||
distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
|
||||
SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
|
||||
static NodeEnum surface_type_enum;
|
||||
surface_type_enum.insert("Solid Surface", SOLID_SURFACE);
|
||||
surface_type_enum.insert("Thin Surface", THIN_SURFACE);
|
||||
SOCKET_ENUM(surface_type, "Surface Type", surface_type_enum, SOLID_SURFACE);
|
||||
SOCKET_IN_COLOR(base_color, "Base Color", make_float3(0.8f, 0.8f, 0.8f));
|
||||
SOCKET_IN_COLOR(subsurface_color, "Subsurface Color", make_float3(0.8f, 0.8f, 0.8f));
|
||||
SOCKET_IN_FLOAT(metallic, "Metallic", 0.0f);
|
||||
SOCKET_IN_FLOAT(subsurface, "Subsurface", 0.0f);
|
||||
SOCKET_IN_VECTOR(subsurface_radius, "Subsurface Radius", make_float3(0.1f, 0.1f, 0.1f));
|
||||
SOCKET_IN_FLOAT(specular, "Specular", 0.0f);
|
||||
SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f);
|
||||
SOCKET_IN_FLOAT(specular_tint, "Specular Tint", 0.0f);
|
||||
SOCKET_IN_FLOAT(anisotropic, "Anisotropic", 0.0f);
|
||||
SOCKET_IN_FLOAT(anisotropic_rotation, "Anisotropic Rotation", 0.0f);
|
||||
SOCKET_IN_FLOAT(sheen, "Sheen", 0.0f);
|
||||
SOCKET_IN_FLOAT(sheen_tint, "Sheen Tint", 0.0f);
|
||||
SOCKET_IN_FLOAT(clearcoat, "Clearcoat", 0.0f);
|
||||
SOCKET_IN_FLOAT(clearcoat_gloss, "Clearcoat Gloss", 0.0f);
|
||||
SOCKET_IN_FLOAT(spec_trans, "Specular Transmission", 0.0f);
|
||||
SOCKET_IN_FLOAT(ior, "IOR", 0.0f);
|
||||
SOCKET_IN_FLOAT(flatness, "Flatness", 0.0f);
|
||||
SOCKET_IN_FLOAT(diff_trans, "Diffuse Transmission", 0.0f);
|
||||
SOCKET_IN_FLOAT(refraction_roughness, "Refraction Roughness", 0.0f);
|
||||
SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
|
||||
SOCKET_IN_NORMAL(clearcoat_normal, "Clearcoat Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
|
||||
SOCKET_IN_NORMAL(tangent, "Tangent", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TANGENT);
|
||||
SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
|
||||
|
||||
SOCKET_OUT_CLOSURE(BSDF, "BSDF");
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
DisneyBsdfNode::DisneyBsdfNode()
|
||||
: ShaderNode(node_type)
|
||||
{
|
||||
special_type = SHADER_SPECIAL_TYPE_CLOSURE;
|
||||
closure = CLOSURE_BSDF_DISNEY_ID;
|
||||
distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
|
||||
distribution_orig = NBUILTIN_CLOSURES;
|
||||
}
|
||||
|
||||
void DisneyBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
|
||||
{
|
||||
if(shader->has_surface) {
|
||||
ShaderInput *tangent_in = input("Tangent");
|
||||
|
||||
if(!tangent_in->link)
|
||||
attributes->add(ATTR_STD_GENERATED);
|
||||
}
|
||||
|
||||
ShaderNode::attributes(shader, attributes);
|
||||
}
|
||||
|
||||
void DisneyBsdfNode::compile(SVMCompiler& compiler, ShaderInput *p_metallic, ShaderInput *p_subsurface, ShaderInput *p_subsurface_radius,
|
||||
ShaderInput *p_specular, ShaderInput *p_specular_tint, ShaderInput *p_roughness, ShaderInput *p_anisotropic, ShaderInput *p_anisotropic_rotation,
|
||||
ShaderInput *p_sheen, ShaderInput *p_sheen_tint, ShaderInput *p_clearcoat, ShaderInput *p_clearcoat_gloss, ShaderInput *p_spec_trans,
|
||||
ShaderInput *p_ior, ShaderInput *p_flatness, ShaderInput *p_diff_trans, ShaderInput *p_refraction_roughness)
|
||||
{
|
||||
ShaderInput *base_color_in = input("Base Color");
|
||||
ShaderInput *subsurface_color_in = input("Subsurface Color");
|
||||
ShaderInput *normal_in = input("Normal");
|
||||
ShaderInput *clearcoat_normal_in = input("Clearcoat Normal");
|
||||
ShaderInput *tangent_in = input("Tangent");
|
||||
|
||||
float3 weight = make_float3(1.0f, 1.0f, 1.0f);
|
||||
|
||||
compiler.add_node(NODE_CLOSURE_SET_WEIGHT, weight);
|
||||
|
||||
int normal_offset = compiler.stack_assign_if_linked(normal_in);
|
||||
int clearcoat_normal_offset = compiler.stack_assign_if_linked(clearcoat_normal_in);
|
||||
int tangent_offset = compiler.stack_assign_if_linked(tangent_in);
|
||||
int specular_offset = compiler.stack_assign(p_specular);
|
||||
int roughness_offset = compiler.stack_assign(p_roughness);
|
||||
int specular_tint_offset = compiler.stack_assign(p_specular_tint);
|
||||
int anisotropic_offset = compiler.stack_assign(p_anisotropic);
|
||||
int anisotropic_rotation_offset = compiler.stack_assign(p_anisotropic_rotation);
|
||||
int sheen_offset = compiler.stack_assign(p_sheen);
|
||||
int sheen_tint_offset = compiler.stack_assign(p_sheen_tint);
|
||||
int clearcoat_offset = compiler.stack_assign(p_clearcoat);
|
||||
int clearcoat_gloss_offset = compiler.stack_assign(p_clearcoat_gloss);
|
||||
int spec_trans_offset = compiler.stack_assign(p_spec_trans);
|
||||
int ior_offset = compiler.stack_assign(p_ior);
|
||||
int flatness_offset = compiler.stack_assign(p_flatness);
|
||||
int diff_trans_offset = compiler.stack_assign(p_diff_trans);
|
||||
int refraction_roughness_offset = compiler.stack_assign(p_refraction_roughness);
|
||||
int subsurface_radius_offset = compiler.stack_assign(p_subsurface_radius);
|
||||
|
||||
compiler.add_node(NODE_CLOSURE_BSDF,
|
||||
compiler.encode_uchar4(closure,
|
||||
compiler.stack_assign(p_metallic),
|
||||
compiler.stack_assign(p_subsurface),
|
||||
compiler.closure_mix_weight_offset()),
|
||||
__float_as_int((p_metallic) ? get_float(p_metallic->socket_type) : 0.0f),
|
||||
__float_as_int((p_subsurface) ? get_float(p_subsurface->socket_type) : 0.0f));
|
||||
|
||||
compiler.add_node(normal_offset, tangent_offset,
|
||||
compiler.encode_uchar4(specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset),
|
||||
compiler.encode_uchar4(sheen_offset, sheen_tint_offset, clearcoat_offset, clearcoat_gloss_offset));
|
||||
|
||||
compiler.add_node(compiler.encode_uchar4(ior_offset, spec_trans_offset, anisotropic_rotation_offset, refraction_roughness_offset),
|
||||
compiler.encode_uchar4(flatness_offset, diff_trans_offset, SVM_STACK_INVALID, SVM_STACK_INVALID), distribution, surface_type);
|
||||
|
||||
float3 bc_default = get_float3(base_color_in->socket_type);
|
||||
|
||||
compiler.add_node(((base_color_in->link) ? compiler.stack_assign(base_color_in) : SVM_STACK_INVALID),
|
||||
__float_as_int(bc_default.x), __float_as_int(bc_default.y), __float_as_int(bc_default.z));
|
||||
|
||||
compiler.add_node(clearcoat_normal_offset, subsurface_radius_offset, SVM_STACK_INVALID, SVM_STACK_INVALID);
|
||||
|
||||
float3 ss_default = get_float3(subsurface_color_in->socket_type);
|
||||
|
||||
compiler.add_node(((subsurface_color_in->link) ? compiler.stack_assign(subsurface_color_in) : SVM_STACK_INVALID),
|
||||
__float_as_int(ss_default.x), __float_as_int(ss_default.y), __float_as_int(ss_default.z));
|
||||
}
|
||||
|
||||
bool DisneyBsdfNode::has_integrator_dependency()
|
||||
{
|
||||
ShaderInput *roughness_input = input("Roughness");
|
||||
return !roughness_input->link && roughness <= 1e-4f;
|
||||
}
|
||||
|
||||
void DisneyBsdfNode::compile(SVMCompiler& compiler)
|
||||
{
|
||||
compile(compiler, input("Metallic"), input("Subsurface"), input("Subsurface Radius"), input("Specular"),
|
||||
input("Specular Tint"), input("Roughness"), input("Anisotropic"), input("Anisotropic Rotation"),
|
||||
input("Sheen"), input("Sheen Tint"), input("Clearcoat"), input("Clearcoat Gloss"), input("Specular Transmission"),
|
||||
input("IOR"), input("Flatness"), input("Diffuse Transmission"), input("Refraction Roughness"));
|
||||
}
|
||||
|
||||
void DisneyBsdfNode::compile(OSLCompiler& compiler)
|
||||
{
|
||||
compiler.parameter(this, "distribution");
|
||||
compiler.parameter(this, "surface_type");
|
||||
compiler.add(this, "node_disney_bsdf");
|
||||
}
|
||||
|
||||
bool DisneyBsdfNode::has_bssrdf_bump()
|
||||
{
|
||||
/* detect if anything is plugged into the normal input besides the default */
|
||||
ShaderInput *normal_in = input("Normal");
|
||||
return (normal_in->link && normal_in->link->parent->special_type != SHADER_SPECIAL_TYPE_GEOMETRY);
|
||||
}
|
||||
|
||||
/* Translucent BSDF Closure */
|
||||
|
||||
NODE_DEFINE(TranslucentBsdfNode)
|
||||
|
@@ -361,6 +361,40 @@ public:
|
||||
float roughness;
|
||||
};
|
||||
|
||||
/* Disney BRDF */
|
||||
class DisneyBsdfNode : public ShaderNode {
|
||||
public:
|
||||
SHADER_NODE_CLASS(DisneyBsdfNode)
|
||||
|
||||
bool has_spatial_varying() { return true; }
|
||||
bool has_surface_bssrdf() { return true; }
|
||||
bool has_bssrdf_bump();
|
||||
void compile(SVMCompiler& compiler, ShaderInput *metallic, ShaderInput *subsurface, ShaderInput *subsurface_radius,
|
||||
ShaderInput *specular, ShaderInput *specular_tint, ShaderInput *roughness, ShaderInput *anisotropic, ShaderInput *anisotropic_rotation,
|
||||
ShaderInput *sheen, ShaderInput *sheen_tint, ShaderInput *clearcoat, ShaderInput *clearcoat_gloss, ShaderInput *spec_trans,
|
||||
ShaderInput *ior, ShaderInput *flatness, ShaderInput *diff_trans, ShaderInput *refraction_roughness);
|
||||
|
||||
float3 base_color;
|
||||
float3 subsurface_color, subsurface_radius;
|
||||
float metallic, subsurface, specular, roughness, specular_tint, anisotropic,
|
||||
sheen, sheen_tint, clearcoat, clearcoat_gloss, ior, spec_trans, diff_trans,
|
||||
anisotropic_rotation, refraction_roughness, flatness;
|
||||
float3 normal, clearcoat_normal, tangent;
|
||||
float surface_mix_weight;
|
||||
ClosureType closure, distribution, distribution_orig;
|
||||
SurfaceType surface_type;
|
||||
|
||||
virtual bool equals(const ShaderNode * /*other*/)
|
||||
{
|
||||
/* TODO(sergey): With some care BSDF nodes can be de-duplicated. */
|
||||
return false;
|
||||
}
|
||||
|
||||
ClosureType get_closure_type() { return closure; }
|
||||
bool has_integrator_dependency();
|
||||
void attributes(Shader *shader, AttributeRequestSet *attributes);
|
||||
};
|
||||
|
||||
class TranslucentBsdfNode : public BsdfNode {
|
||||
public:
|
||||
SHADER_NODE_CLASS(TranslucentBsdfNode)
|
||||
|
Submodule release/datafiles/locale updated: dc16605719...2b3c19f5f6
Submodule release/scripts/addons updated: 06dad53c80...3d8df6195d
Submodule release/scripts/addons_contrib updated: 04af69be14...a52733b58d
@@ -219,6 +219,7 @@ shader_node_categories = [
|
||||
NodeItem("ShaderNodeMixShader"),
|
||||
NodeItem("ShaderNodeAddShader"),
|
||||
NodeItem("ShaderNodeBsdfDiffuse", poll=object_shader_nodes_poll),
|
||||
NodeItem("ShaderNodeBsdfDisney", poll=object_shader_nodes_poll),
|
||||
NodeItem("ShaderNodeBsdfGlossy", poll=object_shader_nodes_poll),
|
||||
NodeItem("ShaderNodeBsdfTransparent", poll=object_shader_nodes_poll),
|
||||
NodeItem("ShaderNodeBsdfRefraction", poll=object_shader_nodes_poll),
|
||||
|
@@ -787,6 +787,7 @@ struct ShadeResult;
|
||||
#define SH_NODE_OUTPUT_LINESTYLE 190
|
||||
#define SH_NODE_UVALONGSTROKE 191
|
||||
#define SH_NODE_TEX_POINTDENSITY 192
|
||||
#define SH_NODE_BSDF_DISNEY 193
|
||||
|
||||
/* custom defines options for Material node */
|
||||
#define SH_NODE_MAT_DIFF 1
|
||||
|
@@ -3591,6 +3591,7 @@ static void registerShaderNodes(void)
|
||||
register_node_type_sh_background();
|
||||
register_node_type_sh_bsdf_anisotropic();
|
||||
register_node_type_sh_bsdf_diffuse();
|
||||
register_node_type_sh_bsdf_disney();
|
||||
register_node_type_sh_bsdf_glossy();
|
||||
register_node_type_sh_bsdf_glass();
|
||||
register_node_type_sh_bsdf_translucent();
|
||||
|
@@ -1071,6 +1071,12 @@ static void node_shader_buts_glossy(uiLayout *layout, bContext *UNUSED(C), Point
|
||||
uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE);
|
||||
}
|
||||
|
||||
static void node_shader_buts_disney(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
|
||||
{
|
||||
uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE);
|
||||
uiItemR(layout, ptr, "surface_type", 0, "", ICON_NONE);
|
||||
}
|
||||
|
||||
static void node_shader_buts_anisotropic(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
|
||||
{
|
||||
uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE);
|
||||
@@ -1236,6 +1242,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_DISNEY:
|
||||
ntype->draw_buttons = node_shader_buts_disney;
|
||||
break;
|
||||
case SH_NODE_BSDF_ANISOTROPIC:
|
||||
ntype->draw_buttons = node_shader_buts_anisotropic;
|
||||
break;
|
||||
|
@@ -2553,6 +2553,13 @@ void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out vec4 resu
|
||||
node_bsdf_diffuse(color, 0.0, N, result);
|
||||
}
|
||||
|
||||
void node_bsdf_disney(vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular,
|
||||
float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat,
|
||||
float clearcoat_gloss, float ior, float transparency, float refraction_roughness, vec3 N, vec3 CN, vec3 T, out vec4 result)
|
||||
{
|
||||
node_bsdf_diffuse(base_color, roughness, N, result);
|
||||
}
|
||||
|
||||
void node_bsdf_translucent(vec4 color, vec3 N, out vec4 result)
|
||||
{
|
||||
node_bsdf_diffuse(color, 0.0, N, result);
|
||||
|
@@ -915,6 +915,10 @@ typedef struct NodeSunBeams {
|
||||
#define SHD_GLOSSY_ASHIKHMIN_SHIRLEY 3
|
||||
#define SHD_GLOSSY_MULTI_GGX 4
|
||||
|
||||
/* surface type */
|
||||
#define SHD_THIN_SURFACE 0
|
||||
#define SHD_SOLID_SURFACE 1
|
||||
|
||||
/* vector transform */
|
||||
#define SHD_VECT_TRANSFORM_TYPE_VECTOR 0
|
||||
#define SHD_VECT_TRANSFORM_TYPE_POINT 1
|
||||
|
@@ -2995,6 +2995,15 @@ static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *p
|
||||
ED_node_tag_update_nodetree(bmain, ntree, node);
|
||||
}
|
||||
|
||||
static void rna_ShaderNodeDisney_update(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
{
|
||||
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
|
||||
bNode *node = (bNode *)ptr->data;
|
||||
|
||||
nodeUpdate(ntree, node);
|
||||
rna_Node_update(bmain, scene, ptr);
|
||||
}
|
||||
|
||||
static void rna_ShaderNodeSubsurface_update(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
{
|
||||
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
|
||||
@@ -4181,6 +4190,35 @@ static void def_glass(StructRNA *srna)
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
}
|
||||
|
||||
static void def_disney(StructRNA *srna)
|
||||
{
|
||||
static EnumPropertyItem prop_disney_distribution_items[] = {
|
||||
{ SHD_GLOSSY_GGX, "GGX", 0, "GGX", "" },
|
||||
{ SHD_GLOSSY_MULTI_GGX, "MULTI_GGX", 0, "Multiscatter GGX", "" },
|
||||
{ 0, NULL, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
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, prop_disney_distribution_items);
|
||||
RNA_def_property_ui_text(prop, "Distribution", "");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeDisney_update");
|
||||
|
||||
static EnumPropertyItem prop_disney_surface_type_items[] = {
|
||||
{ SHD_THIN_SURFACE, "THIN_SURFACE", 0, "Thin Surface", "" },
|
||||
{ SHD_SOLID_SURFACE, "SOLID_SURFACE", 0, "Solid Surface", "" },
|
||||
{ 0, NULL, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
prop = RNA_def_property(srna, "surface_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "custom2");
|
||||
RNA_def_property_enum_items(prop, prop_disney_surface_type_items);
|
||||
RNA_def_property_ui_text(prop, "Surface Type", "");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeDisney_update");
|
||||
}
|
||||
|
||||
static void def_refraction(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
@@ -163,6 +163,7 @@ set(SRC
|
||||
shader/nodes/node_shader_background.c
|
||||
shader/nodes/node_shader_bsdf_anisotropic.c
|
||||
shader/nodes/node_shader_bsdf_diffuse.c
|
||||
shader/nodes/node_shader_bsdf_disney.c
|
||||
shader/nodes/node_shader_bsdf_glass.c
|
||||
shader/nodes/node_shader_bsdf_glossy.c
|
||||
shader/nodes/node_shader_bsdf_toon.c
|
||||
|
@@ -106,6 +106,7 @@ void register_node_type_sh_bsdf_transparent(void);
|
||||
void register_node_type_sh_bsdf_velvet(void);
|
||||
void register_node_type_sh_bsdf_toon(void);
|
||||
void register_node_type_sh_bsdf_anisotropic(void);
|
||||
void register_node_type_sh_bsdf_disney(void);
|
||||
void register_node_type_sh_emission(void);
|
||||
void register_node_type_sh_holdout(void);
|
||||
void register_node_type_sh_volume_absorption(void);
|
||||
|
@@ -80,6 +80,7 @@ DefNode( ShaderNode, SH_NODE_BACKGROUND, 0, "BA
|
||||
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_DIFFUSE, 0, "BSDF_DIFFUSE", BsdfDiffuse, "Diffuse BSDF", "" )
|
||||
DefNode( ShaderNode, SH_NODE_BSDF_DISNEY, def_disney, "BSDF_DISNEY", BsdfDisney, "Disney BSDF", "" )
|
||||
DefNode( ShaderNode, SH_NODE_BSDF_GLOSSY, def_glossy, "BSDF_GLOSSY", BsdfGlossy, "Glossy BSDF", "" )
|
||||
DefNode( ShaderNode, SH_NODE_BSDF_GLASS, def_glass, "BSDF_GLASS", BsdfGlass, "Glass BSDF", "" )
|
||||
DefNode( ShaderNode, SH_NODE_BSDF_REFRACTION, def_refraction, "BSDF_REFRACTION", BsdfRefraction, "Refraction BSDF", "" )
|
||||
|
140
source/blender/nodes/shader/nodes/node_shader_bsdf_disney.c
Normal file
140
source/blender/nodes/shader/nodes/node_shader_bsdf_disney.c
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2005 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include "../node_shader_util.h"
|
||||
|
||||
/* **************** OUTPUT ******************** */
|
||||
|
||||
static bNodeSocketTemplate sh_node_bsdf_disney_in[] = {
|
||||
{ SOCK_RGBA, 1, N_("Base Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
|
||||
{ SOCK_FLOAT, 1, N_("Subsurface"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
|
||||
{ SOCK_VECTOR, 1, N_("Subsurface Radius"), 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f},
|
||||
{ SOCK_RGBA, 1, N_("Subsurface Color"), 0.7f, 0.1f, 0.1f, 1.0f, 0.0f, 1.0f},
|
||||
{ SOCK_FLOAT, 1, N_("Metallic"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
|
||||
{ SOCK_FLOAT, 1, N_("Specular"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
|
||||
{ SOCK_FLOAT, 1, N_("Specular Tint"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
|
||||
{ SOCK_FLOAT, 1, N_("Roughness"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
|
||||
{ SOCK_FLOAT, 1, N_("Anisotropic"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
|
||||
{ SOCK_FLOAT, 1, N_("Anisotropic Rotation"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
|
||||
{ SOCK_FLOAT, 1, N_("Sheen"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
|
||||
{ SOCK_FLOAT, 1, N_("Sheen Tint"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
|
||||
{ SOCK_FLOAT, 1, N_("Clearcoat"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
|
||||
{ SOCK_FLOAT, 1, N_("Clearcoat Gloss"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
|
||||
{ SOCK_FLOAT, 1, N_("Specular Transmission"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
|
||||
{ SOCK_FLOAT, 1, N_("IOR"), 1.45f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
|
||||
{ SOCK_FLOAT, 1, N_("Flatness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
|
||||
{ SOCK_FLOAT, 1, N_("Diffuse Transmission"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, PROP_FACTOR},
|
||||
{ SOCK_FLOAT, 1, N_("Refraction Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
|
||||
{ SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
|
||||
{ SOCK_VECTOR, 1, N_("Clearcoat Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
|
||||
{ SOCK_VECTOR, 1, N_("Tangent"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
|
||||
{ -1, 0, "" }
|
||||
};
|
||||
|
||||
static bNodeSocketTemplate sh_node_bsdf_disney_out[] = {
|
||||
{ SOCK_SHADER, 0, N_("BSDF")},
|
||||
{ -1, 0, "" }
|
||||
};
|
||||
|
||||
static void node_shader_init_disney(bNodeTree *UNUSED(ntree), bNode *node)
|
||||
{
|
||||
node->custom1 = SHD_GLOSSY_MULTI_GGX;
|
||||
node->custom2 = SHD_SOLID_SURFACE;
|
||||
}
|
||||
|
||||
static int node_shader_gpu_bsdf_disney(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
|
||||
{
|
||||
if (!in[18].link)
|
||||
in[18].link = GPU_builtin(GPU_VIEW_NORMAL);
|
||||
else
|
||||
GPU_link(mat, "direction_transform_m4v3", in[18].link, GPU_builtin(GPU_VIEW_MATRIX), &in[18].link);
|
||||
|
||||
return GPU_stack_link(mat, "node_bsdf_disney", in, out);
|
||||
}
|
||||
|
||||
static void node_shader_update_disney(bNodeTree *UNUSED(ntree), bNode *node)
|
||||
{
|
||||
bNodeSocket *sock;
|
||||
int distribution = node->custom1;
|
||||
int surface_type = node->custom2;
|
||||
|
||||
for (sock = node->inputs.first; sock; sock = sock->next) {
|
||||
if (STREQ(sock->name, "Refraction Roughness")) {
|
||||
if (distribution == SHD_GLOSSY_GGX)
|
||||
sock->flag &= ~SOCK_UNAVAIL;
|
||||
else
|
||||
sock->flag |= SOCK_UNAVAIL;
|
||||
}
|
||||
else if (STREQ(sock->name, "Diffuse Transmission")) {
|
||||
if (surface_type == SHD_THIN_SURFACE)
|
||||
sock->flag &= ~SOCK_UNAVAIL;
|
||||
else
|
||||
sock->flag |= SOCK_UNAVAIL;
|
||||
}
|
||||
else if (STREQ(sock->name, "Subsurface")) {
|
||||
if (surface_type == SHD_SOLID_SURFACE)
|
||||
sock->flag &= ~SOCK_UNAVAIL;
|
||||
else
|
||||
sock->flag |= SOCK_UNAVAIL;
|
||||
}
|
||||
else if (STREQ(sock->name, "Subsurface Radius")) {
|
||||
if (surface_type == SHD_SOLID_SURFACE)
|
||||
sock->flag &= ~SOCK_UNAVAIL;
|
||||
else
|
||||
sock->flag |= SOCK_UNAVAIL;
|
||||
}
|
||||
else if (STREQ(sock->name, "Subsurface Color")) {
|
||||
if (surface_type == SHD_SOLID_SURFACE)
|
||||
sock->flag &= ~SOCK_UNAVAIL;
|
||||
else
|
||||
sock->flag |= SOCK_UNAVAIL;
|
||||
}
|
||||
else if (STREQ(sock->name, "Flatness")) {
|
||||
if (surface_type == SHD_THIN_SURFACE)
|
||||
sock->flag &= ~SOCK_UNAVAIL;
|
||||
else
|
||||
sock->flag |= SOCK_UNAVAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* node type definition */
|
||||
void register_node_type_sh_bsdf_disney(void)
|
||||
{
|
||||
static bNodeType ntype;
|
||||
|
||||
sh_node_type_base(&ntype, SH_NODE_BSDF_DISNEY, "Disney BSDF", NODE_CLASS_SHADER, 0);
|
||||
node_type_compatibility(&ntype, NODE_NEW_SHADING);
|
||||
node_type_socket_templates(&ntype, sh_node_bsdf_disney_in, sh_node_bsdf_disney_out);
|
||||
node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
|
||||
node_type_init(&ntype, node_shader_init_disney);
|
||||
node_type_storage(&ntype, "", NULL, NULL);
|
||||
node_type_gpu(&ntype, node_shader_gpu_bsdf_disney);
|
||||
node_type_update(&ntype, node_shader_update_disney, NULL);
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
Reference in New Issue
Block a user