Compare commits
83 Commits
temp-ui-cp
...
cycles_dis
Author | SHA1 | Date | |
---|---|---|---|
![]() |
90778901c9 | ||
![]() |
76eebd9379 | ||
![]() |
013f4a152a | ||
![]() |
482ec5d1f2 | ||
26e906d162 | |||
0593b8c51b | |||
8c7e11423b | |||
17724e9d2d | |||
379ba346b0 | |||
f80dcb4f34 | |||
732db8a57f | |||
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 |
@@ -519,6 +519,19 @@ static ShaderNode *add_node(Scene *scene,
|
||||
}
|
||||
node = hair;
|
||||
}
|
||||
else if(b_node.is_a(&RNA_ShaderNodeBsdfPrincipled)) {
|
||||
BL::ShaderNodeBsdfPrincipled b_principled_node(b_node);
|
||||
PrincipledBsdfNode *principled = new PrincipledBsdfNode();
|
||||
switch (b_principled_node.distribution()) {
|
||||
case BL::ShaderNodeBsdfPrincipled::distribution_GGX:
|
||||
principled->distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
|
||||
break;
|
||||
case BL::ShaderNodeBsdfPrincipled::distribution_MULTI_GGX:
|
||||
principled->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
|
||||
break;
|
||||
}
|
||||
node = principled;
|
||||
}
|
||||
else if(b_node.is_a(&RNA_ShaderNodeBsdfTranslucent)) {
|
||||
node = new TranslucentBsdfNode();
|
||||
}
|
||||
|
@@ -120,6 +120,8 @@ set(SRC_CLOSURE_HEADERS
|
||||
closure/bssrdf.h
|
||||
closure/emissive.h
|
||||
closure/volume.h
|
||||
closure/bsdf_principled_diffuse.h
|
||||
closure/bsdf_principled_sheen.h
|
||||
)
|
||||
|
||||
set(SRC_SVM_HEADERS
|
||||
|
@@ -27,6 +27,8 @@
|
||||
#include "kernel/closure/bsdf_ashikhmin_shirley.h"
|
||||
#include "kernel/closure/bsdf_toon.h"
|
||||
#include "kernel/closure/bsdf_hair.h"
|
||||
#include "kernel/closure/bsdf_principled_diffuse.h"
|
||||
#include "kernel/closure/bsdf_principled_sheen.h"
|
||||
#ifdef __SUBSURFACE__
|
||||
# include "kernel/closure/bssrdf.h"
|
||||
#endif
|
||||
@@ -86,16 +88,21 @@ 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:
|
||||
label = bsdf_microfacet_ggx_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
|
||||
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
|
||||
label = bsdf_microfacet_multi_ggx_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
|
||||
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf, &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, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
|
||||
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf, &sd->lcg_state);
|
||||
break;
|
||||
@@ -130,6 +137,15 @@ ccl_device_forceinline int bsdf_sample(KernelGlobals *kg,
|
||||
label = bsdf_hair_transmission_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
|
||||
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
|
||||
case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
|
||||
label = bsdf_principled_diffuse_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
|
||||
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
|
||||
label = bsdf_principled_sheen_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
|
||||
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
|
||||
break;
|
||||
#endif
|
||||
#ifdef __VOLUME__
|
||||
case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
|
||||
@@ -188,14 +204,19 @@ float3 bsdf_eval(KernelGlobals *kg,
|
||||
eval = bsdf_transparent_eval_reflect(sc, 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:
|
||||
eval = bsdf_microfacet_ggx_eval_reflect(sc, 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, sd->I, omega_in, pdf, &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, sd->I, omega_in, pdf, &sd->lcg_state);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
@@ -222,6 +243,13 @@ float3 bsdf_eval(KernelGlobals *kg,
|
||||
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
|
||||
eval = bsdf_hair_transmission_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
|
||||
case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
|
||||
eval = bsdf_principled_diffuse_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
|
||||
eval = bsdf_principled_sheen_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
#endif
|
||||
#ifdef __VOLUME__
|
||||
case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
|
||||
@@ -256,14 +284,19 @@ float3 bsdf_eval(KernelGlobals *kg,
|
||||
eval = bsdf_transparent_eval_transmit(sc, 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:
|
||||
eval = bsdf_microfacet_ggx_eval_transmit(sc, 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, sd->I, omega_in, pdf, &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, sd->I, omega_in, pdf, &sd->lcg_state);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
@@ -290,6 +323,13 @@ float3 bsdf_eval(KernelGlobals *kg,
|
||||
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
|
||||
eval = bsdf_hair_transmission_eval_transmit(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
|
||||
case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
|
||||
eval = bsdf_principled_diffuse_eval_transmit(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
|
||||
eval = bsdf_principled_sheen_eval_transmit(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
#endif
|
||||
#ifdef __VOLUME__
|
||||
case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
|
||||
@@ -311,11 +351,16 @@ 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:
|
||||
bsdf_microfacet_ggx_blur(sc, roughness);
|
||||
break;
|
||||
@@ -349,10 +394,15 @@ 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_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:
|
||||
|
@@ -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;
|
||||
|
||||
@@ -319,6 +398,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_principled_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 +408,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_principled_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 +466,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_principled_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 +482,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);
|
||||
@@ -489,6 +587,17 @@ 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);
|
||||
}
|
||||
|
||||
label = LABEL_REFLECT | LABEL_SINGULAR;
|
||||
}
|
||||
else {
|
||||
@@ -497,16 +606,32 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
|
||||
float alpha2 = alpha_x * alpha_y;
|
||||
float D, G1i;
|
||||
|
||||
bool is_principled_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_principled_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)));
|
||||
}
|
||||
@@ -538,10 +663,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_principled_clearcoat) {
|
||||
F *= 0.25f * bsdf->extra->clearcoat;
|
||||
}
|
||||
|
||||
*eval = G1i * common * F;
|
||||
}
|
||||
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
|
@@ -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
|
||||
|
||||
|
120
intern/cycles/kernel/closure/bsdf_principled_diffuse.h
Normal file
120
intern/cycles/kernel/closure/bsdf_principled_diffuse.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2011-2017 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_PRINCIPLED_DIFFUSE_H__
|
||||
#define __BSDF_PRINCIPLED_DIFFUSE_H__
|
||||
|
||||
/* DISNEY PRINCIPLED DIFFUSE BRDF
|
||||
*
|
||||
* Shading model by Brent Burley (Disney): "Physically Based Shading at Disney" (2012)
|
||||
*/
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
typedef ccl_addr_space struct PrincipledDiffuseBsdf {
|
||||
SHADER_CLOSURE_BASE;
|
||||
|
||||
float roughness;
|
||||
float3 N;
|
||||
} PrincipledDiffuseBsdf;
|
||||
|
||||
ccl_device float3 calculate_principled_diffuse_brdf(const PrincipledDiffuseBsdf *bsdf,
|
||||
float3 N, float3 V, float3 L, float3 H, float *pdf)
|
||||
{
|
||||
float NdotL = max(dot(N, L), 0.0f);
|
||||
float NdotV = max(dot(N, V), 0.0f);
|
||||
|
||||
if(NdotL < 0 || NdotV < 0) {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
float LdotH = dot(L, H);
|
||||
|
||||
float FL = schlick_fresnel(NdotL), FV = schlick_fresnel(NdotV);
|
||||
const float Fd90 = 0.5f + 2.0f * LdotH*LdotH * bsdf->roughness;
|
||||
float Fd = (1.0f * (1.0f - FL) + Fd90 * FL) * (1.0f * (1.0f - FV) + Fd90 * FV);
|
||||
|
||||
float value = M_1_PI_F * NdotL * Fd;
|
||||
|
||||
return make_float3(value, value, value);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_principled_diffuse_setup(PrincipledDiffuseBsdf *bsdf)
|
||||
{
|
||||
bsdf->type = CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID;
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_principled_diffuse_eval_reflect(const ShaderClosure *sc, const float3 I,
|
||||
const float3 omega_in, float *pdf)
|
||||
{
|
||||
const PrincipledDiffuseBsdf *bsdf = (const PrincipledDiffuseBsdf *)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_principled_diffuse_brdf(bsdf, N, V, L, H, pdf);
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_principled_diffuse_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_principled_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 PrincipledDiffuseBsdf *bsdf = (const PrincipledDiffuseBsdf *)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_principled_diffuse_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_PRINCIPLED_DIFFUSE_H__ */
|
||||
|
||||
|
114
intern/cycles/kernel/closure/bsdf_principled_sheen.h
Normal file
114
intern/cycles/kernel/closure/bsdf_principled_sheen.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 2011-2017 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_PRINCIPLED_SHEEN_H__
|
||||
#define __BSDF_PRINCIPLED_SHEEN_H__
|
||||
|
||||
/* DISNEY PRINCIPLED SHEEN BRDF
|
||||
*
|
||||
* Shading model by Brent Burley (Disney): "Physically Based Shading at Disney" (2012)
|
||||
*/
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
typedef ccl_addr_space struct PrincipledSheenBsdf {
|
||||
SHADER_CLOSURE_BASE;
|
||||
float3 N;
|
||||
} PrincipledSheenBsdf;
|
||||
|
||||
ccl_device float3 calculate_principled_sheen_brdf(const PrincipledSheenBsdf *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_principled_sheen_setup(PrincipledSheenBsdf *bsdf)
|
||||
{
|
||||
bsdf->type = CLOSURE_BSDF_PRINCIPLED_SHEEN_ID;
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_principled_sheen_eval_reflect(const ShaderClosure *sc, const float3 I,
|
||||
const float3 omega_in, float *pdf)
|
||||
{
|
||||
const PrincipledSheenBsdf *bsdf = (const PrincipledSheenBsdf *)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_principled_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_principled_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_principled_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 PrincipledSheenBsdf *bsdf = (const PrincipledSheenBsdf *)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_principled_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_PRINCIPLED_SHEEN_H__ */
|
||||
|
||||
|
@@ -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__ */
|
||||
|
@@ -27,6 +27,7 @@ typedef ccl_addr_space struct Bssrdf {
|
||||
float d;
|
||||
float texture_blur;
|
||||
float albedo;
|
||||
float roughness;
|
||||
float3 N;
|
||||
} Bssrdf;
|
||||
|
||||
@@ -360,10 +361,29 @@ 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_PRINCIPLED_ID) {
|
||||
float roughness = bssrdf->roughness;
|
||||
float3 N = bssrdf->N;
|
||||
float3 weight = bssrdf->weight;
|
||||
float sample_weight = bssrdf->sample_weight;
|
||||
|
||||
PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf*)bssrdf;
|
||||
|
||||
bsdf->N = N;
|
||||
bsdf->roughness = roughness;
|
||||
bsdf->weight = weight;
|
||||
bsdf->sample_weight = sample_weight;
|
||||
flag = bsdf_principled_diffuse_setup(bsdf);
|
||||
bsdf->type = CLOSURE_BSDF_BSSRDF_PRINCIPLED_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 +391,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_PRINCIPLED_ID) {
|
||||
bssrdf_burley_setup(bssrdf);
|
||||
}
|
||||
|
||||
@@ -385,7 +405,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_PRINCIPLED_ID)*/
|
||||
bssrdf_burley_sample(sc, xi, r, h);
|
||||
}
|
||||
|
||||
@@ -395,7 +415,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_PRINCIPLED_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_PRINCIPLED_ID) {
|
||||
PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf*)bsdf_alloc(sd, sizeof(PrincipledDiffuseBsdf), weight);
|
||||
|
||||
if(bsdf) {
|
||||
bsdf->N = N;
|
||||
sd->flag |= bsdf_diffuse_setup(bsdf);
|
||||
if(bsdf) {
|
||||
bsdf->N = N;
|
||||
bsdf->roughness = bssrdf->roughness;
|
||||
sd->flag |= bsdf_principled_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_PRINCIPLED_DIFFUSE_ID with this special ID so render passes
|
||||
* can recognize it as not being a regular Disney principled diffuse closure */
|
||||
bsdf->type = CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID;
|
||||
}
|
||||
}
|
||||
else if(CLOSURE_IS_BSSRDF(bssrdf->type)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -388,7 +404,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);
|
||||
}
|
||||
|
||||
#ifndef __SPLIT_KERNEL__
|
||||
@@ -479,7 +495,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);
|
||||
}
|
||||
#endif /* ! __SPLIT_KERNEL__ */
|
||||
|
||||
|
@@ -39,7 +39,9 @@
|
||||
#include "kernel/kernel_montecarlo.h"
|
||||
|
||||
#include "kernel/closure/alloc.h"
|
||||
#include "kernel/closure/bsdf_util.h"
|
||||
#include "kernel/closure/bsdf_diffuse.h"
|
||||
#include "kernel/closure/bsdf_principled_diffuse.h"
|
||||
#include "kernel/closure/bssrdf.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
@@ -78,6 +80,7 @@ public:
|
||||
bssrdf->albedo = albedo.x;
|
||||
bssrdf->sharpness = sharpness;
|
||||
bssrdf->N = params.N;
|
||||
bssrdf->roughness = params.roughness;
|
||||
sd->flag |= bssrdf_setup(bssrdf, (ClosureType)type);
|
||||
}
|
||||
|
||||
@@ -89,6 +92,7 @@ public:
|
||||
bssrdf->albedo = albedo.y;
|
||||
bssrdf->sharpness = sharpness;
|
||||
bssrdf->N = params.N;
|
||||
bssrdf->roughness = params.roughness;
|
||||
sd->flag |= bssrdf_setup(bssrdf, (ClosureType)type);
|
||||
}
|
||||
|
||||
@@ -100,6 +104,7 @@ public:
|
||||
bssrdf->albedo = albedo.z;
|
||||
bssrdf->sharpness = sharpness;
|
||||
bssrdf->N = params.N;
|
||||
bssrdf->roughness = params.roughness;
|
||||
sd->flag |= bssrdf_setup(bssrdf, (ClosureType)type);
|
||||
}
|
||||
}
|
||||
@@ -180,5 +185,31 @@ ClosureParam *closure_bssrdf_burley_params()
|
||||
|
||||
CCLOSURE_PREPARE(closure_bssrdf_burley_prepare, BurleyBSSRDFClosure)
|
||||
|
||||
/* Disney principled */
|
||||
|
||||
class PrincipledBSSRDFClosure : public CBSSRDFClosure {
|
||||
public:
|
||||
void setup(ShaderData *sd, int path_flag, float3 weight)
|
||||
{
|
||||
alloc(sd, path_flag, weight * albedo, CLOSURE_BSSRDF_PRINCIPLED_ID);
|
||||
}
|
||||
};
|
||||
|
||||
ClosureParam *closure_bssrdf_principled_params()
|
||||
{
|
||||
static ClosureParam params[] = {
|
||||
CLOSURE_FLOAT3_PARAM(PrincipledBSSRDFClosure, params.N),
|
||||
CLOSURE_FLOAT3_PARAM(PrincipledBSSRDFClosure, radius),
|
||||
CLOSURE_FLOAT_PARAM(PrincipledBSSRDFClosure, params.texture_blur),
|
||||
CLOSURE_FLOAT3_PARAM(PrincipledBSSRDFClosure, albedo),
|
||||
CLOSURE_FLOAT_PARAM(PrincipledBSSRDFClosure, params.roughness),
|
||||
CLOSURE_STRING_KEYPARAM(PrincipledBSSRDFClosure, label, "label"),
|
||||
CLOSURE_FINISH_PARAM(PrincipledBSSRDFClosure)
|
||||
};
|
||||
return params;
|
||||
}
|
||||
|
||||
CCLOSURE_PREPARE(closure_bssrdf_principled_prepare, PrincipledBSSRDFClosure)
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
@@ -60,6 +60,8 @@
|
||||
#include "kernel/closure/bsdf_ashikhmin_shirley.h"
|
||||
#include "kernel/closure/bsdf_toon.h"
|
||||
#include "kernel/closure/bsdf_hair.h"
|
||||
#include "kernel/closure/bsdf_principled_diffuse.h"
|
||||
#include "kernel/closure/bsdf_principled_sheen.h"
|
||||
#include "kernel/closure/volume.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
@@ -176,6 +178,63 @@ 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(PrincipledDiffuse, principled_diffuse, PrincipledDiffuseBsdf, LABEL_DIFFUSE)
|
||||
CLOSURE_FLOAT3_PARAM(PrincipledDiffuseClosure, params.N),
|
||||
CLOSURE_FLOAT_PARAM(PrincipledDiffuseClosure, params.roughness),
|
||||
BSDF_CLOSURE_CLASS_END(PrincipledDiffuse, principled_diffuse)
|
||||
|
||||
BSDF_CLOSURE_CLASS_BEGIN(PrincipledSheen, principled_sheen, PrincipledSheenBsdf, LABEL_DIFFUSE)
|
||||
CLOSURE_FLOAT3_PARAM(PrincipledSheenClosure, params.N),
|
||||
BSDF_CLOSURE_CLASS_END(PrincipledSheen, principled_sheen)
|
||||
|
||||
/* DISNEY PRINCIPLED CLEARCOAT */
|
||||
class PrincipledClearcoatClosure : 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_principled_clearcoat_params()
|
||||
{
|
||||
static ClosureParam params[] = {
|
||||
CLOSURE_FLOAT3_PARAM(PrincipledClearcoatClosure, params.N),
|
||||
CLOSURE_FLOAT_PARAM(PrincipledClearcoatClosure, clearcoat),
|
||||
CLOSURE_FLOAT_PARAM(PrincipledClearcoatClosure, clearcoat_gloss),
|
||||
CLOSURE_STRING_KEYPARAM(PrincipledClearcoatClosure, label, "label"),
|
||||
CLOSURE_FINISH_PARAM(PrincipledClearcoatClosure)
|
||||
};
|
||||
return params;
|
||||
}
|
||||
CCLOSURE_PREPARE(closure_bsdf_principled_clearcoat_prepare, PrincipledClearcoatClosure)
|
||||
|
||||
|
||||
/* Registration */
|
||||
|
||||
static void register_closure(OSL::ShadingSystem *ss, const char *name, int id, OSL::ClosureParam *params, OSL::PrepareClosureFunc prepare)
|
||||
@@ -215,6 +274,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++,
|
||||
@@ -229,6 +298,12 @@ 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, "principled_diffuse", id++,
|
||||
bsdf_principled_diffuse_params(), bsdf_principled_diffuse_prepare);
|
||||
register_closure(ss, "principled_sheen", id++,
|
||||
bsdf_principled_sheen_params(), bsdf_principled_sheen_prepare);
|
||||
register_closure(ss, "principled_clearcoat", id++,
|
||||
closure_bsdf_principled_clearcoat_params(), closure_bsdf_principled_clearcoat_prepare);
|
||||
|
||||
register_closure(ss, "emission", id++,
|
||||
closure_emission_params(), closure_emission_prepare);
|
||||
@@ -248,6 +323,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_principled", id++,
|
||||
closure_bssrdf_principled_params(), closure_bssrdf_principled_prepare);
|
||||
|
||||
register_closure(ss, "hair_reflection", id++,
|
||||
bsdf_hair_reflection_params(), bsdf_hair_reflection_prepare);
|
||||
@@ -278,6 +355,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 {
|
||||
@@ -287,7 +444,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)) {
|
||||
@@ -375,5 +532,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,17 @@ 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_principled_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();
|
||||
OSL::ClosureParam *closure_bsdf_principled_clearcoat_params();
|
||||
|
||||
void closure_emission_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void closure_background_prepare(OSL::RendererServices *, int id, void *data);
|
||||
@@ -65,10 +72,17 @@ 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_principled_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);
|
||||
void closure_bsdf_principled_clearcoat_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_principled_bsdf.osl
|
||||
node_rgb_to_bw.osl
|
||||
)
|
||||
|
||||
|
120
intern/cycles/kernel/shaders/node_principled_bsdf.osl
Normal file
120
intern/cycles/kernel/shaders/node_principled_bsdf.osl
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2011-2017 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_principled_bsdf(
|
||||
string distribution = "Multiscatter GGX",
|
||||
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 IOR = 1.45,
|
||||
float Transparency = 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(Transparency, 0.0, 1.0));
|
||||
float transp = clamp(Transparency, 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) {
|
||||
if (Subsurface > 1e-5) {
|
||||
color Albedo = SubsurfaceColor * Subsurface + BaseColor * (1.0 - Subsurface);
|
||||
BSDF = bssrdf_principled(Normal, Subsurface * SubsurfaceRadius, 0.0, Albedo, Roughness);
|
||||
} else {
|
||||
BSDF = BaseColor * principled_diffuse(Normal, Roughness);
|
||||
}
|
||||
|
||||
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 * principled_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() ? 1.0 / f : f;
|
||||
|
||||
if (distribution == "GGX" || Roughness <= 5e-2) {
|
||||
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);
|
||||
|
||||
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 + principled_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,15 @@ closure color emission() BUILTIN;
|
||||
closure color background() BUILTIN;
|
||||
closure color holdout() BUILTIN;
|
||||
closure color ambient_occlusion() BUILTIN;
|
||||
closure color principled_diffuse(normal N, float roughness) BUILTIN;
|
||||
closure color principled_sheen(normal N) BUILTIN;
|
||||
closure color principled_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_principled(normal N, vector radius, float texture_blur, color subsurface_color, float roughness) BUILTIN;
|
||||
|
||||
// Hair
|
||||
closure color hair_reflection(normal N, float roughnessu, float roughnessv, vector T, float offset) BUILTIN;
|
||||
|
@@ -76,6 +76,338 @@ 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_PRINCIPLED_ID: {
|
||||
uint specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset, sheen_offset,
|
||||
sheen_tint_offset, clearcoat_offset, clearcoat_gloss_offset, eta_offset, transparency_offset,
|
||||
anisotropic_rotation_offset, refraction_roughness_offset;
|
||||
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, &transparency_offset, &anisotropic_rotation_offset, &refraction_roughness_offset);
|
||||
|
||||
// get Disney principled 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 transparency = stack_load_float(stack, transparency_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);
|
||||
|
||||
ClosureType distribution = stack_valid(data_node2.y) ? (ClosureType) data_node2.y : CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
|
||||
|
||||
/* rotate tangent */
|
||||
if(anisotropic_rotation != 0.0f)
|
||||
T = rotate_around_axis(T, N, anisotropic_rotation * M_2PI_F);
|
||||
|
||||
/* calculate ior */
|
||||
float ior = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
|
||||
|
||||
// calculate fresnel for refraction
|
||||
float cosNO = dot(N, 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(transparency));
|
||||
|
||||
float transp = saturate(transparency) * (1.0f - saturate(metallic));
|
||||
float specular_weight = (1.0f - 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) : 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 = sd->svm_closure_weight * mix_weight;
|
||||
|
||||
#ifdef __SUBSURFACE__
|
||||
float3 albedo = subsurface_color * subsurface + base_color * (1.0f - subsurface);
|
||||
float3 subsurf_weight = weight * albedo * 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(fabsf(average(base_color)) > CLOSURE_WEIGHT_CUTOFF) {
|
||||
if(subsurface < CLOSURE_WEIGHT_CUTOFF && diffuse_weight > CLOSURE_WEIGHT_CUTOFF) {
|
||||
float3 diff_weight = weight * base_color * diffuse_weight;
|
||||
|
||||
PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf*)bsdf_alloc(sd, sizeof(PrincipledDiffuseBsdf), diff_weight);
|
||||
|
||||
if(bsdf) {
|
||||
bsdf->N = N;
|
||||
bsdf->roughness = roughness;
|
||||
|
||||
/* setup bsdf */
|
||||
sd->flag |= bsdf_principled_diffuse_setup(bsdf);
|
||||
}
|
||||
}
|
||||
else if(subsurface > CLOSURE_WEIGHT_CUTOFF && 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->roughness = roughness;
|
||||
|
||||
/* setup bsdf */
|
||||
sd->flag |= bssrdf_setup(bssrdf, (ClosureType)CLOSURE_BSSRDF_PRINCIPLED_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->roughness = roughness;
|
||||
|
||||
/* setup bsdf */
|
||||
sd->flag |= bssrdf_setup(bssrdf, (ClosureType)CLOSURE_BSSRDF_PRINCIPLED_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->roughness = roughness;
|
||||
|
||||
/* setup bsdf */
|
||||
sd->flag |= bssrdf_setup(bssrdf, (ClosureType)CLOSURE_BSSRDF_PRINCIPLED_ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* diffuse */
|
||||
if(diffuse_weight > CLOSURE_WEIGHT_CUTOFF) {
|
||||
float3 diff_weight = weight * base_color * diffuse_weight;
|
||||
|
||||
PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf*)bsdf_alloc(sd, sizeof(PrincipledDiffuseBsdf), diff_weight);
|
||||
|
||||
if(bsdf) {
|
||||
bsdf->N = N;
|
||||
bsdf->roughness = roughness;
|
||||
|
||||
/* setup bsdf */
|
||||
sd->flag |= bsdf_principled_diffuse_setup(bsdf);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 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;
|
||||
|
||||
PrincipledSheenBsdf *bsdf = (PrincipledSheenBsdf*)bsdf_alloc(sd, sizeof(PrincipledSheenBsdf), sheen_weight);
|
||||
|
||||
if(bsdf) {
|
||||
bsdf->N = N;
|
||||
|
||||
/* setup bsdf */
|
||||
sd->flag |= bsdf_principled_sheen_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;
|
||||
|
||||
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 */
|
||||
sd->flag |= bsdf_microfacet_ggx_aniso_fresnel_setup(bsdf);
|
||||
else /* use multi-scatter GGX */
|
||||
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(transp > CLOSURE_WEIGHT_CUTOFF) {
|
||||
float3 glass_weight = weight * 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) { /* 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
|
||||
{
|
||||
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 */
|
||||
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;
|
||||
|
||||
bsdf->alpha_x = refraction_roughness * refraction_roughness;
|
||||
bsdf->alpha_y = refraction_roughness * refraction_roughness;
|
||||
bsdf->ior = ior;
|
||||
|
||||
/* setup bsdf */
|
||||
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 */
|
||||
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 */
|
||||
sd->flag |= bsdf_microfacet_ggx_clearcoat_setup(bsdf);
|
||||
}
|
||||
}
|
||||
#ifdef __CAUSTICS_TRICKS__
|
||||
}
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
case CLOSURE_BSDF_DIFFUSE_ID: {
|
||||
float3 weight = sd->svm_closure_weight * mix_weight;
|
||||
OrenNayarBsdf *bsdf = (OrenNayarBsdf*)bsdf_alloc(sd, sizeof(OrenNayarBsdf), weight);
|
||||
|
@@ -397,17 +397,24 @@ typedef enum ClosureType {
|
||||
CLOSURE_BSDF_DIFFUSE_ID,
|
||||
CLOSURE_BSDF_OREN_NAYAR_ID,
|
||||
CLOSURE_BSDF_DIFFUSE_RAMP_ID,
|
||||
CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID,
|
||||
CLOSURE_BSDF_PRINCIPLED_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,
|
||||
@@ -424,16 +431,19 @@ typedef enum ClosureType {
|
||||
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_PRINCIPLED_ID,
|
||||
CLOSURE_BSDF_TRANSPARENT_ID,
|
||||
|
||||
/* BSSRDF */
|
||||
CLOSURE_BSSRDF_CUBIC_ID,
|
||||
CLOSURE_BSSRDF_GAUSSIAN_ID,
|
||||
CLOSURE_BSSRDF_PRINCIPLED_ID,
|
||||
CLOSURE_BSSRDF_BURLEY_ID,
|
||||
|
||||
/* Other */
|
||||
@@ -447,6 +457,8 @@ typedef enum ClosureType {
|
||||
CLOSURE_VOLUME_ABSORPTION_ID,
|
||||
CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID,
|
||||
|
||||
CLOSURE_BSDF_PRINCIPLED_ID,
|
||||
|
||||
NBUILTIN_CLOSURES
|
||||
} ClosureType;
|
||||
|
||||
@@ -455,7 +467,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_PRINCIPLED_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 || \
|
||||
@@ -469,6 +481,7 @@ 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_PRINCIPLED(type) (type == CLOSURE_BSDF_PRINCIPLED_ID)
|
||||
|
||||
#define CLOSURE_WEIGHT_CUTOFF 1e-5f
|
||||
|
||||
|
@@ -997,6 +997,9 @@ int ShaderGraph::get_num_closures()
|
||||
else if(CLOSURE_IS_BSDF_MULTISCATTER(closure_type)) {
|
||||
num_closures += 2;
|
||||
}
|
||||
else if(CLOSURE_IS_PRINCIPLED(closure_type)) {
|
||||
num_closures += 8;
|
||||
}
|
||||
else {
|
||||
++num_closures;
|
||||
}
|
||||
|
@@ -2286,6 +2286,150 @@ void DiffuseBsdfNode::compile(OSLCompiler& compiler)
|
||||
compiler.add(this, "node_diffuse_bsdf");
|
||||
}
|
||||
|
||||
/* Disney principled BSDF Closure */
|
||||
NODE_DEFINE(PrincipledBsdfNode)
|
||||
{
|
||||
NodeType* type = NodeType::add("principled_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);
|
||||
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(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(ior, "IOR", 0.0f);
|
||||
SOCKET_IN_FLOAT(transparency, "Transparency", 0.0f);
|
||||
SOCKET_IN_FLOAT(refraction_roughness, "Refraction Roughness", 0.0f);
|
||||
SOCKET_IN_FLOAT(anisotropic_rotation, "Anisotropic Rotation", 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;
|
||||
}
|
||||
|
||||
PrincipledBsdfNode::PrincipledBsdfNode()
|
||||
: ShaderNode(node_type)
|
||||
{
|
||||
special_type = SHADER_SPECIAL_TYPE_CLOSURE;
|
||||
closure = CLOSURE_BSDF_PRINCIPLED_ID;
|
||||
distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
|
||||
distribution_orig = NBUILTIN_CLOSURES;
|
||||
}
|
||||
|
||||
void PrincipledBsdfNode::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 PrincipledBsdfNode::compile(SVMCompiler& compiler, ShaderInput *p_metallic, ShaderInput *p_subsurface, ShaderInput *p_subsurface_radius,
|
||||
ShaderInput *p_specular, ShaderInput *p_roughness, ShaderInput *p_specular_tint, ShaderInput *p_anisotropic,
|
||||
ShaderInput *p_sheen, ShaderInput *p_sheen_tint, ShaderInput *p_clearcoat, ShaderInput *p_clearcoat_gloss,
|
||||
ShaderInput *p_ior, ShaderInput *p_transparency, ShaderInput *p_anisotropic_rotation, 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 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 ior_offset = compiler.stack_assign(p_ior);
|
||||
int transparency_offset = compiler.stack_assign(p_transparency);
|
||||
int refraction_roughness_offset = compiler.stack_assign(p_refraction_roughness);
|
||||
int anisotropic_rotation_offset = compiler.stack_assign(p_anisotropic_rotation);
|
||||
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, transparency_offset, anisotropic_rotation_offset, refraction_roughness_offset),
|
||||
distribution, SVM_STACK_INVALID, SVM_STACK_INVALID);
|
||||
|
||||
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 PrincipledBsdfNode::has_integrator_dependency()
|
||||
{
|
||||
ShaderInput *roughness_input = input("Roughness");
|
||||
return !roughness_input->link && roughness <= 1e-4f;
|
||||
}
|
||||
|
||||
void PrincipledBsdfNode::compile(SVMCompiler& compiler)
|
||||
{
|
||||
compile(compiler, input("Metallic"), input("Subsurface"), input("Subsurface Radius"), input("Specular"),
|
||||
input("Roughness"), input("Specular Tint"), input("Anisotropic"), input("Sheen"), input("Sheen Tint"),
|
||||
input("Clearcoat"), input("Clearcoat Gloss"), input("IOR"), input("Transparency"),
|
||||
input("Anisotropic Rotation"), input("Refraction Roughness"));
|
||||
}
|
||||
|
||||
void PrincipledBsdfNode::compile(OSLCompiler& compiler)
|
||||
{
|
||||
compiler.parameter(this, "distribution");
|
||||
compiler.add(this, "node_principled_bsdf");
|
||||
}
|
||||
|
||||
bool PrincipledBsdfNode::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,39 @@ public:
|
||||
float roughness;
|
||||
};
|
||||
|
||||
/* Disney principled BRDF */
|
||||
class PrincipledBsdfNode : public ShaderNode {
|
||||
public:
|
||||
SHADER_NODE_CLASS(PrincipledBsdfNode)
|
||||
|
||||
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 *roughness, ShaderInput *specular_tint, ShaderInput *anisotropic,
|
||||
ShaderInput *sheen, ShaderInput *sheen_tint, ShaderInput *clearcoat, ShaderInput *clearcoat_gloss,
|
||||
ShaderInput *ior, ShaderInput *transparency, ShaderInput *anisotropic_rotation, 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, transparency,
|
||||
anisotropic_rotation, refraction_roughness;
|
||||
float3 normal, clearcoat_normal, tangent;
|
||||
float surface_mix_weight;
|
||||
ClosureType closure, distribution, distribution_orig;
|
||||
|
||||
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)
|
||||
|
@@ -225,6 +225,7 @@ shader_node_categories = [
|
||||
NodeItem("ShaderNodeMixShader"),
|
||||
NodeItem("ShaderNodeAddShader"),
|
||||
NodeItem("ShaderNodeBsdfDiffuse", poll=object_shader_nodes_poll),
|
||||
NodeItem("ShaderNodeBsdfPrincipled", 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),
|
||||
|
@@ -785,6 +785,7 @@ struct ShadeResult;
|
||||
#define SH_NODE_OUTPUT_LINESTYLE 190
|
||||
#define SH_NODE_UVALONGSTROKE 191
|
||||
#define SH_NODE_TEX_POINTDENSITY 192
|
||||
#define SH_NODE_BSDF_PRINCIPLED 193
|
||||
|
||||
/* custom defines options for Material node */
|
||||
#define SH_NODE_MAT_DIFF 1
|
||||
|
@@ -3568,6 +3568,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_principled();
|
||||
register_node_type_sh_bsdf_glossy();
|
||||
register_node_type_sh_bsdf_glass();
|
||||
register_node_type_sh_bsdf_translucent();
|
||||
|
@@ -1234,6 +1234,7 @@ static void node_shader_set_butfunc(bNodeType *ntype)
|
||||
case SH_NODE_BSDF_GLOSSY:
|
||||
case SH_NODE_BSDF_GLASS:
|
||||
case SH_NODE_BSDF_REFRACTION:
|
||||
case SH_NODE_BSDF_PRINCIPLED:
|
||||
ntype->draw_buttons = node_shader_buts_glossy;
|
||||
break;
|
||||
case SH_NODE_BSDF_ANISOTROPIC:
|
||||
|
@@ -2378,11 +2378,19 @@ void shade_alpha_obcolor(vec4 col, vec4 obcol, out vec4 outcol)
|
||||
|
||||
/*********** NEW SHADER UTILITIES **************/
|
||||
|
||||
float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta)
|
||||
float fresnel_dielectric_0(float eta)
|
||||
{
|
||||
/* compute fresnel reflactance at normal incidence => cosi = 1.0 */
|
||||
float A = (eta - 1.0) / (eta + 1.0);
|
||||
|
||||
return A * A;
|
||||
}
|
||||
|
||||
float fresnel_dielectric_cos(float cosi, float eta)
|
||||
{
|
||||
/* compute fresnel reflectance without explicitly computing
|
||||
* the refracted direction */
|
||||
float c = abs(dot(Incoming, Normal));
|
||||
float c = abs(cosi);
|
||||
float g = eta * eta - 1.0 + c * c;
|
||||
float result;
|
||||
|
||||
@@ -2399,6 +2407,13 @@ float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta)
|
||||
return result;
|
||||
}
|
||||
|
||||
float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta)
|
||||
{
|
||||
/* compute fresnel reflectance without explicitly computing
|
||||
* the refracted direction */
|
||||
return fresnel_dielectric_cos(dot(Incoming, Normal), eta);
|
||||
}
|
||||
|
||||
float hypot(float x, float y)
|
||||
{
|
||||
return sqrt(x * x + y * y);
|
||||
@@ -2492,6 +2507,57 @@ float floorfrac(float x, out int i)
|
||||
return x - i;
|
||||
}
|
||||
|
||||
|
||||
/* Principled BSDF operations */
|
||||
|
||||
float sqr(float a)
|
||||
{
|
||||
return a*a;
|
||||
}
|
||||
|
||||
float schlick_fresnel(float u)
|
||||
{
|
||||
float m = clamp(1.0 - u, 0.0, 1.0);
|
||||
float m2 = m * m;
|
||||
return m2 * m2 * m; // pow(m,5)
|
||||
}
|
||||
|
||||
float GTR1(float NdotH, float a)
|
||||
{
|
||||
if (a >= 1.0) return M_1_PI;
|
||||
float a2 = a*a;
|
||||
float t = 1.0 + (a2 - 1.0) * NdotH*NdotH;
|
||||
return (a2 - 1.0) / (M_PI * log(a2) * t);
|
||||
}
|
||||
|
||||
float GTR2(float NdotH, float a)
|
||||
{
|
||||
float a2 = a*a;
|
||||
float t = 1.0 + (a2 - 1.0) * NdotH*NdotH;
|
||||
return a2 / (M_PI * t*t);
|
||||
}
|
||||
|
||||
float GTR2_aniso(float NdotH, float HdotX, float HdotY, float ax, float ay)
|
||||
{
|
||||
return 1.0 / (M_PI * ax*ay * sqr(sqr(HdotX / ax) + sqr(HdotY / ay) + NdotH*NdotH));
|
||||
}
|
||||
|
||||
float smithG_GGX(float NdotV, float alphaG)
|
||||
{
|
||||
float a = alphaG*alphaG;
|
||||
float b = NdotV*NdotV;
|
||||
return 1.0 / (NdotV + sqrt(a + b - a * b));
|
||||
}
|
||||
|
||||
vec3 rotate_vector(vec3 p, vec3 n, float theta) {
|
||||
return (
|
||||
p * cos(theta) + cross(n, p) *
|
||||
sin(theta) + n * dot(p, n) *
|
||||
(1.0 - cos(theta))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/*********** NEW SHADER NODES ***************/
|
||||
|
||||
#define NUM_LIGHTS 3
|
||||
@@ -2553,6 +2619,126 @@ 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_principled(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, vec3 I, out vec4 result)
|
||||
{
|
||||
/* ambient light */
|
||||
// TODO: set ambient light to an appropriate value
|
||||
vec3 L = vec3(mix(0.1, 0.03, metallic)) * base_color.rgb;
|
||||
|
||||
float eta = (2.0 / (1.0 - sqrt(0.08 * specular))) - 1.0;
|
||||
|
||||
/* set the viewing vector */
|
||||
vec3 V = -normalize(I);
|
||||
|
||||
/* get the tangent */
|
||||
vec3 Tangent = T;
|
||||
if (T == vec3(0.0)) {
|
||||
// if no tangent is set, use a default tangent
|
||||
Tangent = vec3(1.0, 0.0, 0.0);
|
||||
if (N.x != 0.0 || N.y != 0.0) {
|
||||
vec3 N_xz = normalize(vec3(N.x, 0.0, N.z));
|
||||
|
||||
vec3 axis = normalize(cross(vec3(0.0, 0.0, 1.0), N_xz));
|
||||
float angle = acos(dot(vec3(0.0, 0.0, 1.0), N_xz));
|
||||
|
||||
Tangent = normalize(rotate_vector(vec3(1.0, 0.0, 0.0), axis, angle));
|
||||
}
|
||||
}
|
||||
|
||||
/* rotate tangent */
|
||||
if (anisotropic_rotation != 0.0) {
|
||||
Tangent = rotate_vector(Tangent, N, anisotropic_rotation * 2.0 * M_PI);
|
||||
}
|
||||
|
||||
/* calculate the tangent and bitangent */
|
||||
vec3 Y = normalize(cross(N, Tangent));
|
||||
vec3 X = cross(Y, N);
|
||||
|
||||
/* fresnel normalization parameters */
|
||||
float F0 = fresnel_dielectric_0(eta);
|
||||
float F0_norm = 1.0 / (1.0 - F0);
|
||||
|
||||
/* directional lights */
|
||||
for (int i = 0; i < NUM_LIGHTS; i++) {
|
||||
vec3 light_position_world = gl_LightSource[i].position.xyz;
|
||||
vec3 light_position = normalize(gl_NormalMatrix * light_position_world);
|
||||
|
||||
vec3 H = normalize(light_position + V);
|
||||
|
||||
vec3 light_specular = gl_LightSource[i].specular.rgb;
|
||||
|
||||
float NdotL = dot(N, light_position);
|
||||
float NdotV = dot(N, V);
|
||||
float LdotH = dot(light_position, H);
|
||||
|
||||
vec3 diffuse_and_specular_bsdf = vec3(0.0);
|
||||
if (NdotL >= 0.0 && NdotV >= 0.0) {
|
||||
float NdotH = dot(N, H);
|
||||
|
||||
float Cdlum = 0.3 * base_color.r + 0.6 * base_color.g + 0.1 * base_color.b; // luminance approx.
|
||||
|
||||
vec3 Ctint = Cdlum > 0 ? base_color.rgb / Cdlum : vec3(1.0); // normalize lum. to isolate hue+sat
|
||||
vec3 Cspec0 = mix(specular * 0.08 * mix(vec3(1.0), Ctint, specular_tint), base_color.rgb, metallic);
|
||||
vec3 Csheen = mix(vec3(1.0), Ctint, sheen_tint);
|
||||
|
||||
// Diffuse fresnel - go from 1 at normal incidence to .5 at grazing
|
||||
// and mix in diffuse retro-reflection based on roughness
|
||||
|
||||
float FL = schlick_fresnel(NdotL), FV = schlick_fresnel(NdotV);
|
||||
float Fd90 = 0.5 + 2.0 * LdotH*LdotH * roughness;
|
||||
float Fd = mix(1.0, Fd90, FL) * mix(1.0, Fd90, FV);
|
||||
|
||||
// Based on Hanrahan-Krueger brdf approximation of isotropic bssrdf
|
||||
// 1.25 scale is used to (roughly) preserve albedo
|
||||
// Fss90 used to "flatten" retroreflection based on roughness
|
||||
float Fss90 = LdotH*LdotH * roughness;
|
||||
float Fss = mix(1.0, Fss90, FL) * mix(1.0, Fss90, FV);
|
||||
float ss = 1.25 * (Fss * (1.0 / (NdotL + NdotV) - 0.5) + 0.5);
|
||||
|
||||
// specular
|
||||
float aspect = sqrt(1.0 - anisotropic * 0.9);
|
||||
float a = sqr(roughness);
|
||||
float ax = max(0.001, a / aspect);
|
||||
float ay = max(0.001, a * aspect);
|
||||
float Ds = GTR2_aniso(NdotH, dot(H, X), dot(H, Y), ax, ay); //GTR2(NdotH, a);
|
||||
float FH = (fresnel_dielectric_cos(LdotH, eta) - F0) * F0_norm;
|
||||
vec3 Fs = mix(Cspec0, vec3(1.0), FH);
|
||||
float roughg = sqr(roughness * 0.5 + 0.5);
|
||||
float Gs = smithG_GGX(NdotL, roughg) * smithG_GGX(NdotV, roughg);
|
||||
|
||||
// sheen
|
||||
vec3 Fsheen = schlick_fresnel(LdotH) * sheen * Csheen;
|
||||
|
||||
diffuse_and_specular_bsdf = (M_1_PI * mix(Fd, ss, subsurface) * base_color.rgb + Fsheen)
|
||||
* (1.0 - metallic) + Gs * Fs * Ds;
|
||||
}
|
||||
diffuse_and_specular_bsdf *= max(NdotL, 0.0);
|
||||
|
||||
float CNdotL = dot(CN, light_position);
|
||||
float CNdotV = dot(CN, V);
|
||||
|
||||
vec3 clearcoat_bsdf = vec3(0.0);
|
||||
if (CNdotL >= 0.0 && CNdotV >= 0.0 && clearcoat > 0.0) {
|
||||
float CNdotH = dot(CN, H);
|
||||
//float FH = schlick_fresnel(LdotH);
|
||||
|
||||
// clearcoat (ior = 1.5 -> F0 = 0.04)
|
||||
float Dr = GTR1(CNdotH, mix(0.1, 0.001, clearcoat_gloss));
|
||||
float Fr = fresnel_dielectric_cos(LdotH, 1.5); //mix(0.04, 1.0, FH);
|
||||
float Gr = smithG_GGX(CNdotL, 0.25) * smithG_GGX(CNdotV, 0.25);
|
||||
|
||||
clearcoat_bsdf = clearcoat * Gr * Fr * Dr * vec3(0.25);
|
||||
}
|
||||
clearcoat_bsdf *= max(CNdotL, 0.0);
|
||||
|
||||
L += light_specular * (diffuse_and_specular_bsdf + clearcoat_bsdf);
|
||||
}
|
||||
|
||||
result = vec4(L, 1.0);
|
||||
}
|
||||
|
||||
void node_bsdf_translucent(vec4 color, vec3 N, out vec4 result)
|
||||
{
|
||||
node_bsdf_diffuse(color, 0.0, N, result);
|
||||
|
@@ -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_ShaderNodePrincipled_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;
|
||||
@@ -3254,6 +3263,12 @@ static EnumPropertyItem node_script_mode_items[] = {
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
static EnumPropertyItem node_principled_distribution_items[] = {
|
||||
{ SHD_GLOSSY_GGX, "GGX", 0, "GGX", "" },
|
||||
{ SHD_GLOSSY_MULTI_GGX, "MULTI_GGX", 0, "Multiscatter GGX", "" },
|
||||
{ 0, NULL, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
/* -- Common nodes ---------------------------------------------------------- */
|
||||
|
||||
static void def_group_input(StructRNA *srna)
|
||||
@@ -4188,6 +4203,17 @@ static void def_glass(StructRNA *srna)
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
}
|
||||
|
||||
static void def_principled(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
prop = RNA_def_property(srna, "distribution", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "custom1");
|
||||
RNA_def_property_enum_items(prop, node_principled_distribution_items);
|
||||
RNA_def_property_ui_text(prop, "Distribution", "");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodePrincipled_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_principled.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_principled(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_PRINCIPLED, def_principled, "BSDF_PRINCIPLED", BsdfPrincipled, "Principled 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", "" )
|
||||
|
114
source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
Normal file
114
source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* ***** 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_principled_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_("IOR"), 1.45f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
|
||||
{ SOCK_FLOAT, 1, N_("Transparency"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.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_principled_out[] = {
|
||||
{ SOCK_SHADER, 0, N_("BSDF")},
|
||||
{ -1, 0, "" }
|
||||
};
|
||||
|
||||
static void node_shader_init_principled(bNodeTree *UNUSED(ntree), bNode *node)
|
||||
{
|
||||
node->custom1 = SHD_GLOSSY_MULTI_GGX;
|
||||
}
|
||||
|
||||
static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
|
||||
{
|
||||
// normal
|
||||
if (!in[17].link)
|
||||
in[17].link = GPU_builtin(GPU_VIEW_NORMAL);
|
||||
else
|
||||
GPU_link(mat, "direction_transform_m4v3", in[17].link, GPU_builtin(GPU_VIEW_MATRIX), &in[17].link);
|
||||
|
||||
// clearcoat normal
|
||||
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_principled", in, out, GPU_builtin(GPU_VIEW_POSITION));
|
||||
}
|
||||
|
||||
static void node_shader_update_principled(bNodeTree *UNUSED(ntree), bNode *node)
|
||||
{
|
||||
bNodeSocket *sock;
|
||||
int distribution = node->custom1;
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* node type definition */
|
||||
void register_node_type_sh_bsdf_principled(void)
|
||||
{
|
||||
static bNodeType ntype;
|
||||
|
||||
sh_node_type_base(&ntype, SH_NODE_BSDF_PRINCIPLED, "Principled BSDF", NODE_CLASS_SHADER, 0);
|
||||
node_type_compatibility(&ntype, NODE_NEW_SHADING);
|
||||
node_type_socket_templates(&ntype, sh_node_bsdf_principled_in, sh_node_bsdf_principled_out);
|
||||
node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
|
||||
node_type_init(&ntype, node_shader_init_principled);
|
||||
node_type_storage(&ntype, "", NULL, NULL);
|
||||
node_type_gpu(&ntype, node_shader_gpu_bsdf_principled);
|
||||
node_type_update(&ntype, node_shader_update_principled, NULL);
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
Reference in New Issue
Block a user