Merge remote-tracking branch 'origin/master' into blender2.8
This commit is contained in:
commit
c9d78b6c43
|
@ -2593,7 +2593,6 @@ install_DEB() {
|
|||
fi
|
||||
|
||||
# These libs should always be available in debian/ubuntu official repository...
|
||||
OPENJPEG_DEV="libopenjpeg-dev"
|
||||
VORBIS_DEV="libvorbis-dev"
|
||||
OGG_DEV="libogg-dev"
|
||||
THEORA_DEV="libtheora-dev"
|
||||
|
@ -2601,16 +2600,24 @@ install_DEB() {
|
|||
_packages="gawk cmake cmake-curses-gui build-essential libjpeg-dev libpng-dev libtiff-dev \
|
||||
git libfreetype6-dev libx11-dev flex bison libtbb-dev libxxf86vm-dev \
|
||||
libxcursor-dev libxi-dev wget libsqlite3-dev libxrandr-dev libxinerama-dev \
|
||||
libbz2-dev libncurses5-dev libssl-dev liblzma-dev libreadline-dev $OPENJPEG_DEV \
|
||||
libbz2-dev libncurses5-dev libssl-dev liblzma-dev libreadline-dev \
|
||||
libopenal-dev libglew-dev yasm $THEORA_DEV $VORBIS_DEV $OGG_DEV \
|
||||
libsdl1.2-dev libfftw3-dev patch bzip2 libxml2-dev libtinyxml-dev libjemalloc-dev"
|
||||
# libglewmx-dev (broken in deb testing currently...)
|
||||
|
||||
OPENJPEG_USE=true
|
||||
VORBIS_USE=true
|
||||
OGG_USE=true
|
||||
THEORA_USE=true
|
||||
|
||||
PRINT ""
|
||||
# New Ubuntu crap (17.04 and more) have no openjpeg lib!
|
||||
OPENJPEG_DEV="libopenjpeg-dev"
|
||||
check_package_DEB $OPENJPEG_DEV
|
||||
if [ $? -eq 0 ]; then
|
||||
_packages="$_packages $OPENJPEG_DEV"
|
||||
OPENJPEG_USE=true
|
||||
fi
|
||||
|
||||
PRINT ""
|
||||
# Some not-so-old distro (ubuntu 12.4) do not have it, do not fail in this case, just warn.
|
||||
YAMLCPP_DEV="libyaml-cpp-dev"
|
||||
|
|
|
@ -379,27 +379,16 @@ Object *BlenderSync::sync_object(BL::Object& b_parent,
|
|||
}
|
||||
}
|
||||
|
||||
/* random number */
|
||||
object->random_id = hash_string(object->name.c_str());
|
||||
|
||||
if(persistent_id) {
|
||||
for(int i = 0; i < OBJECT_PERSISTENT_ID_SIZE; i++)
|
||||
object->random_id = hash_int_2d(object->random_id, persistent_id[i]);
|
||||
}
|
||||
else
|
||||
object->random_id = hash_int_2d(object->random_id, 0);
|
||||
|
||||
if(b_parent.ptr.data != b_ob.ptr.data)
|
||||
object->random_id ^= hash_int(hash_string(b_parent.name().c_str()));
|
||||
|
||||
/* dupli texture coordinates */
|
||||
/* dupli texture coordinates and random_id */
|
||||
if(b_dupli_ob) {
|
||||
object->dupli_generated = 0.5f*get_float3(b_dupli_ob.orco()) - make_float3(0.5f, 0.5f, 0.5f);
|
||||
object->dupli_uv = get_float2(b_dupli_ob.uv());
|
||||
object->random_id = b_dupli_ob.random_id();
|
||||
}
|
||||
else {
|
||||
object->dupli_generated = make_float3(0.0f, 0.0f, 0.0f);
|
||||
object->dupli_uv = make_float2(0.0f, 0.0f);
|
||||
object->random_id = hash_int_2d(hash_string(object->name.c_str()), 0);
|
||||
}
|
||||
|
||||
object->tag_update(scene);
|
||||
|
|
|
@ -521,6 +521,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();
|
||||
}
|
||||
|
|
|
@ -902,7 +902,7 @@ bool OpenCLInfo::get_platform_name(cl_platform_id platform_id,
|
|||
string OpenCLInfo::get_platform_name(cl_platform_id platform_id)
|
||||
{
|
||||
string platform_name;
|
||||
if (!get_platform_name(platform_id, &platform_name)) {
|
||||
if(!get_platform_name(platform_id, &platform_name)) {
|
||||
return "";
|
||||
}
|
||||
return platform_name;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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__ */
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -379,7 +379,7 @@ ccl_device bool shadow_blocked_transparent_stepped(
|
|||
float3 *shadow)
|
||||
{
|
||||
bool blocked, is_transparent_isect;
|
||||
if (skip_object == OBJECT_NONE) {
|
||||
if(skip_object == OBJECT_NONE) {
|
||||
blocked = scene_intersect(kg,
|
||||
*ray,
|
||||
PATH_RAY_SHADOW_OPAQUE,
|
||||
|
|
|
@ -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,13 +81,15 @@ set(SRC_OSL
|
|||
node_wireframe.osl
|
||||
node_hair_bsdf.osl
|
||||
node_uv_map.osl
|
||||
node_principled_bsdf.osl
|
||||
node_rgb_to_bw.osl
|
||||
)
|
||||
|
||||
set(SRC_OSL_HEADERS
|
||||
node_texture.h
|
||||
node_color.h
|
||||
node_fresnel.h
|
||||
node_ramp_util.h
|
||||
node_texture.h
|
||||
stdosl.h
|
||||
oslutil.h
|
||||
)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -122,7 +122,7 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
|
|||
|
||||
#ifdef __SHADOW_TRICKS__
|
||||
if((sd->object_flag & SD_OBJECT_SHADOW_CATCHER)) {
|
||||
if (state->flag & PATH_RAY_CAMERA) {
|
||||
if(state->flag & PATH_RAY_CAMERA) {
|
||||
state->flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_SHADOW_CATCHER_ONLY);
|
||||
state->catcher_object = sd->object;
|
||||
if(!kernel_data.background.transparent) {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -423,7 +423,8 @@ void ShaderGraph::copy_nodes(ShaderNodeSet& nodes, ShaderNodeMap& nnodemap)
|
|||
/* Graph simplification */
|
||||
/* ******************** */
|
||||
|
||||
/* Step 1: Remove proxy nodes.
|
||||
/* Remove proxy nodes.
|
||||
*
|
||||
* These only exists temporarily when exporting groups, and we must remove them
|
||||
* early so that node->attributes() and default links do not see them.
|
||||
*/
|
||||
|
@ -493,7 +494,8 @@ void ShaderGraph::remove_proxy_nodes()
|
|||
}
|
||||
}
|
||||
|
||||
/* Step 2: Constant folding.
|
||||
/* Constant folding.
|
||||
*
|
||||
* Try to constant fold some nodes, and pipe result directly to
|
||||
* the input socket of connected nodes.
|
||||
*/
|
||||
|
@ -554,7 +556,7 @@ void ShaderGraph::constant_fold()
|
|||
}
|
||||
}
|
||||
|
||||
/* Step 3: Simplification. */
|
||||
/* Simplification. */
|
||||
void ShaderGraph::simplify_settings(Scene *scene)
|
||||
{
|
||||
foreach(ShaderNode *node, nodes) {
|
||||
|
@ -562,7 +564,7 @@ void ShaderGraph::simplify_settings(Scene *scene)
|
|||
}
|
||||
}
|
||||
|
||||
/* Step 4: Deduplicate nodes with same settings. */
|
||||
/* Deduplicate nodes with same settings. */
|
||||
void ShaderGraph::deduplicate_nodes()
|
||||
{
|
||||
/* NOTES:
|
||||
|
@ -638,6 +640,48 @@ void ShaderGraph::deduplicate_nodes()
|
|||
}
|
||||
}
|
||||
|
||||
/* Check whether volume output has meaningful nodes, otherwise
|
||||
* disconnect the output.
|
||||
*/
|
||||
void ShaderGraph::verify_volume_output()
|
||||
{
|
||||
/* Check whether we can optimize the whole volume graph out. */
|
||||
ShaderInput *volume_in = output()->input("Volume");
|
||||
if(volume_in->link == NULL) {
|
||||
return;
|
||||
}
|
||||
bool has_valid_volume = false;
|
||||
ShaderNodeSet scheduled;
|
||||
queue<ShaderNode*> traverse_queue;
|
||||
/* Schedule volume output. */
|
||||
traverse_queue.push(volume_in->link->parent);
|
||||
scheduled.insert(volume_in->link->parent);
|
||||
/* Traverse down the tree. */
|
||||
while(!traverse_queue.empty()) {
|
||||
ShaderNode *node = traverse_queue.front();
|
||||
traverse_queue.pop();
|
||||
/* Node is fully valid for volume, can't optimize anything out. */
|
||||
if(node->has_volume_support()) {
|
||||
has_valid_volume = true;
|
||||
break;
|
||||
}
|
||||
foreach(ShaderInput *input, node->inputs) {
|
||||
if(input->link == NULL) {
|
||||
continue;
|
||||
}
|
||||
if(scheduled.find(input->link->parent) != scheduled.end()) {
|
||||
continue;
|
||||
}
|
||||
traverse_queue.push(input->link->parent);
|
||||
scheduled.insert(input->link->parent);
|
||||
}
|
||||
}
|
||||
if(!has_valid_volume) {
|
||||
VLOG(1) << "Disconnect meaningless volume output.";
|
||||
disconnect(volume_in->link);
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderGraph::break_cycles(ShaderNode *node, vector<bool>& visited, vector<bool>& on_stack)
|
||||
{
|
||||
visited[node->id] = true;
|
||||
|
@ -666,16 +710,11 @@ void ShaderGraph::clean(Scene *scene)
|
|||
{
|
||||
/* Graph simplification */
|
||||
|
||||
/* 1: Remove proxy nodes was already done. */
|
||||
|
||||
/* 2: Constant folding. */
|
||||
/* NOTE: Remove proxy nodes was already done. */
|
||||
constant_fold();
|
||||
|
||||
/* 3: Simplification. */
|
||||
simplify_settings(scene);
|
||||
|
||||
/* 4: De-duplication. */
|
||||
deduplicate_nodes();
|
||||
verify_volume_output();
|
||||
|
||||
/* we do two things here: find cycles and break them, and remove unused
|
||||
* nodes that don't feed into the output. how cycles are broken is
|
||||
|
@ -998,6 +1037,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;
|
||||
}
|
||||
|
|
|
@ -155,7 +155,7 @@ public:
|
|||
virtual bool has_spatial_varying() { return false; }
|
||||
virtual bool has_object_dependency() { return false; }
|
||||
virtual bool has_integrator_dependency() { return false; }
|
||||
|
||||
virtual bool has_volume_support() { return false; }
|
||||
vector<ShaderInput*> inputs;
|
||||
vector<ShaderOutput*> outputs;
|
||||
|
||||
|
@ -284,6 +284,7 @@ protected:
|
|||
void constant_fold();
|
||||
void simplify_settings(Scene *scene);
|
||||
void deduplicate_nodes();
|
||||
void verify_volume_output();
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
@ -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)
|
||||
|
@ -445,6 +478,7 @@ public:
|
|||
virtual ClosureType get_closure_type() { return CLOSURE_EMISSION_ID; }
|
||||
|
||||
bool has_surface_emission() { return true; }
|
||||
bool has_volume_support() { return true; }
|
||||
|
||||
float3 color;
|
||||
float strength;
|
||||
|
@ -496,6 +530,7 @@ public:
|
|||
return ShaderNode::get_feature() | NODE_FEATURE_VOLUME;
|
||||
}
|
||||
virtual ClosureType get_closure_type() { return closure; }
|
||||
virtual bool has_volume_support() { return true; }
|
||||
|
||||
float3 color;
|
||||
float density;
|
||||
|
|
|
@ -1238,7 +1238,6 @@ class CLIP_MT_view(Menu):
|
|||
|
||||
layout.prop(sc, "show_seconds")
|
||||
layout.prop(sc, "show_locked_time")
|
||||
layout.separator()
|
||||
|
||||
layout.separator()
|
||||
layout.operator("screen.area_dupli")
|
||||
|
|
|
@ -1677,7 +1677,7 @@ class VIEW3D_MT_brush(Menu):
|
|||
layout = self.layout
|
||||
|
||||
settings = UnifiedPaintPanel.paint_settings(context)
|
||||
brush = settings.brush
|
||||
brush = getattr(settings, "brush", None)
|
||||
|
||||
ups = context.tool_settings.unified_paint_settings
|
||||
layout.prop(ups, "use_unified_size", text="Unified Size")
|
||||
|
@ -1686,6 +1686,11 @@ class VIEW3D_MT_brush(Menu):
|
|||
layout.prop(ups, "use_unified_color", text="Unified Color")
|
||||
layout.separator()
|
||||
|
||||
# skip if no active brush
|
||||
if not brush:
|
||||
layout.label(text="No Brushes currently available", icon="INFO")
|
||||
return
|
||||
|
||||
# brush paint modes
|
||||
layout.menu("VIEW3D_MT_brush_paint_modes")
|
||||
|
||||
|
@ -1698,10 +1703,6 @@ class VIEW3D_MT_brush(Menu):
|
|||
elif context.vertex_paint_object or context.weight_paint_object:
|
||||
layout.prop_menu_enum(brush, "vertex_tool")
|
||||
|
||||
# skip if no active brush
|
||||
if not brush:
|
||||
return
|
||||
|
||||
# TODO: still missing a lot of brush options here
|
||||
|
||||
# sculpt options
|
||||
|
|
|
@ -157,6 +157,7 @@ shader_node_categories = [
|
|||
NodeItem("ShaderNodeGeometry"),
|
||||
NodeItem("ShaderNodeExtendedMaterial"),
|
||||
NodeItem("ShaderNodeParticleInfo"),
|
||||
NodeItem("ShaderNodeObjectInfo"),
|
||||
NodeItem("NodeGroupInput", poll=group_input_output_item_poll),
|
||||
]),
|
||||
ShaderOldNodeCategory("SH_OUTPUT", "Output", items=[
|
||||
|
@ -225,6 +226,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),
|
||||
|
|
|
@ -95,7 +95,7 @@ void AbcCurveWriter::do_write()
|
|||
for (; nurbs; nurbs = nurbs->next) {
|
||||
if (nurbs->bp) {
|
||||
curve_basis = Alembic::AbcGeom::kNoBasis;
|
||||
curve_type = Alembic::AbcGeom::kLinear;
|
||||
curve_type = Alembic::AbcGeom::kVariableOrder;
|
||||
|
||||
const int totpoint = nurbs->pntsu * nurbs->pntsv;
|
||||
|
||||
|
@ -160,7 +160,7 @@ void AbcCurveWriter::do_write()
|
|||
}
|
||||
}
|
||||
|
||||
orders.push_back(nurbs->orderu + 1);
|
||||
orders.push_back(nurbs->orderu);
|
||||
vert_counts.push_back(verts.size());
|
||||
}
|
||||
|
||||
|
@ -258,8 +258,8 @@ void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const float time)
|
|||
case Alembic::AbcGeom::kVariableOrder:
|
||||
if (orders && orders->size() > i) {
|
||||
nu->orderu = static_cast<short>((*orders)[i]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Alembic::AbcGeom::kLinear:
|
||||
default:
|
||||
nu->orderu = 2;
|
||||
|
|
|
@ -290,13 +290,7 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled)
|
|||
|
||||
OBox3dProperty archive_bounds_prop = Alembic::AbcGeom::CreateOArchiveBounds(m_writer->archive(), m_trans_sampling_index);
|
||||
|
||||
if (m_settings.flatten_hierarchy) {
|
||||
createTransformWritersFlat();
|
||||
}
|
||||
else {
|
||||
createTransformWritersHierarchy(bmain->eval_ctx);
|
||||
}
|
||||
|
||||
createTransformWritersHierarchy(bmain->eval_ctx);
|
||||
createShapeWriters(bmain->eval_ctx);
|
||||
|
||||
/* Make a list of frames to export. */
|
||||
|
@ -381,20 +375,6 @@ void AbcExporter::createTransformWritersHierarchy(EvaluationContext *eval_ctx)
|
|||
}
|
||||
}
|
||||
|
||||
void AbcExporter::createTransformWritersFlat()
|
||||
{
|
||||
for (Base *base = static_cast<Base *>(m_settings.sl->object_bases.first); base; base = base->next) {
|
||||
Object *ob = base->object;
|
||||
|
||||
if (export_object(&m_settings, base, false) && object_is_shape(ob)) {
|
||||
std::string name = get_id_name(ob);
|
||||
m_xforms[name] = new AbcTransformWriter(
|
||||
ob, m_writer->archive().getTop(), NULL,
|
||||
m_trans_sampling_index, m_settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AbcExporter::exploreTransform(EvaluationContext *eval_ctx, Base *ob_base, Object *parent, Object *dupliObParent)
|
||||
{
|
||||
Object *ob = ob_base->object;
|
||||
|
@ -440,12 +420,18 @@ void AbcExporter::exploreTransform(EvaluationContext *eval_ctx, Base *ob_base, O
|
|||
|
||||
AbcTransformWriter * AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupliObParent)
|
||||
{
|
||||
const std::string name = get_object_dag_path_name(ob, dupliObParent);
|
||||
|
||||
/* An object should not be its own parent, or we'll get infinite loops. */
|
||||
BLI_assert(ob != parent);
|
||||
BLI_assert(ob != dupliObParent);
|
||||
|
||||
std::string name;
|
||||
if (m_settings.flatten_hierarchy) {
|
||||
name = get_id_name(ob);
|
||||
}
|
||||
else {
|
||||
name = get_object_dag_path_name(ob, dupliObParent);
|
||||
}
|
||||
|
||||
/* check if we have already created a transform writer for this object */
|
||||
AbcTransformWriter *my_writer = getXForm(name);
|
||||
if (my_writer != NULL){
|
||||
|
@ -455,13 +441,23 @@ AbcTransformWriter * AbcExporter::createTransformWriter(Object *ob, Object *pare
|
|||
AbcTransformWriter *parent_writer = NULL;
|
||||
Alembic::Abc::OObject alembic_parent;
|
||||
|
||||
if (parent) {
|
||||
if (m_settings.flatten_hierarchy || parent == NULL) {
|
||||
/* Parentless objects still have the "top object" as parent
|
||||
* in Alembic. */
|
||||
alembic_parent = m_writer->archive().getTop();
|
||||
}
|
||||
else {
|
||||
/* Since there are so many different ways to find parents (as evident
|
||||
* in the number of conditions below), we can't really look up the
|
||||
* parent by name. We'll just call createTransformWriter(), which will
|
||||
* return the parent's AbcTransformWriter pointer. */
|
||||
if (parent->parent) {
|
||||
parent_writer = createTransformWriter(parent, parent->parent, dupliObParent);
|
||||
if (parent == dupliObParent) {
|
||||
parent_writer = createTransformWriter(parent, parent->parent, NULL);
|
||||
}
|
||||
else {
|
||||
parent_writer = createTransformWriter(parent, parent->parent, dupliObParent);
|
||||
}
|
||||
}
|
||||
else if (parent == dupliObParent) {
|
||||
if (dupliObParent->parent == NULL) {
|
||||
|
@ -478,14 +474,15 @@ AbcTransformWriter * AbcExporter::createTransformWriter(Object *ob, Object *pare
|
|||
BLI_assert(parent_writer);
|
||||
alembic_parent = parent_writer->alembicXform();
|
||||
}
|
||||
else {
|
||||
/* Parentless objects still have the "top object" as parent
|
||||
* in Alembic. */
|
||||
alembic_parent = m_writer->archive().getTop();
|
||||
}
|
||||
|
||||
my_writer = new AbcTransformWriter(ob, alembic_parent, parent_writer,
|
||||
m_trans_sampling_index, m_settings);
|
||||
|
||||
/* When flattening, the matrix of the dupliobject has to be added. */
|
||||
if (m_settings.flatten_hierarchy && dupliObParent) {
|
||||
my_writer->m_proxy_from = dupliObParent;
|
||||
}
|
||||
|
||||
m_xforms[name] = my_writer;
|
||||
return my_writer;
|
||||
}
|
||||
|
|
|
@ -112,7 +112,6 @@ private:
|
|||
void getFrameSet(double step, std::set<double> &frames);
|
||||
|
||||
void createTransformWritersHierarchy(EvaluationContext *eval_ctx);
|
||||
void createTransformWritersFlat();
|
||||
AbcTransformWriter * createTransformWriter(Object *ob, Object *parent, Object *dupliObParent);
|
||||
void exploreTransform(EvaluationContext *eval_ctx, Base *ob_base, Object *parent, Object *dupliObParent);
|
||||
void exploreObject(EvaluationContext *eval_ctx, Base *ob_base, Object *dupliObParent);
|
||||
|
|
|
@ -62,6 +62,7 @@ AbcTransformWriter::AbcTransformWriter(Object *ob,
|
|||
unsigned int time_sampling,
|
||||
ExportSettings &settings)
|
||||
: AbcObjectWriter(NULL, ob, time_sampling, settings, parent)
|
||||
, m_proxy_from(NULL)
|
||||
{
|
||||
m_is_animated = hasAnimation(m_object);
|
||||
|
||||
|
@ -90,7 +91,8 @@ void AbcTransformWriter::do_write()
|
|||
|
||||
float yup_mat[4][4];
|
||||
create_transform_matrix(m_object, yup_mat,
|
||||
m_inherits_xform ? ABC_MATRIX_LOCAL : ABC_MATRIX_WORLD);
|
||||
m_inherits_xform ? ABC_MATRIX_LOCAL : ABC_MATRIX_WORLD,
|
||||
m_proxy_from);
|
||||
|
||||
/* Only apply rotation to root camera, parenting will propagate it. */
|
||||
if (m_object->type == OB_CAMERA && (!m_inherits_xform || !has_parent_camera(m_object))) {
|
||||
|
|
|
@ -40,6 +40,9 @@ class AbcTransformWriter : public AbcObjectWriter {
|
|||
bool m_visible;
|
||||
bool m_inherits_xform;
|
||||
|
||||
public:
|
||||
Object *m_proxy_from;
|
||||
|
||||
public:
|
||||
AbcTransformWriter(Object *ob,
|
||||
const Alembic::AbcGeom::OObject &abc_parent,
|
||||
|
|
|
@ -245,7 +245,8 @@ void convert_matrix(const Imath::M44d &xform, Object *ob, float r_mat[4][4])
|
|||
|
||||
/* Recompute transform matrix of object in new coordinate system
|
||||
* (from Z-Up to Y-Up). */
|
||||
void create_transform_matrix(Object *obj, float r_yup_mat[4][4], AbcMatrixMode mode)
|
||||
void create_transform_matrix(Object *obj, float r_yup_mat[4][4], AbcMatrixMode mode,
|
||||
Object *proxy_from)
|
||||
{
|
||||
float zup_mat[4][4];
|
||||
|
||||
|
@ -255,11 +256,16 @@ void create_transform_matrix(Object *obj, float r_yup_mat[4][4], AbcMatrixMode m
|
|||
* constraints and modifiers as well as the obj->parentinv matrix. */
|
||||
invert_m4_m4(obj->parent->imat, obj->parent->obmat);
|
||||
mul_m4_m4m4(zup_mat, obj->parent->imat, obj->obmat);
|
||||
copy_m44_axis_swap(r_yup_mat, zup_mat, ABC_YUP_FROM_ZUP);
|
||||
}
|
||||
else {
|
||||
copy_m44_axis_swap(r_yup_mat, obj->obmat, ABC_YUP_FROM_ZUP);
|
||||
copy_m4_m4(zup_mat, obj->obmat);
|
||||
}
|
||||
|
||||
if (proxy_from) {
|
||||
mul_m4_m4m4(zup_mat, proxy_from->obmat, zup_mat);
|
||||
}
|
||||
|
||||
copy_m44_axis_swap(r_yup_mat, zup_mat, ABC_YUP_FROM_ZUP);
|
||||
}
|
||||
|
||||
bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name)
|
||||
|
|
|
@ -62,7 +62,8 @@ typedef enum {
|
|||
ABC_MATRIX_WORLD = 1,
|
||||
ABC_MATRIX_LOCAL = 2,
|
||||
} AbcMatrixMode;
|
||||
void create_transform_matrix(Object *obj, float r_transform_mat[4][4], AbcMatrixMode mode);
|
||||
void create_transform_matrix(Object *obj, float r_transform_mat[4][4],
|
||||
AbcMatrixMode mode, Object *proxy_from);
|
||||
|
||||
void split(const std::string &s, const char delim, std::vector<std::string> &tokens);
|
||||
|
||||
|
|
|
@ -176,6 +176,7 @@ void BKE_pose_eval_bone(struct EvaluationContext *eval_ctx,
|
|||
struct bPoseChannel *pchan);
|
||||
|
||||
void BKE_pose_constraints_evaluate(struct EvaluationContext *eval_ctx,
|
||||
struct Scene *scene,
|
||||
struct Object *ob,
|
||||
struct bPoseChannel *pchan);
|
||||
|
||||
|
|
|
@ -792,6 +792,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
|
||||
|
|
|
@ -621,10 +621,10 @@ void BKE_pose_eval_bone(struct EvaluationContext *UNUSED(eval_ctx),
|
|||
}
|
||||
|
||||
void BKE_pose_constraints_evaluate(struct EvaluationContext *UNUSED(eval_ctx),
|
||||
Scene *scene,
|
||||
Object *ob,
|
||||
bPoseChannel *pchan)
|
||||
{
|
||||
Scene *scene = G.main->scene.first;
|
||||
DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, pchan->name);
|
||||
bArmature *arm = (bArmature *)ob->data;
|
||||
if (arm->flag & ARM_RESTPOS) {
|
||||
|
|
|
@ -2216,8 +2216,10 @@ void BKE_imbuf_write_prepare(ImBuf *ibuf, const ImageFormatData *imf)
|
|||
ibuf->foptions.flag |= OPENEXR_HALF;
|
||||
ibuf->foptions.flag |= (imf->exr_codec & OPENEXR_COMPRESS);
|
||||
|
||||
if (!(imf->flag & R_IMF_FLAG_ZBUF))
|
||||
ibuf->zbuf_float = NULL; /* signal for exr saving */
|
||||
if (!(imf->flag & R_IMF_FLAG_ZBUF)) {
|
||||
/* Signal for exr saving. */
|
||||
IMB_freezbuffloatImBuf(ibuf);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
#include "DEG_depsgraph.h"
|
||||
|
||||
#include "BLI_strict_flags.h"
|
||||
#include "BLI_hash.h"
|
||||
|
||||
/* Dupli-Geometry */
|
||||
|
||||
|
@ -180,6 +181,22 @@ static DupliObject *make_dupli(const DupliContext *ctx,
|
|||
if (ob->type == OB_MBALL)
|
||||
dob->no_draw = true;
|
||||
|
||||
/* random number */
|
||||
/* the logic here is designed to match Cycles */
|
||||
dob->random_id = BLI_hash_string(dob->ob->id.name + 2);
|
||||
|
||||
if (dob->persistent_id[0] != INT_MAX) {
|
||||
for(i = 0; i < MAX_DUPLI_RECUR*2; i++)
|
||||
dob->random_id = BLI_hash_int_2d(dob->random_id, (unsigned int)dob->persistent_id[i]);
|
||||
}
|
||||
else {
|
||||
dob->random_id = BLI_hash_int_2d(dob->random_id, 0);
|
||||
}
|
||||
|
||||
if (ctx->object != ob) {
|
||||
dob->random_id ^= BLI_hash_int(BLI_hash_string(ctx->object->id.name + 2));
|
||||
}
|
||||
|
||||
return dob;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* ***** 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.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef __BLI_HASH_H__
|
||||
#define __BLI_HASH_H__
|
||||
|
||||
/** \file BLI_hash.h
|
||||
* \ingroup bli
|
||||
*/
|
||||
|
||||
BLI_INLINE unsigned int BLI_hash_int_2d(unsigned int kx, unsigned int ky)
|
||||
{
|
||||
#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
|
||||
|
||||
unsigned int a, b, c;
|
||||
|
||||
a = b = c = 0xdeadbeef + (2 << 2) + 13;
|
||||
a += kx;
|
||||
b += ky;
|
||||
|
||||
c ^= b; c -= rot(b,14);
|
||||
a ^= c; a -= rot(c,11);
|
||||
b ^= a; b -= rot(a,25);
|
||||
c ^= b; c -= rot(b,16);
|
||||
a ^= c; a -= rot(c,4);
|
||||
b ^= a; b -= rot(a,14);
|
||||
c ^= b; c -= rot(b,24);
|
||||
|
||||
return c;
|
||||
|
||||
#undef rot
|
||||
}
|
||||
|
||||
BLI_INLINE unsigned int BLI_hash_string(const char *str)
|
||||
{
|
||||
unsigned int i = 0, c;
|
||||
|
||||
while((c = *str++))
|
||||
i = i * 37 + c;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
BLI_INLINE unsigned int BLI_hash_int(unsigned int k)
|
||||
{
|
||||
return BLI_hash_int_2d(k, 0);
|
||||
}
|
||||
|
||||
#endif // __BLI_HASH_H__
|
|
@ -44,7 +44,7 @@ void BLI_setenv_if_new(const char *env, const char *val) ATTR_NONNULL(1);
|
|||
|
||||
void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file);
|
||||
void BLI_make_exist(char *dir);
|
||||
void BLI_make_existing_file(const char *name);
|
||||
bool BLI_make_existing_file(const char *name);
|
||||
void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t dirlen, const size_t filelen);
|
||||
void BLI_split_dir_part(const char *string, char *dir, const size_t dirlen);
|
||||
void BLI_split_file_part(const char *string, char *file, const size_t filelen);
|
||||
|
|
|
@ -152,6 +152,7 @@ set(SRC
|
|||
BLI_ghash.h
|
||||
BLI_graph.h
|
||||
BLI_gsqueue.h
|
||||
BLI_hash.h
|
||||
BLI_hash_md5.h
|
||||
BLI_hash_mm2a.h
|
||||
BLI_heap.h
|
||||
|
|
|
@ -1234,14 +1234,16 @@ void BLI_make_exist(char *dir)
|
|||
|
||||
/**
|
||||
* Ensures that the parent directory of *name exists.
|
||||
*
|
||||
* \return true on success (i.e. given path now exists on FS), false otherwise.
|
||||
*/
|
||||
void BLI_make_existing_file(const char *name)
|
||||
bool BLI_make_existing_file(const char *name)
|
||||
{
|
||||
char di[FILE_MAX];
|
||||
BLI_split_dir_part(name, di, sizeof(di));
|
||||
|
||||
/* make if the dir doesn't exist */
|
||||
BLI_dir_create_recursive(di);
|
||||
return BLI_dir_create_recursive(di);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -130,7 +130,7 @@ struct DepsgraphNodeBuilder {
|
|||
void build_object(Scene *scene, Object *ob);
|
||||
void build_object_transform(Scene *scene, Object *ob);
|
||||
void build_object_constraints(Scene *scene, Object *ob);
|
||||
void build_pose_constraints(Object *ob, bPoseChannel *pchan);
|
||||
void build_pose_constraints(Scene *scene, Object *ob, bPoseChannel *pchan);
|
||||
void build_rigidbody(Scene *scene);
|
||||
void build_particles(Scene *scene, Object *ob);
|
||||
void build_cloth(Scene *scene, Object *object);
|
||||
|
|
|
@ -64,11 +64,12 @@ extern "C" {
|
|||
|
||||
namespace DEG {
|
||||
|
||||
void DepsgraphNodeBuilder::build_pose_constraints(Object *ob, bPoseChannel *pchan)
|
||||
void DepsgraphNodeBuilder::build_pose_constraints(Scene *scene, Object *ob, bPoseChannel *pchan)
|
||||
{
|
||||
/* create node for constraint stack */
|
||||
add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
|
||||
DEPSOP_TYPE_EXEC, function_bind(BKE_pose_constraints_evaluate, _1, ob, pchan),
|
||||
DEPSOP_TYPE_EXEC,
|
||||
function_bind(BKE_pose_constraints_evaluate, _1, scene, ob, pchan),
|
||||
DEG_OPCODE_BONE_CONSTRAINTS);
|
||||
}
|
||||
|
||||
|
@ -201,7 +202,7 @@ void DepsgraphNodeBuilder::build_rig(Scene *scene, Object *ob)
|
|||
|
||||
/* constraints */
|
||||
if (pchan->constraints.first != NULL) {
|
||||
build_pose_constraints(ob, pchan);
|
||||
build_pose_constraints(scene, ob, pchan);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -6049,6 +6049,9 @@ int join_curve_exec(bContext *C, wmOperator *op)
|
|||
cu = ob->data;
|
||||
BLI_movelisttolist(&cu->nurb, &tempbase);
|
||||
|
||||
/* Account for mixed 2D/3D curves when joining */
|
||||
BKE_curve_curve_dimension_update(cu);
|
||||
|
||||
DAG_relations_tag_update(bmain); // because we removed object(s), call before editmode!
|
||||
|
||||
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
|
||||
|
|
|
@ -486,7 +486,8 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure,
|
|||
bGPdata *gpd = p->gpd;
|
||||
bGPDbrush *brush = p->brush;
|
||||
tGPspoint *pt;
|
||||
|
||||
ToolSettings *ts = p->scene->toolsettings;
|
||||
|
||||
/* check painting mode */
|
||||
if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
|
||||
/* straight lines only - i.e. only store start and end point in buffer */
|
||||
|
@ -638,7 +639,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure,
|
|||
View3D *v3d = p->sa->spacedata.first;
|
||||
|
||||
view3d_region_operator_needs_opengl(p->win, p->ar);
|
||||
ED_view3d_autodist_init(p->scene, p->ar, v3d, (p->gpd->flag & GP_DATA_DEPTH_STROKE) ? 1 : 0);
|
||||
ED_view3d_autodist_init(p->scene, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
|
||||
}
|
||||
|
||||
/* convert screen-coordinates to appropriate coordinates (and store them) */
|
||||
|
@ -758,7 +759,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
|
|||
|
||||
int i, totelem;
|
||||
/* since strokes are so fine, when using their depth we need a margin otherwise they might get missed */
|
||||
int depth_margin = (p->gpd->flag & GP_DATA_DEPTH_STROKE) ? 4 : 0;
|
||||
int depth_margin = (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 4 : 0;
|
||||
|
||||
/* get total number of points to allocate space for
|
||||
* - drawing straight-lines only requires the endpoints
|
||||
|
@ -912,7 +913,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
|
|||
depth_arr[i] = 0.9999f;
|
||||
}
|
||||
else {
|
||||
if (p->gpd->flag & GP_DATA_DEPTH_STROKE_ENDPOINTS) {
|
||||
if (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE_ENDPOINTS) {
|
||||
/* remove all info between the valid endpoints */
|
||||
int first_valid = 0;
|
||||
int last_valid = 0;
|
||||
|
@ -1797,6 +1798,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode)
|
|||
/* finish off a stroke (clears buffer, but doesn't finish the paint operation) */
|
||||
static void gp_paint_strokeend(tGPsdata *p)
|
||||
{
|
||||
ToolSettings *ts = p->scene->toolsettings;
|
||||
/* for surface sketching, need to set the right OpenGL context stuff so that
|
||||
* the conversions will project the values correctly...
|
||||
*/
|
||||
|
@ -1805,7 +1807,7 @@ static void gp_paint_strokeend(tGPsdata *p)
|
|||
|
||||
/* need to restore the original projection settings before packing up */
|
||||
view3d_region_operator_needs_opengl(p->win, p->ar);
|
||||
ED_view3d_autodist_init(p->scene, p->ar, v3d, (p->gpd->flag & GP_DATA_DEPTH_STROKE) ? 1 : 0);
|
||||
ED_view3d_autodist_init(p->scene, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
|
||||
}
|
||||
|
||||
/* check if doing eraser or not */
|
||||
|
|
|
@ -631,71 +631,63 @@ static int fluid_validate_scene(ReportList *reports, Scene *scene, Object *fsDom
|
|||
#define FLUID_SUFFIX_CONFIG_TMP (FLUID_SUFFIX_CONFIG ".tmp")
|
||||
#define FLUID_SUFFIX_SURFACE "fluidsurface"
|
||||
|
||||
static int fluid_init_filepaths(Object *fsDomain, char *targetDir, char *targetFile, char *debugStrBuffer)
|
||||
static bool fluid_init_filepaths(
|
||||
ReportList *reports, FluidsimSettings *domainSettings, Object *fsDomain,
|
||||
char *targetDir, char *targetFile)
|
||||
{
|
||||
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(fsDomain, eModifierType_Fluidsim);
|
||||
FluidsimSettings *domainSettings= fluidmd->fss;
|
||||
FILE *fileCfg;
|
||||
int dirExist = 0;
|
||||
char newSurfdataPath[FILE_MAX]; /* modified output settings */
|
||||
const char *suffixConfigTmp = FLUID_SUFFIX_CONFIG_TMP;
|
||||
int outStringsChanged = 0;
|
||||
|
||||
/* prepare names... */
|
||||
const char *relbase= modifier_path_relbase(fsDomain);
|
||||
const char *relbase = modifier_path_relbase(fsDomain);
|
||||
|
||||
/* We do not accept empty paths, they can end in random places silently, see T51176. */
|
||||
if (domainSettings->surfdataPath[0] == '\0') {
|
||||
modifier_path_init(domainSettings->surfdataPath, sizeof(domainSettings->surfdataPath),
|
||||
OB_FLUIDSIM_SURF_DIR_DEFAULT);
|
||||
BKE_reportf(reports, RPT_WARNING, "Fluidsim: empty cache path, reset to default '%s'",
|
||||
domainSettings->surfdataPath);
|
||||
}
|
||||
|
||||
BLI_strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR);
|
||||
BLI_strncpy(newSurfdataPath, domainSettings->surfdataPath, FILE_MAXDIR); /* if 0'd out below, this value is never used! */
|
||||
BLI_path_abs(targetDir, relbase); /* fixed #frame-no */
|
||||
BLI_path_abs(targetDir, relbase);
|
||||
|
||||
/* .tmp: don't overwrite/delete original file */
|
||||
BLI_join_dirfile(targetFile, FILE_MAX, targetDir, suffixConfigTmp);
|
||||
|
||||
// make sure all directories exist
|
||||
// as the bobjs use the same dir, this only needs to be checked
|
||||
// for the cfg output
|
||||
BLI_make_existing_file(targetFile);
|
||||
|
||||
// check selected directory
|
||||
// simply try to open cfg file for writing to test validity of settings
|
||||
fileCfg = BLI_fopen(targetFile, "w");
|
||||
if (fileCfg) {
|
||||
dirExist = 1; fclose(fileCfg);
|
||||
// remove cfg dummy from directory test
|
||||
BLI_delete(targetFile, false, false);
|
||||
/* Ensure whole path exists and is wirtable. */
|
||||
const bool dir_exists = BLI_dir_create_recursive(targetDir);
|
||||
const bool is_writable = BLI_file_is_writable(targetFile);
|
||||
|
||||
/* We change path to some presumably valid default value, but do not allow bake process to continue,
|
||||
* this gives user chance to set manually another path. */
|
||||
if (!dir_exists || !is_writable) {
|
||||
modifier_path_init(domainSettings->surfdataPath, sizeof(domainSettings->surfdataPath),
|
||||
OB_FLUIDSIM_SURF_DIR_DEFAULT);
|
||||
|
||||
if (!dir_exists) {
|
||||
BKE_reportf(reports, RPT_ERROR, "Fluidsim: could not create cache directory '%s', reset to default '%s'",
|
||||
targetDir, domainSettings->surfdataPath);
|
||||
}
|
||||
else {
|
||||
BKE_reportf(reports, RPT_ERROR, "Fluidsim: cache directory '%s' is not writable, reset to default '%s'",
|
||||
targetDir, domainSettings->surfdataPath);
|
||||
}
|
||||
|
||||
BLI_strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR);
|
||||
BLI_path_abs(targetDir, relbase);
|
||||
|
||||
/* .tmp: don't overwrite/delete original file */
|
||||
BLI_join_dirfile(targetFile, FILE_MAX, targetDir, suffixConfigTmp);
|
||||
|
||||
/* Ensure whole path exists and is wirtable. */
|
||||
if (!BLI_dir_create_recursive(targetDir) || !BLI_file_is_writable(targetFile)) {
|
||||
BKE_reportf(reports, RPT_ERROR, "Fluidsim: could not use default cache directory '%s', "
|
||||
"please define a valid cache path manually", targetDir);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (targetDir[0] == '\0' || (!dirExist)) {
|
||||
char blendFile[FILE_MAX];
|
||||
|
||||
// invalid dir, reset to current/previous
|
||||
BLI_split_file_part(G.main->name, blendFile, sizeof(blendFile));
|
||||
BLI_replace_extension(blendFile, FILE_MAX, ""); /* strip .blend */
|
||||
BLI_snprintf(newSurfdataPath, FILE_MAX, "//fluidsimdata/%s_%s_", blendFile, fsDomain->id.name);
|
||||
|
||||
BLI_snprintf(debugStrBuffer, 256, "fluidsimBake::error - warning resetting output dir to '%s'\n", newSurfdataPath);
|
||||
elbeemDebugOut(debugStrBuffer);
|
||||
outStringsChanged=1;
|
||||
}
|
||||
|
||||
/* check if modified output dir is ok */
|
||||
#if 0
|
||||
if (outStringsChanged) {
|
||||
char dispmsg[FILE_MAX+256];
|
||||
int selection=0;
|
||||
BLI_strncpy(dispmsg, "Output settings set to: '", sizeof(dispmsg));
|
||||
strcat(dispmsg, newSurfdataPath);
|
||||
strcat(dispmsg, "'%t|Continue with changed settings %x1|Discard and abort %x0");
|
||||
|
||||
/* ask user if thats what he/she wants... */
|
||||
selection = pupmenu(dispmsg);
|
||||
if (selection < 1) return 0; /* 0 from menu, or -1 aborted */
|
||||
BLI_strncpy(targetDir, newSurfdataPath, sizeof(targetDir));
|
||||
strncpy(domainSettings->surfdataPath, newSurfdataPath, FILE_MAXDIR);
|
||||
BLI_path_abs(targetDir, G.main->name); /* fixed #frame-no */
|
||||
}
|
||||
#endif
|
||||
return outStringsChanged;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ******************************************************************************** */
|
||||
|
@ -857,7 +849,6 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor
|
|||
|
||||
char targetDir[FILE_MAX]; // store & modify output settings
|
||||
char targetFile[FILE_MAX]; // temp. store filename from targetDir for access
|
||||
int outStringsChanged = 0; // modified? copy back before baking
|
||||
|
||||
float domainMat[4][4];
|
||||
float invDomMat[4][4];
|
||||
|
@ -943,7 +934,11 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor
|
|||
|
||||
|
||||
/* ******** prepare output file paths ******** */
|
||||
outStringsChanged = fluid_init_filepaths(fsDomain, targetDir, targetFile, debugStrBuffer);
|
||||
if (!fluid_init_filepaths(reports, domainSettings, fsDomain, targetDir, targetFile)) {
|
||||
fluidbake_free_data(channels, fobjects, fsset, fb);
|
||||
return false;
|
||||
}
|
||||
|
||||
channels->length = scene->r.efra; // DG TODO: why using endframe and not "noFrames" here? .. because "noFrames" is buggy too? (not using sfra)
|
||||
channels->aniFrameTime = (double)((double)domainSettings->animEnd - (double)domainSettings->animStart) / (double)noFrames;
|
||||
|
||||
|
@ -968,11 +963,6 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor
|
|||
/* ******** start writing / exporting ******** */
|
||||
// use .tmp, don't overwrite/delete original file
|
||||
BLI_join_dirfile(targetFile, sizeof(targetFile), targetDir, suffixConfigTmp);
|
||||
|
||||
// make sure these directories exist as well
|
||||
if (outStringsChanged) {
|
||||
BLI_make_existing_file(targetFile);
|
||||
}
|
||||
|
||||
/* ******** export domain to elbeem ******** */
|
||||
elbeemResetSettings(fsset);
|
||||
|
|
|
@ -1184,6 +1184,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:
|
||||
|
|
|
@ -97,6 +97,7 @@ typedef enum GPUBuiltin {
|
|||
GPU_PARTICLE_ANG_VELOCITY = (1 << 12),
|
||||
GPU_LOC_TO_VIEW_MATRIX = (1 << 13),
|
||||
GPU_INVERSE_LOC_TO_VIEW_MATRIX = (1 << 14),
|
||||
GPU_OBJECT_INFO = (1 << 15)
|
||||
} GPUBuiltin;
|
||||
|
||||
typedef enum GPUOpenGLBuiltin {
|
||||
|
@ -212,6 +213,7 @@ bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNod
|
|||
|
||||
void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link);
|
||||
void GPU_material_enable_alpha(GPUMaterial *material);
|
||||
GPUBuiltin GPU_get_material_builtins(GPUMaterial *material);
|
||||
GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4]);
|
||||
|
||||
/* High level functions to create and use GPU materials */
|
||||
|
@ -228,7 +230,7 @@ void GPU_material_bind(
|
|||
float viewmat[4][4], float viewinv[4][4], float cameraborder[4], bool scenelock);
|
||||
void GPU_material_bind_uniforms(
|
||||
GPUMaterial *material, float obmat[4][4], float viewmat[4][4], float obcol[4],
|
||||
float autobumpscale, GPUParticleInfo *pi);
|
||||
float autobumpscale, GPUParticleInfo *pi, float object_info[3]);
|
||||
void GPU_material_unbind(GPUMaterial *material);
|
||||
bool GPU_material_bound(GPUMaterial *material);
|
||||
struct Scene *GPU_material_scene(GPUMaterial *material);
|
||||
|
@ -325,6 +327,7 @@ struct GPUParticleInfo
|
|||
float location[3];
|
||||
float velocity[3];
|
||||
float angular_velocity[3];
|
||||
int random_id;
|
||||
};
|
||||
|
||||
#ifdef WITH_OPENSUBDIV
|
||||
|
|
|
@ -410,6 +410,8 @@ const char *GPU_builtin_name(GPUBuiltin builtin)
|
|||
return "unfparticlevel";
|
||||
else if (builtin == GPU_PARTICLE_ANG_VELOCITY)
|
||||
return "unfparticleangvel";
|
||||
else if (builtin == GPU_OBJECT_INFO)
|
||||
return "unfobjectinfo";
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
|
|
@ -826,7 +826,9 @@ bool GPU_fx_do_composite_pass(
|
|||
ssao_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_SSAO, is_persp);
|
||||
if (ssao_shader) {
|
||||
const GPUSSAOSettings *fx_ssao = fx->settings.ssao;
|
||||
float ssao_params[4] = {fx_ssao->distance_max, fx_ssao->factor, fx_ssao->attenuation, 0.0f};
|
||||
/* adjust attenuation to be scale invariant */
|
||||
float attenuation = fx_ssao->attenuation / (fx_ssao->distance_max * fx_ssao->distance_max);
|
||||
float ssao_params[4] = {fx_ssao->distance_max, fx_ssao->factor, attenuation, 0.0f};
|
||||
float sample_params[3];
|
||||
|
||||
sample_params[0] = fx->ssao_sample_count_cache;
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "BLI_math.h"
|
||||
#include "BLI_threads.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_hash.h"
|
||||
|
||||
#include "DNA_lamp_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
|
@ -1880,6 +1881,21 @@ static int gpu_get_particle_info(GPUParticleInfo *pi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void GPU_get_object_info(float oi[3], Material *mat)
|
||||
{
|
||||
Object *ob = GMS.gob;
|
||||
oi[0] = ob->index;
|
||||
oi[1] = mat->index;
|
||||
unsigned int random;
|
||||
if (GMS.dob) {
|
||||
random = GMS.dob->random_id;
|
||||
}
|
||||
else {
|
||||
random = BLI_hash_int_2d(BLI_hash_string(GMS.gob->id.name + 2), 0);
|
||||
}
|
||||
oi[2] = random * (1.0f/(float)0xFFFFFFFF);
|
||||
}
|
||||
|
||||
int GPU_object_material_bind(int nr, void *attribs)
|
||||
{
|
||||
GPUVertexAttribs *gattribs = attribs;
|
||||
|
@ -1939,21 +1955,27 @@ int GPU_object_material_bind(int nr, void *attribs)
|
|||
/* bind glsl material and get attributes */
|
||||
Material *mat = GMS.gmatbuf[nr];
|
||||
GPUParticleInfo partile_info;
|
||||
float object_info[3] = {0};
|
||||
|
||||
float auto_bump_scale;
|
||||
|
||||
GPUMaterial *gpumat = GPU_material_from_blender(GMS.gscene, mat, GMS.is_opensubdiv);
|
||||
GPU_material_vertex_attributes(gpumat, gattribs);
|
||||
|
||||
if (GMS.dob)
|
||||
if (GMS.dob) {
|
||||
gpu_get_particle_info(&partile_info);
|
||||
}
|
||||
|
||||
if ((GPU_get_material_builtins(gpumat) & GPU_OBJECT_INFO) != 0) {
|
||||
GPU_get_object_info(object_info, mat);
|
||||
}
|
||||
|
||||
GPU_material_bind(
|
||||
gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT),
|
||||
GMS.gviewmat, GMS.gviewinv, GMS.gviewcamtexcofac, GMS.gscenelock);
|
||||
|
||||
auto_bump_scale = GMS.gob->derivedFinal != NULL ? GMS.gob->derivedFinal->auto_bump_scale : 1.0f;
|
||||
GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gob->col, auto_bump_scale, &partile_info);
|
||||
GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gob->col, auto_bump_scale, &partile_info, object_info);
|
||||
GMS.gboundmat = mat;
|
||||
|
||||
/* for glsl use alpha blend mode, unless it's set to solid and
|
||||
|
|
|
@ -124,6 +124,8 @@ struct GPUMaterial {
|
|||
int partvel;
|
||||
int partangvel;
|
||||
|
||||
int objectinfoloc;
|
||||
|
||||
ListBase lamps;
|
||||
bool bound;
|
||||
|
||||
|
@ -226,6 +228,8 @@ static int gpu_material_construct_end(GPUMaterial *material, const char *passnam
|
|||
material->partvel = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_VELOCITY));
|
||||
if (material->builtins & GPU_PARTICLE_ANG_VELOCITY)
|
||||
material->partangvel = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_ANG_VELOCITY));
|
||||
if (material->builtins & GPU_OBJECT_INFO)
|
||||
material->objectinfoloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_OBJECT_INFO));
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
|
@ -346,9 +350,14 @@ void GPU_material_bind(
|
|||
}
|
||||
}
|
||||
|
||||
GPUBuiltin GPU_get_material_builtins(GPUMaterial *material)
|
||||
{
|
||||
return material->builtins;
|
||||
}
|
||||
|
||||
void GPU_material_bind_uniforms(
|
||||
GPUMaterial *material, float obmat[4][4], float viewmat[4][4], float obcol[4],
|
||||
float autobumpscale, GPUParticleInfo *pi)
|
||||
float autobumpscale, GPUParticleInfo *pi, float object_info[3])
|
||||
{
|
||||
if (material->pass) {
|
||||
GPUShader *shader = GPU_pass_shader(material->pass);
|
||||
|
@ -397,6 +406,9 @@ void GPU_material_bind_uniforms(
|
|||
if (material->builtins & GPU_PARTICLE_ANG_VELOCITY) {
|
||||
GPU_shader_uniform_vector(shader, material->partangvel, 3, 1, pi->angular_velocity);
|
||||
}
|
||||
if (material->builtins & GPU_OBJECT_INFO) {
|
||||
GPU_shader_uniform_vector(shader, material->objectinfoloc, 3, 1, object_info);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,10 +35,10 @@
|
|||
|
||||
#include "GPU_compositing.h"
|
||||
#include "GPU_extensions.h"
|
||||
#include "GPU_shader.h"
|
||||
#include "GPU_uniformbuffer.h"
|
||||
#include "GPU_texture.h"
|
||||
#include "GPU_matrix.h"
|
||||
#include "GPU_shader.h"
|
||||
#include "GPU_texture.h"
|
||||
#include "GPU_uniformbuffer.h"
|
||||
|
||||
#include "gpu_shader_private.h"
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ float calculate_ssao_factor(float depth)
|
|||
float f = dot(dir, normal);
|
||||
|
||||
/* use minor bias here to avoid self shadowing */
|
||||
if (f > 0.05 * len + 0.0001)
|
||||
if (f > 0.05 * len)
|
||||
factor += f * 1.0 / (len * (1.0 + len * len * ssao_params.z));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2393,11 +2393,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;
|
||||
|
||||
|
@ -2414,6 +2422,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);
|
||||
|
@ -2507,6 +2522,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
|
||||
|
@ -2568,6 +2634,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);
|
||||
|
@ -3578,12 +3764,12 @@ void node_light_falloff(float strength, float tsmooth, out float quadratic, out
|
|||
constant = strength;
|
||||
}
|
||||
|
||||
void node_object_info(out vec3 location, out float object_index, out float material_index, out float random)
|
||||
void node_object_info(mat4 obmat, vec3 info, out vec3 location, out float object_index, out float material_index, out float random)
|
||||
{
|
||||
location = vec3(0.0);
|
||||
object_index = 0.0;
|
||||
material_index = 0.0;
|
||||
random = 0.0;
|
||||
location = obmat[3].xyz;
|
||||
object_index = info.x;
|
||||
material_index = info.y;
|
||||
random = info.z;
|
||||
}
|
||||
|
||||
void node_normal_map(vec4 tangent, vec3 normal, vec3 texnormal, out vec3 outnormal)
|
||||
|
|
|
@ -179,6 +179,7 @@ typedef struct FluidsimSettings {
|
|||
#define OB_FLUIDSIM_ACTIVE (1 << 1)
|
||||
#define OB_FLUIDSIM_OVERRIDE_TIME (1 << 2)
|
||||
|
||||
#define OB_FLUIDSIM_SURF_DIR_DEFAULT "cache_fluid"
|
||||
#define OB_FLUIDSIM_SURF_PREVIEW_OBJ_FNAME "fluidsurface_preview_####.bobj.gz"
|
||||
#define OB_FLUIDSIM_SURF_FINAL_OBJ_FNAME "fluidsurface_final_####.bobj.gz"
|
||||
#define OB_FLUIDSIM_SURF_FINAL_VEL_FNAME "fluidsurface_final_####.bvel.gz"
|
||||
|
|
|
@ -342,6 +342,8 @@ typedef struct DupliObject {
|
|||
|
||||
/* particle this dupli was generated from */
|
||||
struct ParticleSystem *particle_system;
|
||||
unsigned int random_id;
|
||||
unsigned int pad;
|
||||
} DupliObject;
|
||||
|
||||
/* **************** OBJECT ********************* */
|
||||
|
|
|
@ -342,7 +342,7 @@ static void rna_ID_user_clear(ID *id)
|
|||
|
||||
static void rna_ID_user_remap(ID *id, Main *bmain, ID *new_id)
|
||||
{
|
||||
if (GS(id->name) == GS(new_id->name)) {
|
||||
if ((GS(id->name) == GS(new_id->name)) && (id != new_id)) {
|
||||
/* For now, do not allow remapping data in linked data from here... */
|
||||
BKE_libblock_remap(bmain, id, new_id, ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_NEVER_NULL_USAGE);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -2889,6 +2889,10 @@ static void rna_def_dupli_object(BlenderRNA *brna)
|
|||
RNA_def_property_enum_items(prop, dupli_items);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Dupli Type", "Duplicator type that generated this dupli object");
|
||||
|
||||
prop = RNA_def_property(srna, "random_id", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Dupli random id", "Random id for this dupli object");
|
||||
}
|
||||
|
||||
static void rna_def_object_base_legacy(BlenderRNA *brna)
|
||||
|
|
|
@ -379,49 +379,55 @@ static void rna_Object_ray_cast(
|
|||
float origin[3], float direction[3], float distance,
|
||||
int *r_success, float r_location[3], float r_normal[3], int *r_index)
|
||||
{
|
||||
BVHTreeFromMesh treeData = {NULL};
|
||||
|
||||
bool success = false;
|
||||
|
||||
if (ob->derivedFinal == NULL) {
|
||||
BKE_reportf(reports, RPT_ERROR, "Object '%s' has no mesh data to be used for ray casting", ob->id.name + 2);
|
||||
return;
|
||||
}
|
||||
|
||||
/* no need to managing allocation or freeing of the BVH data. this is generated and freed as needed */
|
||||
bvhtree_from_mesh_looptri(&treeData, ob->derivedFinal, 0.0f, 4, 6);
|
||||
/* Test BoundBox first (efficiency) */
|
||||
BoundBox *bb = BKE_object_boundbox_get(ob);
|
||||
float distmin;
|
||||
if (!bb || (isect_ray_aabb_v3_simple(origin, direction, bb->vec[0], bb->vec[6], &distmin, NULL) && distmin <= distance)) {
|
||||
|
||||
/* may fail if the mesh has no faces, in that case the ray-cast misses */
|
||||
if (treeData.tree != NULL) {
|
||||
BVHTreeRayHit hit;
|
||||
BVHTreeFromMesh treeData = {NULL};
|
||||
|
||||
hit.index = -1;
|
||||
hit.dist = distance;
|
||||
|
||||
normalize_v3(direction);
|
||||
/* no need to managing allocation or freeing of the BVH data. this is generated and freed as needed */
|
||||
bvhtree_from_mesh_looptri(&treeData, ob->derivedFinal, 0.0f, 4, 6);
|
||||
|
||||
/* may fail if the mesh has no faces, in that case the ray-cast misses */
|
||||
if (treeData.tree != NULL) {
|
||||
BVHTreeRayHit hit;
|
||||
|
||||
hit.index = -1;
|
||||
hit.dist = distance;
|
||||
|
||||
normalize_v3(direction);
|
||||
|
||||
|
||||
if (BLI_bvhtree_ray_cast(treeData.tree, origin, direction, 0.0f, &hit,
|
||||
treeData.raycast_callback, &treeData) != -1)
|
||||
{
|
||||
if (hit.dist <= distance) {
|
||||
*r_success = true;
|
||||
if (BLI_bvhtree_ray_cast(treeData.tree, origin, direction, 0.0f, &hit,
|
||||
treeData.raycast_callback, &treeData) != -1)
|
||||
{
|
||||
if (hit.dist <= distance) {
|
||||
*r_success = success = true;
|
||||
|
||||
copy_v3_v3(r_location, hit.co);
|
||||
copy_v3_v3(r_normal, hit.no);
|
||||
*r_index = dm_looptri_to_poly_index(ob->derivedFinal, &treeData.looptri[hit.index]);
|
||||
|
||||
goto finally;
|
||||
copy_v3_v3(r_location, hit.co);
|
||||
copy_v3_v3(r_normal, hit.no);
|
||||
*r_index = dm_looptri_to_poly_index(ob->derivedFinal, &treeData.looptri[hit.index]);
|
||||
}
|
||||
}
|
||||
|
||||
free_bvhtree_from_mesh(&treeData);
|
||||
}
|
||||
}
|
||||
if (success == false) {
|
||||
*r_success = false;
|
||||
|
||||
*r_success = false;
|
||||
|
||||
zero_v3(r_location);
|
||||
zero_v3(r_normal);
|
||||
*r_index = -1;
|
||||
|
||||
finally:
|
||||
free_bvhtree_from_mesh(&treeData);
|
||||
zero_v3(r_location);
|
||||
zero_v3(r_normal);
|
||||
*r_index = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void rna_Object_closest_point_on_mesh(
|
||||
|
|
|
@ -78,8 +78,8 @@ void fluidsim_init(FluidsimModifierData *fluidmd)
|
|||
fss->resolutionxyz = 65;
|
||||
fss->previewresxyz = 45;
|
||||
fss->realsize = 0.5;
|
||||
fss->guiDisplayMode = 2; // preview
|
||||
fss->renderDisplayMode = 3; // render
|
||||
fss->guiDisplayMode = OB_FSDOM_PREVIEW;
|
||||
fss->renderDisplayMode = OB_FSDOM_FINAL;
|
||||
|
||||
fss->viscosityValue = 1.0;
|
||||
fss->viscosityExponent = 6;
|
||||
|
@ -98,7 +98,7 @@ void fluidsim_init(FluidsimModifierData *fluidmd)
|
|||
/* fluid/inflow settings
|
||||
* fss->iniVel --> automatically set to 0 */
|
||||
|
||||
modifier_path_init(fss->surfdataPath, sizeof(fss->surfdataPath), "cache_fluid");
|
||||
modifier_path_init(fss->surfdataPath, sizeof(fss->surfdataPath), OB_FLUIDSIM_SURF_DIR_DEFAULT);
|
||||
|
||||
/* first init of bounding box */
|
||||
/* no bounding box needed */
|
||||
|
@ -423,8 +423,6 @@ static void fluidsim_read_vel_cache(FluidsimModifierData *fluidmd, DerivedMesh *
|
|||
static DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm,
|
||||
FluidsimModifierData *fluidmd, int framenr, int useRenderParams)
|
||||
{
|
||||
int displaymode = 0;
|
||||
|
||||
int curFrame = framenr /* - 1 */ /*scene->r.sfra*/; /* start with 0 at start frame */
|
||||
/* why start with 0 as start frame?? Animations + time are frozen for frame 0 anyway. (See physics_fluid.c for that. - DG */
|
||||
/* If we start with frame 0, we need to remap all animation channels, too, because they will all be 1 frame late if using frame-1! - DG */
|
||||
|
@ -435,25 +433,23 @@ static DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm,
|
|||
MPoly *mpoly;
|
||||
MPoly mp_example = {0};
|
||||
|
||||
if (!useRenderParams) {
|
||||
displaymode = fss->guiDisplayMode;
|
||||
}
|
||||
else {
|
||||
displaymode = fss->renderDisplayMode;
|
||||
}
|
||||
const int displaymode = useRenderParams ? fss->renderDisplayMode : fss->guiDisplayMode;
|
||||
|
||||
switch (displaymode) {
|
||||
case 1:
|
||||
case OB_FSDOM_GEOM:
|
||||
/* just display original object */
|
||||
return NULL;
|
||||
case 2:
|
||||
case OB_FSDOM_PREVIEW:
|
||||
/* use preview mesh */
|
||||
BLI_join_dirfile(targetFile, sizeof(targetFile), fss->surfdataPath, OB_FLUIDSIM_SURF_PREVIEW_OBJ_FNAME);
|
||||
break;
|
||||
default: /* 3 */
|
||||
/* 3. use final mesh */
|
||||
case OB_FSDOM_FINAL:
|
||||
/* use final mesh */
|
||||
BLI_join_dirfile(targetFile, sizeof(targetFile), fss->surfdataPath, OB_FLUIDSIM_SURF_FINAL_OBJ_FNAME);
|
||||
break;
|
||||
default:
|
||||
BLI_assert(!"Wrong fluidsim display type");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* offset baked frame */
|
||||
|
@ -494,7 +490,7 @@ static DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm,
|
|||
/* load vertex velocities, if they exist...
|
||||
* TODO? use generate flag as loading flag as well?
|
||||
* warning, needs original .bobj.gz mesh loading filename */
|
||||
if (displaymode == 3) {
|
||||
if (displaymode == OB_FSDOM_FINAL) {
|
||||
fluidsim_read_vel_cache(fluidmd, dm, targetFile);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -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", "" )
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -39,7 +39,16 @@ static bNodeSocketTemplate sh_node_object_info_out[] = {
|
|||
|
||||
static int node_shader_gpu_object_info(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
|
||||
{
|
||||
return GPU_stack_link(mat, "node_object_info", in, out);
|
||||
return GPU_stack_link(mat, "node_object_info", in, out, GPU_builtin(GPU_OBJECT_MATRIX), GPU_builtin(GPU_OBJECT_INFO));
|
||||
}
|
||||
|
||||
static void node_shader_exec_object_info(void *data, int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **UNUSED(in), bNodeStack **out)
|
||||
{
|
||||
ShaderCallData *scd = (ShaderCallData *)data;
|
||||
copy_v4_v4(out[0]->vec, RE_object_instance_get_matrix(scd->shi->obi, RE_OBJECT_INSTANCE_MATRIX_OB)[3]);
|
||||
out[1]->vec[0] = RE_object_instance_get_object_pass_index(scd->shi->obi);
|
||||
out[2]->vec[0] = scd->shi->mat->index;
|
||||
out[3]->vec[0] = RE_object_instance_get_random_id(scd->shi->obi) * (1.0f/(float)0xFFFFFFFF);;
|
||||
}
|
||||
|
||||
/* node type definition */
|
||||
|
@ -53,6 +62,7 @@ void register_node_type_sh_object_info(void)
|
|||
node_type_init(&ntype, NULL);
|
||||
node_type_storage(&ntype, "", NULL, NULL);
|
||||
node_type_gpu(&ntype, node_shader_gpu_object_info);
|
||||
node_type_exec(&ntype, NULL, NULL, node_shader_exec_object_info);
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
|
|
|
@ -381,7 +381,7 @@ bool RE_allow_render_generic_object(struct Object *ob);
|
|||
/* RE_updateRenderInstances flag */
|
||||
enum {
|
||||
RE_OBJECT_INSTANCES_UPDATE_VIEW = (1 << 0),
|
||||
RE_OBJECT_INSTANCES_UPDATE_OBMAT = (1 << 1),
|
||||
RE_OBJECT_INSTANCES_UPDATE_OBMAT = (1 << 1)
|
||||
};
|
||||
void RE_updateRenderInstances(Render *re, int flag);
|
||||
|
||||
|
|
|
@ -178,6 +178,7 @@ typedef struct ShadeInput {
|
|||
|
||||
unsigned int lay;
|
||||
int layflag, passflag, combinedflag;
|
||||
short object_pass_index;
|
||||
struct Group *light_override;
|
||||
struct Material *mat_override;
|
||||
|
||||
|
@ -241,6 +242,9 @@ enum {
|
|||
|
||||
const float (*RE_object_instance_get_matrix(struct ObjectInstanceRen *obi, int matrix_id))[4];
|
||||
|
||||
float RE_object_instance_get_object_pass_index(struct ObjectInstanceRen *obi);
|
||||
float RE_object_instance_get_random_id(struct ObjectInstanceRen *obi);
|
||||
|
||||
enum {
|
||||
RE_VIEW_MATRIX,
|
||||
RE_VIEWINV_MATRIX,
|
||||
|
|
|
@ -382,6 +382,8 @@ typedef struct ObjectInstanceRen {
|
|||
float part_co[3];
|
||||
float part_vel[3];
|
||||
float part_avel[3];
|
||||
|
||||
unsigned int random_id;
|
||||
} ObjectInstanceRen;
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
#include "BLI_math.h"
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_hash.h"
|
||||
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
|
@ -1458,6 +1459,14 @@ ObjectInstanceRen *RE_addRenderInstance(
|
|||
}
|
||||
}
|
||||
|
||||
/* Fill object info */
|
||||
if (dob) {
|
||||
obi->random_id = dob->random_id;
|
||||
}
|
||||
else {
|
||||
obi->random_id = BLI_hash_int_2d(BLI_hash_string(obi->ob->id.name + 2), 0);
|
||||
}
|
||||
|
||||
RE_updateRenderInstance(re, obi, RE_OBJECT_INSTANCES_UPDATE_OBMAT | RE_OBJECT_INSTANCES_UPDATE_VIEW);
|
||||
|
||||
if (mat) {
|
||||
|
|
|
@ -2141,6 +2141,16 @@ const float (*RE_object_instance_get_matrix(struct ObjectInstanceRen *obi, int m
|
|||
return NULL;
|
||||
}
|
||||
|
||||
float RE_object_instance_get_object_pass_index(struct ObjectInstanceRen *obi)
|
||||
{
|
||||
return obi->ob->index;
|
||||
}
|
||||
|
||||
float RE_object_instance_get_random_id(struct ObjectInstanceRen *obi)
|
||||
{
|
||||
return obi->random_id;
|
||||
}
|
||||
|
||||
const float (*RE_render_current_get_matrix(int matrix_id))[4]
|
||||
{
|
||||
switch (matrix_id) {
|
||||
|
|
|
@ -278,6 +278,8 @@ struct Object *RE_GetCamera(struct Render *re) RET_NULL
|
|||
float RE_lamp_get_data(struct ShadeInput *shi, struct Object *lamp_obj, float col[4], float lv[3], float *dist, float shadow[4]) RET_ZERO
|
||||
const float (*RE_object_instance_get_matrix(struct ObjectInstanceRen *obi, int matrix_id))[4] RET_NULL
|
||||
const float (*RE_render_current_get_matrix(int matrix_id))[4] RET_NULL
|
||||
float RE_object_instance_get_object_pass_index(struct ObjectInstanceRen *obi) RET_ZERO
|
||||
float RE_object_instance_get_random_id(struct ObjectInstanceRen *obi) RET_ZERO
|
||||
|
||||
/* blenkernel */
|
||||
bool BKE_paint_proj_mesh_data_check(struct Scene *scene, struct Object *ob, bool *uvs, bool *mat, bool *tex, bool *stencil) RET_ZERO
|
||||
|
|
|
@ -169,7 +169,7 @@ void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty )
|
|||
|
||||
rasty->GetViewMatrix().getValue(&viewmat[0][0]);
|
||||
float auto_bump_scale = ms.m_pDerivedMesh!=0 ? ms.m_pDerivedMesh->auto_bump_scale : 1.0f;
|
||||
GPU_material_bind_uniforms(gpumat, obmat, viewmat, obcol, auto_bump_scale, NULL);
|
||||
GPU_material_bind_uniforms(gpumat, obmat, viewmat, obcol, auto_bump_scale, NULL, NULL);
|
||||
|
||||
mAlphaBlend = GPU_material_alpha_blend(gpumat, obcol);
|
||||
}
|
||||
|
|
|
@ -59,12 +59,6 @@ class AbstractAlembicTest(unittest.TestCase):
|
|||
def setUpClass(cls):
|
||||
import re
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--blender', required=True)
|
||||
parser.add_argument('--testdir', required=True)
|
||||
parser.add_argument('--alembic-root', required=True)
|
||||
args, _ = parser.parse_known_args()
|
||||
|
||||
cls.blender = args.blender
|
||||
cls.testdir = pathlib.Path(args.testdir)
|
||||
cls.alembic_root = pathlib.Path(args.alembic_root)
|
||||
|
@ -116,6 +110,7 @@ class AbstractAlembicTest(unittest.TestCase):
|
|||
The Python bindings for Alembic are old, and only compatible with Python 2.x,
|
||||
so that's why we can't use them here, and have to rely on other tooling.
|
||||
"""
|
||||
import collections
|
||||
|
||||
abcls = self.alembic_root / 'bin' / 'abcls'
|
||||
|
||||
|
@ -133,14 +128,19 @@ class AbstractAlembicTest(unittest.TestCase):
|
|||
converters = {
|
||||
'bool_t': int,
|
||||
'uint8_t': int,
|
||||
'int32_t': int,
|
||||
'float64_t': float,
|
||||
'float32_t': float,
|
||||
}
|
||||
|
||||
result = {}
|
||||
|
||||
# Ideally we'd get abcls to output JSON, see https://github.com/alembic/alembic/issues/121
|
||||
lines = output.split('\n')
|
||||
for info, value in zip(lines[0::2], lines[1::2]):
|
||||
lines = collections.deque(output.split('\n'))
|
||||
while lines:
|
||||
info = lines.popleft()
|
||||
if not info:
|
||||
continue
|
||||
proptype, valtype_and_arrsize, name_and_extent = info.split()
|
||||
|
||||
# Parse name and extent
|
||||
|
@ -152,22 +152,41 @@ class AbstractAlembicTest(unittest.TestCase):
|
|||
if extent != '1':
|
||||
self.fail('Unsupported extent %s for property %s/%s' % (extent, proppath, name))
|
||||
|
||||
# Parse type and convert values
|
||||
# Parse type
|
||||
m = self.abcls_array.match(valtype_and_arrsize)
|
||||
if not m:
|
||||
self.fail('Unparsable value type from abcls: %s' % valtype_and_arrsize)
|
||||
valtype, arraysize = m.group('name'), m.group('arraysize')
|
||||
valtype, scalarsize = m.group('name'), m.group('arraysize')
|
||||
|
||||
# Convert values
|
||||
try:
|
||||
conv = converters[valtype]
|
||||
except KeyError:
|
||||
self.fail('Unsupported type %s for property %s/%s' % (valtype, proppath, name))
|
||||
|
||||
if arraysize is None:
|
||||
result[name] = conv(value)
|
||||
def convert_single_line(linevalue):
|
||||
try:
|
||||
if scalarsize is None:
|
||||
return conv(linevalue)
|
||||
else:
|
||||
return [conv(v.strip()) for v in linevalue.split(',')]
|
||||
except ValueError as ex:
|
||||
return str(ex)
|
||||
|
||||
if proptype == 'ScalarProperty':
|
||||
value = lines.popleft()
|
||||
result[name] = convert_single_line(value)
|
||||
elif proptype == 'ArrayProperty':
|
||||
arrayvalue = []
|
||||
# Arrays consist of a variable number of items, and end in a blank line.
|
||||
while True:
|
||||
linevalue = lines.popleft()
|
||||
if not linevalue:
|
||||
break
|
||||
arrayvalue.append(convert_single_line(linevalue))
|
||||
result[name] = arrayvalue
|
||||
else:
|
||||
values = [conv(v.strip()) for v in value.split(',')]
|
||||
result[name] = values
|
||||
self.fail('Unsupported type %s for property %s/%s' % (proptype, proppath, name))
|
||||
|
||||
return result
|
||||
|
||||
|
@ -221,5 +240,63 @@ class HierarchicalAndFlatExportTest(AbstractAlembicTest):
|
|||
)
|
||||
|
||||
|
||||
class DupliGroupExportTest(AbstractAlembicTest):
|
||||
@with_tempdir
|
||||
def test_hierarchical_export(self, tempdir: pathlib.Path):
|
||||
abc = tempdir / 'dupligroup_hierarchical.abc'
|
||||
script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \
|
||||
"renderable_only=True, visible_layers_only=True, flatten=False)" % abc
|
||||
self.run_blender('dupligroup-scene.blend', script)
|
||||
|
||||
# Now check the resulting Alembic file.
|
||||
xform = self.abcprop(abc, '/Real_Cube/Linked_Suzanne/Cylinder/Suzanne/.xform')
|
||||
self.assertEqual(1, xform['.inherits'])
|
||||
self.assertAlmostEqualFloatArray(
|
||||
xform['.vals'],
|
||||
[1.0, 0.0, 0.0, 0.0,
|
||||
0.0, 1.0, 0.0, 0.0,
|
||||
0.0, 0.0, 1.0, 0.0,
|
||||
0.0, 2.0, 0.0, 1.0]
|
||||
)
|
||||
|
||||
@with_tempdir
|
||||
def test_flat_export(self, tempdir: pathlib.Path):
|
||||
abc = tempdir / 'dupligroup_hierarchical.abc'
|
||||
script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \
|
||||
"renderable_only=True, visible_layers_only=True, flatten=True)" % abc
|
||||
self.run_blender('dupligroup-scene.blend', script)
|
||||
|
||||
# Now check the resulting Alembic file.
|
||||
xform = self.abcprop(abc, '/Suzanne/.xform')
|
||||
self.assertEqual(0, xform['.inherits'])
|
||||
|
||||
self.assertAlmostEqualFloatArray(
|
||||
xform['.vals'],
|
||||
[1.5, 0.0, 0.0, 0.0,
|
||||
0.0, 1.5, 0.0, 0.0,
|
||||
0.0, 0.0, 1.5, 0.0,
|
||||
2.0, 3.0, 0.0, 1.0]
|
||||
)
|
||||
|
||||
|
||||
class CurveExportTest(AbstractAlembicTest):
|
||||
@with_tempdir
|
||||
def test_export_single_curve(self, tempdir: pathlib.Path):
|
||||
abc = tempdir / 'single-curve.abc'
|
||||
script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \
|
||||
"renderable_only=True, visible_layers_only=True, flatten=False)" % abc
|
||||
self.run_blender('single-curve.blend', script)
|
||||
|
||||
# Now check the resulting Alembic file.
|
||||
abcprop = self.abcprop(abc, '/NurbsCurve/NurbsCurveShape/.geom')
|
||||
self.assertEqual(abcprop['.orders'], [4])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(argv=sys.argv[0:1])
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--blender', required=True)
|
||||
parser.add_argument('--testdir', required=True)
|
||||
parser.add_argument('--alembic-root', required=True)
|
||||
args, remaining = parser.parse_known_args()
|
||||
|
||||
unittest.main(argv=sys.argv[0:1] + remaining)
|
||||
|
|
Loading…
Reference in New Issue