Shader: Change specular tint in Principled BSDF from float to color
For more artistic control. Tints the reflection of dielectric materials at normal incidence. Ref #99447 Pull Request: https://projects.blender.org/blender/blender/pulls/112192
This commit is contained in:
parent
86156566a7
commit
def9b76207
@ -15,7 +15,7 @@ shader node_principled_bsdf(string distribution = "multi_ggx",
|
|||||||
float SubsurfaceAnisotropy = 0.0,
|
float SubsurfaceAnisotropy = 0.0,
|
||||||
float Metallic = 0.0,
|
float Metallic = 0.0,
|
||||||
float Specular = 0.5,
|
float Specular = 0.5,
|
||||||
float SpecularTint = 0.0,
|
color SpecularTint = color(1.0),
|
||||||
color MetallicTint = 1.0,
|
color MetallicTint = 1.0,
|
||||||
float Roughness = 0.5,
|
float Roughness = 0.5,
|
||||||
float Anisotropic = 0.0,
|
float Anisotropic = 0.0,
|
||||||
@ -68,14 +68,9 @@ shader node_principled_bsdf(string distribution = "multi_ggx",
|
|||||||
BSDF = mix(BSDF, BaseColor * SubsurfBSDF, Subsurface);
|
BSDF = mix(BSDF, BaseColor * SubsurfBSDF, Subsurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
color f0 = color(F0_from_ior(IOR));
|
|
||||||
color f90 = color(1.0);
|
|
||||||
|
|
||||||
/* Apply specular tint */
|
/* Apply specular tint */
|
||||||
float m_cdlum = luminance(BaseColor);
|
color f0 = F0_from_ior(IOR) * SpecularTint * 2.0 * Specular;
|
||||||
color m_ctint = m_cdlum > 0.0 ? BaseColor / m_cdlum : color(1.0);
|
color f90 = color(1.0);
|
||||||
color specTint = mix(color(1.0), m_ctint, SpecularTint);
|
|
||||||
f0 *= (specTint * 2.0 * Specular);
|
|
||||||
|
|
||||||
BSDF = layer(
|
BSDF = layer(
|
||||||
generalized_schlick_bsdf(
|
generalized_schlick_bsdf(
|
||||||
@ -85,12 +80,14 @@ shader node_principled_bsdf(string distribution = "multi_ggx",
|
|||||||
|
|
||||||
closure color TransmissionBSDF = 0;
|
closure color TransmissionBSDF = 0;
|
||||||
if (Metallic < 1.0 && Transmission > 0.0) {
|
if (Metallic < 1.0 && Transmission > 0.0) {
|
||||||
color reflectTint = mix(color(1.0), BaseColor, SpecularTint);
|
|
||||||
float eta = max(IOR, 1e-5);
|
float eta = max(IOR, 1e-5);
|
||||||
eta = backfacing() ? 1.0 / eta : eta;
|
eta = backfacing() ? 1.0 / eta : eta;
|
||||||
|
|
||||||
TransmissionBSDF = dielectric_bsdf(
|
color f0 = F0_from_ior(eta) * SpecularTint;
|
||||||
Normal, vector(0.0), reflectTint, sqrt(BaseColor), r2, r2, eta, distribution);
|
color f90 = color(1.0);
|
||||||
|
|
||||||
|
TransmissionBSDF = generalized_schlick_bsdf(
|
||||||
|
Normal, vector(0.0), color(1.0), sqrt(BaseColor), r2, r2, f0, f90, -eta, distribution),
|
||||||
BSDF = mix(BSDF, TransmissionBSDF, clamp(Transmission, 0.0, 1.0));
|
BSDF = mix(BSDF, TransmissionBSDF, clamp(Transmission, 0.0, 1.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||||||
float subsurface = param2;
|
float subsurface = param2;
|
||||||
float specular = stack_load_float(stack, specular_offset);
|
float specular = stack_load_float(stack, specular_offset);
|
||||||
float roughness = stack_load_float(stack, roughness_offset);
|
float roughness = stack_load_float(stack, roughness_offset);
|
||||||
float specular_tint = stack_load_float(stack, specular_tint_offset);
|
Spectrum specular_tint = rgb_to_spectrum(stack_load_float3(stack, specular_tint_offset));
|
||||||
float anisotropic = stack_load_float(stack, anisotropic_offset);
|
float anisotropic = stack_load_float(stack, anisotropic_offset);
|
||||||
float sheen = stack_load_float(stack, sheen_offset);
|
float sheen = stack_load_float(stack, sheen_offset);
|
||||||
float3 sheen_tint = stack_load_float3(stack, sheen_tint_offset);
|
float3 sheen_tint = stack_load_float3(stack, sheen_tint_offset);
|
||||||
@ -287,9 +287,9 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||||||
if (glass_caustics && transmission > CLOSURE_WEIGHT_CUTOFF) {
|
if (glass_caustics && transmission > CLOSURE_WEIGHT_CUTOFF) {
|
||||||
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
|
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
|
||||||
sd, sizeof(MicrofacetBsdf), transmission * weight);
|
sd, sizeof(MicrofacetBsdf), transmission * weight);
|
||||||
ccl_private FresnelDielectricTint *fresnel =
|
ccl_private FresnelGeneralizedSchlick *fresnel =
|
||||||
(bsdf != NULL) ? (ccl_private FresnelDielectricTint *)closure_alloc_extra(
|
(bsdf != NULL) ? (ccl_private FresnelGeneralizedSchlick *)closure_alloc_extra(
|
||||||
sd, sizeof(FresnelDielectricTint)) :
|
sd, sizeof(FresnelGeneralizedSchlick)) :
|
||||||
NULL;
|
NULL;
|
||||||
|
|
||||||
if (bsdf && fresnel) {
|
if (bsdf && fresnel) {
|
||||||
@ -299,14 +299,16 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||||||
bsdf->alpha_x = bsdf->alpha_y = sqr(roughness);
|
bsdf->alpha_x = bsdf->alpha_y = sqr(roughness);
|
||||||
bsdf->ior = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
|
bsdf->ior = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
|
||||||
|
|
||||||
fresnel->reflection_tint = mix(
|
fresnel->f0 = F0_from_ior(eta) * specular_tint;
|
||||||
one_spectrum(), rgb_to_spectrum(base_color), specular_tint);
|
fresnel->f90 = one_spectrum();
|
||||||
|
fresnel->exponent = -eta;
|
||||||
|
fresnel->reflection_tint = one_spectrum();
|
||||||
fresnel->transmission_tint = sqrt(rgb_to_spectrum(base_color));
|
fresnel->transmission_tint = sqrt(rgb_to_spectrum(base_color));
|
||||||
|
|
||||||
/* setup bsdf */
|
/* setup bsdf */
|
||||||
sd->flag |= bsdf_microfacet_ggx_glass_setup(bsdf);
|
sd->flag |= bsdf_microfacet_ggx_glass_setup(bsdf);
|
||||||
const bool is_multiggx = (distribution == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
|
const bool is_multiggx = (distribution == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
|
||||||
bsdf_microfacet_setup_fresnel_dielectric_tint(kg, bsdf, sd, fresnel, is_multiggx);
|
bsdf_microfacet_setup_fresnel_generalized_schlick(kg, bsdf, sd, fresnel, is_multiggx);
|
||||||
|
|
||||||
/* Attenuate other components */
|
/* Attenuate other components */
|
||||||
weight *= (1.0f - transmission);
|
weight *= (1.0f - transmission);
|
||||||
@ -329,11 +331,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||||||
bsdf->alpha_x = alpha_x;
|
bsdf->alpha_x = alpha_x;
|
||||||
bsdf->alpha_y = alpha_y;
|
bsdf->alpha_y = alpha_y;
|
||||||
|
|
||||||
float m_cdlum = linear_rgb_to_gray(kg, base_color);
|
fresnel->f0 = F0_from_ior(eta) * 2.0f * specular * specular_tint;
|
||||||
float3 m_ctint = m_cdlum > 0.0f ? base_color / m_cdlum : one_float3();
|
|
||||||
float3 specTint = mix(one_spectrum(), rgb_to_spectrum(m_ctint), specular_tint);
|
|
||||||
|
|
||||||
fresnel->f0 = F0_from_ior(eta) * 2.0f * specular * specTint;
|
|
||||||
fresnel->f90 = one_spectrum();
|
fresnel->f90 = one_spectrum();
|
||||||
fresnel->exponent = -eta;
|
fresnel->exponent = -eta;
|
||||||
fresnel->reflection_tint = one_spectrum();
|
fresnel->reflection_tint = one_spectrum();
|
||||||
|
@ -2707,7 +2707,7 @@ NODE_DEFINE(PrincipledBsdfNode)
|
|||||||
SOCKET_IN_FLOAT(subsurface_anisotropy, "Subsurface Anisotropy", 0.0f);
|
SOCKET_IN_FLOAT(subsurface_anisotropy, "Subsurface Anisotropy", 0.0f);
|
||||||
SOCKET_IN_FLOAT(specular, "Specular", 0.0f);
|
SOCKET_IN_FLOAT(specular, "Specular", 0.0f);
|
||||||
SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
|
SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
|
||||||
SOCKET_IN_FLOAT(specular_tint, "Specular Tint", 0.0f);
|
SOCKET_IN_COLOR(specular_tint, "Specular Tint", one_float3());
|
||||||
SOCKET_IN_COLOR(metallic_tint, "Metallic Tint", one_float3());
|
SOCKET_IN_COLOR(metallic_tint, "Metallic Tint", one_float3());
|
||||||
SOCKET_IN_FLOAT(anisotropic, "Anisotropic", 0.0f);
|
SOCKET_IN_FLOAT(anisotropic, "Anisotropic", 0.0f);
|
||||||
SOCKET_IN_FLOAT(sheen, "Sheen", 0.0f);
|
SOCKET_IN_FLOAT(sheen, "Sheen", 0.0f);
|
||||||
|
@ -527,7 +527,7 @@ class PrincipledBsdfNode : public BsdfBaseNode {
|
|||||||
NODE_SOCKET_API(float, subsurface)
|
NODE_SOCKET_API(float, subsurface)
|
||||||
NODE_SOCKET_API(float, specular)
|
NODE_SOCKET_API(float, specular)
|
||||||
NODE_SOCKET_API(float, roughness)
|
NODE_SOCKET_API(float, roughness)
|
||||||
NODE_SOCKET_API(float, specular_tint)
|
NODE_SOCKET_API(float3, specular_tint)
|
||||||
NODE_SOCKET_API(float3, metallic_tint)
|
NODE_SOCKET_API(float3, metallic_tint)
|
||||||
NODE_SOCKET_API(float, anisotropic)
|
NODE_SOCKET_API(float, anisotropic)
|
||||||
NODE_SOCKET_API(float, sheen)
|
NODE_SOCKET_API(float, sheen)
|
||||||
|
@ -294,14 +294,15 @@ class PrincipledBSDFWrapper(ShaderWrapper):
|
|||||||
|
|
||||||
def specular_tint_get(self):
|
def specular_tint_get(self):
|
||||||
if not self.use_nodes or self.node_principled_bsdf is None:
|
if not self.use_nodes or self.node_principled_bsdf is None:
|
||||||
return 0.0
|
return Color((0.0, 0.0, 0.0))
|
||||||
return self.node_principled_bsdf.inputs["Specular Tint"].default_value
|
return rgba_to_rgb(self.node_principled_bsdf.inputs["Specular Tint"].default_value)
|
||||||
|
|
||||||
@_set_check
|
@_set_check
|
||||||
def specular_tint_set(self, value):
|
def specular_tint_set(self, color):
|
||||||
value = values_clamp(value, 0.0, 1.0)
|
color = values_clamp(color, 0.0, 1.0)
|
||||||
|
color = rgb_to_rgba(color)
|
||||||
if self.use_nodes and self.node_principled_bsdf is not None:
|
if self.use_nodes and self.node_principled_bsdf is not None:
|
||||||
self.node_principled_bsdf.inputs["Specular Tint"].default_value = value
|
self.node_principled_bsdf.inputs["Specular Tint"].default_value = color
|
||||||
|
|
||||||
specular_tint = property(specular_tint_get, specular_tint_set)
|
specular_tint = property(specular_tint_get, specular_tint_set)
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ extern "C" {
|
|||||||
|
|
||||||
/* Blender file format version. */
|
/* Blender file format version. */
|
||||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||||
#define BLENDER_FILE_SUBVERSION 24
|
#define BLENDER_FILE_SUBVERSION 25
|
||||||
|
|
||||||
/* Minimum Blender version that supports reading file written with the current
|
/* Minimum Blender version that supports reading file written with the current
|
||||||
* version. Older Blender versions will test this and cancel loading the file, showing a warning to
|
* version. Older Blender versions will test this and cancel loading the file, showing a warning to
|
||||||
|
@ -905,6 +905,65 @@ static void version_node_group_split_socket(bNodeTreeInterface &tree_interface,
|
|||||||
csocket->flag &= ~NODE_INTERFACE_SOCKET_OUTPUT;
|
csocket->flag &= ~NODE_INTERFACE_SOCKET_OUTPUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Convert specular tint in Principled BSDF. */
|
||||||
|
static void version_principled_bsdf_specular_tint(bNodeTree *ntree)
|
||||||
|
{
|
||||||
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||||
|
if (node->type != SH_NODE_BSDF_PRINCIPLED) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
bNodeSocket *specular_tint_sock = nodeFindSocket(node, SOCK_IN, "Specular Tint");
|
||||||
|
if (specular_tint_sock->type == SOCK_RGBA) {
|
||||||
|
/* Node is already updated. */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bNodeSocket *base_color_sock = nodeFindSocket(node, SOCK_IN, "Base Color");
|
||||||
|
float specular_tint_old = *version_cycles_node_socket_float_value(specular_tint_sock);
|
||||||
|
float *base_color = version_cycles_node_socket_rgba_value(base_color_sock);
|
||||||
|
|
||||||
|
/* Change socket type to Color. */
|
||||||
|
nodeModifySocketTypeStatic(ntree, node, specular_tint_sock, SOCK_RGBA, 0);
|
||||||
|
|
||||||
|
static float one[] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||||
|
|
||||||
|
/* If any of the two inputs is dynamic, we add a Mix node. */
|
||||||
|
if (base_color_sock->link || specular_tint_sock->link) {
|
||||||
|
bNode *mix = nodeAddStaticNode(nullptr, ntree, SH_NODE_MIX);
|
||||||
|
static_cast<NodeShaderMix *>(mix->storage)->data_type = SOCK_RGBA;
|
||||||
|
mix->locx = node->locx - 170;
|
||||||
|
mix->locy = node->locy - 120;
|
||||||
|
|
||||||
|
bNodeSocket *a_in = nodeFindSocket(mix, SOCK_IN, "A_Color");
|
||||||
|
bNodeSocket *b_in = nodeFindSocket(mix, SOCK_IN, "B_Color");
|
||||||
|
bNodeSocket *fac_in = nodeFindSocket(mix, SOCK_IN, "Factor_Float");
|
||||||
|
bNodeSocket *result_out = nodeFindSocket(mix, SOCK_OUT, "Result_Color");
|
||||||
|
|
||||||
|
copy_v4_v4(version_cycles_node_socket_rgba_value(a_in), one);
|
||||||
|
copy_v4_v4(version_cycles_node_socket_rgba_value(b_in), base_color);
|
||||||
|
*version_cycles_node_socket_float_value(fac_in) = specular_tint_old;
|
||||||
|
|
||||||
|
if (base_color_sock->link) {
|
||||||
|
nodeAddLink(
|
||||||
|
ntree, base_color_sock->link->fromnode, base_color_sock->link->fromsock, mix, b_in);
|
||||||
|
}
|
||||||
|
if (specular_tint_sock->link) {
|
||||||
|
nodeAddLink(ntree,
|
||||||
|
specular_tint_sock->link->fromnode,
|
||||||
|
specular_tint_sock->link->fromsock,
|
||||||
|
mix,
|
||||||
|
fac_in);
|
||||||
|
nodeRemLink(ntree, specular_tint_sock->link);
|
||||||
|
}
|
||||||
|
nodeAddLink(ntree, mix, result_out, node, specular_tint_sock);
|
||||||
|
}
|
||||||
|
|
||||||
|
float *specular_tint = version_cycles_node_socket_rgba_value(specular_tint_sock);
|
||||||
|
/* Mix the fixed values. */
|
||||||
|
interp_v4_v4v4(specular_tint, one, base_color, specular_tint_old);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
|
void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
|
||||||
{
|
{
|
||||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 1)) {
|
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 1)) {
|
||||||
@ -1359,6 +1418,16 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||||||
FOREACH_NODETREE_END;
|
FOREACH_NODETREE_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 25)) {
|
||||||
|
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
|
||||||
|
if (ntree->type == NTREE_SHADER) {
|
||||||
|
/* Convert specular tint on the Principled BSDF. */
|
||||||
|
version_principled_bsdf_specular_tint(ntree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FOREACH_NODETREE_END;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Versioning code until next subversion bump goes here.
|
* Versioning code until next subversion bump goes here.
|
||||||
*
|
*
|
||||||
|
@ -93,7 +93,15 @@ float ambient_occlusion_eval(vec3 normal,
|
|||||||
vec3 safe_normalize(vec3 N);
|
vec3 safe_normalize(vec3 N);
|
||||||
float fast_sqrt(float a);
|
float fast_sqrt(float a);
|
||||||
vec3 cameraVec(vec3 P);
|
vec3 cameraVec(vec3 P);
|
||||||
vec2 bsdf_lut(float a, float b, float c, float d);
|
void bsdf_lut(vec3 F0,
|
||||||
|
vec3 F90,
|
||||||
|
vec3 transmission_tint,
|
||||||
|
float cos_theta,
|
||||||
|
float roughness,
|
||||||
|
float ior,
|
||||||
|
float do_multiscatter,
|
||||||
|
out vec3 reflectance,
|
||||||
|
out vec3 transmittance);
|
||||||
vec2 brdf_lut(float a, float b);
|
vec2 brdf_lut(float a, float b);
|
||||||
vec3 F_brdf_multi_scatter(vec3 a, vec3 b, vec2 c);
|
vec3 F_brdf_multi_scatter(vec3 a, vec3 b, vec2 c);
|
||||||
vec3 F_brdf_single_scatter(vec3 a, vec3 b, vec2 c);
|
vec3 F_brdf_single_scatter(vec3 a, vec3 b, vec2 c);
|
||||||
|
@ -101,24 +101,35 @@ vec3 lut_coords_bsdf(float cos_theta, float roughness, float ior)
|
|||||||
return coords;
|
return coords;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Computes the reflectance and transmittance based on the BSDF LUT. */
|
/* Computes the reflectance and transmittance based on the tint (`f0`, `f90`, `transmission_tint`)
|
||||||
vec2 bsdf_lut(float cos_theta, float roughness, float ior, float do_multiscatter)
|
* and the BSDF LUT. */
|
||||||
|
void bsdf_lut(vec3 F0,
|
||||||
|
vec3 F90,
|
||||||
|
vec3 transmission_tint,
|
||||||
|
float cos_theta,
|
||||||
|
float roughness,
|
||||||
|
float ior,
|
||||||
|
float do_multiscatter,
|
||||||
|
out vec3 reflectance,
|
||||||
|
out vec3 transmittance)
|
||||||
{
|
{
|
||||||
if (ior == 1.0) {
|
if (ior == 1.0) {
|
||||||
return vec2(0.0, 1.0);
|
reflectance = vec3(0.0);
|
||||||
|
transmittance = transmission_tint;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 split_sum;
|
vec2 split_sum;
|
||||||
float transmission_factor;
|
float transmission_factor;
|
||||||
float F0 = F0_from_ior(ior);
|
|
||||||
float F90 = 1.0;
|
|
||||||
|
|
||||||
if (ior >= 1.0) {
|
if (ior > 1.0) {
|
||||||
split_sum = brdf_lut(cos_theta, roughness);
|
split_sum = brdf_lut(cos_theta, roughness);
|
||||||
transmission_factor = sample_3D_texture(utilTex, lut_coords_btdf(cos_theta, roughness, ior)).a;
|
transmission_factor = sample_3D_texture(utilTex, lut_coords_btdf(cos_theta, roughness, ior)).a;
|
||||||
/* Gradually increase `f90` from 0 to 1 when IOR is in the range of [1.0, 1.33], to avoid harsh
|
/* Gradually increase `f90` from 0 to 1 when IOR is in the range of [1.0, 1.33], to avoid harsh
|
||||||
* transition at `IOR == 1`. */
|
* transition at `IOR == 1`. */
|
||||||
F90 = saturate(2.33 / 0.33 * (ior - 1.0) / (ior + 1.0));
|
if (all(equal(F90, vec3(1.0)))) {
|
||||||
|
F90 = vec3(saturate(2.33 / 0.33 * (ior - 1.0) / (ior + 1.0)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
vec3 bsdf = sample_3D_texture(utilTex, lut_coords_bsdf(cos_theta, roughness, ior)).rgb;
|
vec3 bsdf = sample_3D_texture(utilTex, lut_coords_bsdf(cos_theta, roughness, ior)).rgb;
|
||||||
@ -126,20 +137,34 @@ vec2 bsdf_lut(float cos_theta, float roughness, float ior, float do_multiscatter
|
|||||||
transmission_factor = bsdf.b;
|
transmission_factor = bsdf.b;
|
||||||
}
|
}
|
||||||
|
|
||||||
float reflectance = F_brdf_single_scatter(vec3(F0), vec3(F90), split_sum).r;
|
reflectance = F_brdf_single_scatter(F0, F90, split_sum);
|
||||||
float transmittance = (1.0 - F0) * transmission_factor;
|
transmittance = (vec3(1.0) - F0) * transmission_factor * transmission_tint;
|
||||||
|
|
||||||
if (do_multiscatter != 0.0) {
|
if (do_multiscatter != 0.0) {
|
||||||
float Ess = F0 * split_sum.x + split_sum.y + (1.0 - F0) * transmission_factor;
|
float real_F0 = F0_from_ior(ior);
|
||||||
/* TODO: maybe add saturation for higher roughness similar as in `F_brdf_multi_scatter()`.
|
float Ess = real_F0 * split_sum.x + split_sum.y + (1.0 - real_F0) * transmission_factor;
|
||||||
* However, it is not necessarily desirable that the users see a different color than they
|
float Ems = 1.0 - Ess;
|
||||||
* picked. */
|
/* Assume that the transmissive tint makes up most of the overall color if it's not zero. */
|
||||||
float scale = 1.0 / Ess;
|
vec3 Favg = all(equal(transmission_tint, vec3(0.0))) ? F0 + (F90 - F0) / 21.0 :
|
||||||
|
transmission_tint;
|
||||||
|
|
||||||
|
vec3 scale = 1.0 / (1.0 - Ems * Favg);
|
||||||
reflectance *= scale;
|
reflectance *= scale;
|
||||||
transmittance *= scale;
|
transmittance *= scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
return vec2(reflectance, transmittance);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Computes the reflectance and transmittance based on the BSDF LUT. */
|
||||||
|
vec2 bsdf_lut(float cos_theta, float roughness, float ior, float do_multiscatter)
|
||||||
|
{
|
||||||
|
float F0 = F0_from_ior(ior);
|
||||||
|
vec3 color = vec3(1.0);
|
||||||
|
vec3 reflectance, transmittance;
|
||||||
|
bsdf_lut(
|
||||||
|
F0, color, color, cos_theta, roughness, ior, do_multiscatter, reflectance, transmittance);
|
||||||
|
return vec2(reflectance.r, transmittance.r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
@ -43,6 +43,21 @@ vec2 bsdf_lut(float a, float b, float c, float d)
|
|||||||
return vec2(0.0);
|
return vec2(0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bsdf_lut(vec3 F0,
|
||||||
|
vec3 F90,
|
||||||
|
vec3 transmission_tint,
|
||||||
|
float cos_theta,
|
||||||
|
float roughness,
|
||||||
|
float ior,
|
||||||
|
float do_multiscatter,
|
||||||
|
out vec3 reflectance,
|
||||||
|
out vec3 transmittance)
|
||||||
|
{
|
||||||
|
reflectance = vec3(0.0);
|
||||||
|
transmittance = vec3(0.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
vec2 brdf_lut(float a, float b)
|
vec2 brdf_lut(float a, float b)
|
||||||
{
|
{
|
||||||
return vec2(0.0);
|
return vec2(0.0);
|
||||||
|
@ -323,26 +323,37 @@ vec3 lut_coords_btdf(float cos_theta, float roughness, float ior)
|
|||||||
return vec3(sqrt((ior - 1.0) / (ior + 1.0)), sqrt(1.0 - cos_theta), roughness);
|
return vec3(sqrt((ior - 1.0) / (ior + 1.0)), sqrt(1.0 - cos_theta), roughness);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Computes the reflectance and transmittance based on the BSDF LUT. */
|
/* Computes the reflectance and transmittance based on the tint (`f0`, `f90`, `transmission_tint`)
|
||||||
vec2 bsdf_lut(float cos_theta, float roughness, float ior, float do_multiscatter)
|
* and the BSDF LUT. */
|
||||||
|
void bsdf_lut(vec3 F0,
|
||||||
|
vec3 F90,
|
||||||
|
vec3 transmission_tint,
|
||||||
|
float cos_theta,
|
||||||
|
float roughness,
|
||||||
|
float ior,
|
||||||
|
float do_multiscatter,
|
||||||
|
out vec3 reflectance,
|
||||||
|
out vec3 transmittance)
|
||||||
{
|
{
|
||||||
#ifdef EEVEE_UTILITY_TX
|
#ifdef EEVEE_UTILITY_TX
|
||||||
if (ior == 1.0) {
|
if (ior == 1.0) {
|
||||||
return vec2(0.0, 1.0);
|
reflectance = vec3(0.0);
|
||||||
|
transmittance = transmission_tint;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 split_sum;
|
vec2 split_sum;
|
||||||
float transmission_factor;
|
float transmission_factor;
|
||||||
float F0 = F0_from_ior(ior);
|
|
||||||
float F90 = 1.0;
|
|
||||||
|
|
||||||
if (ior >= 1.0) {
|
if (ior > 1.0) {
|
||||||
split_sum = brdf_lut(cos_theta, roughness);
|
split_sum = brdf_lut(cos_theta, roughness);
|
||||||
vec3 coords = lut_coords_btdf(cos_theta, roughness, ior);
|
vec3 coords = lut_coords_btdf(cos_theta, roughness, ior);
|
||||||
transmission_factor = utility_tx_sample_bsdf_lut(utility_tx, coords.xy, coords.z).a;
|
transmission_factor = utility_tx_sample_bsdf_lut(utility_tx, coords.xy, coords.z).a;
|
||||||
/* Gradually increase `f90` from 0 to 1 when IOR is in the range of [1.0, 1.33], to avoid harsh
|
/* Gradually increase `f90` from 0 to 1 when IOR is in the range of [1.0, 1.33], to avoid harsh
|
||||||
* transition at `IOR == 1`. */
|
* transition at `IOR == 1`. */
|
||||||
F90 = saturate(2.33 / 0.33 * (ior - 1.0) / (ior + 1.0));
|
if (all(equal(F90, vec3(1.0)))) {
|
||||||
|
F90 = vec3(saturate(2.33 / 0.33 * (ior - 1.0) / (ior + 1.0)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
vec3 coords = lut_coords_bsdf(cos_theta, roughness, ior);
|
vec3 coords = lut_coords_bsdf(cos_theta, roughness, ior);
|
||||||
@ -351,23 +362,37 @@ vec2 bsdf_lut(float cos_theta, float roughness, float ior, float do_multiscatter
|
|||||||
transmission_factor = bsdf.b;
|
transmission_factor = bsdf.b;
|
||||||
}
|
}
|
||||||
|
|
||||||
float reflectance = F_brdf_single_scatter(vec3(F0), vec3(F90), split_sum).r;
|
reflectance = F_brdf_single_scatter(F0, F90, split_sum);
|
||||||
float transmittance = (1.0 - F0) * transmission_factor;
|
transmittance = (vec3(1.0) - F0) * transmission_factor * transmission_tint;
|
||||||
|
|
||||||
if (do_multiscatter != 0.0) {
|
if (do_multiscatter != 0.0) {
|
||||||
float Ess = F0 * split_sum.x + split_sum.y + (1.0 - F0) * transmission_factor;
|
float real_F0 = F0_from_ior(ior);
|
||||||
/* TODO: maybe add saturation for higher roughness similar as in `F_brdf_multi_scatter()`.
|
float Ess = real_F0 * split_sum.x + split_sum.y + (1.0 - real_F0) * transmission_factor;
|
||||||
* However, it is not necessarily desirable that the users see a different color than they
|
float Ems = 1.0 - Ess;
|
||||||
* picked. */
|
/* Assume that the transmissive tint makes up most of the overall color if it's not zero. */
|
||||||
float scale = 1.0 / Ess;
|
vec3 Favg = all(equal(transmission_tint, vec3(0.0))) ? F0 + (F90 - F0) / 21.0 :
|
||||||
|
transmission_tint;
|
||||||
|
|
||||||
|
vec3 scale = 1.0 / (1.0 - Ems * Favg);
|
||||||
reflectance *= scale;
|
reflectance *= scale;
|
||||||
transmittance *= scale;
|
transmittance *= scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
return vec2(reflectance, transmittance);
|
|
||||||
#else
|
#else
|
||||||
return vec2(0.0);
|
reflectance = vec3(0.0);
|
||||||
|
transmittance = vec3(0.0);
|
||||||
#endif
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Computes the reflectance and transmittance based on the BSDF LUT. */
|
||||||
|
vec2 bsdf_lut(float cos_theta, float roughness, float ior, float do_multiscatter)
|
||||||
|
{
|
||||||
|
float F0 = F0_from_ior(ior);
|
||||||
|
vec3 color = vec3(1.0);
|
||||||
|
vec3 reflectance, transmittance;
|
||||||
|
bsdf_lut(
|
||||||
|
F0, color, color, cos_theta, roughness, ior, do_multiscatter, reflectance, transmittance);
|
||||||
|
return vec2(reflectance.r, transmittance.r);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef EEVEE_MATERIAL_STUBS
|
#ifdef EEVEE_MATERIAL_STUBS
|
||||||
|
@ -33,7 +33,7 @@ void node_bsdf_principled(vec4 base_color,
|
|||||||
float subsurface_anisotropy,
|
float subsurface_anisotropy,
|
||||||
vec4 metallic_tint,
|
vec4 metallic_tint,
|
||||||
float specular,
|
float specular,
|
||||||
float specular_tint,
|
vec4 specular_tint,
|
||||||
float anisotropic,
|
float anisotropic,
|
||||||
float anisotropic_rotation,
|
float anisotropic_rotation,
|
||||||
vec3 T,
|
vec3 T,
|
||||||
@ -110,10 +110,11 @@ void node_bsdf_principled(vec4 base_color,
|
|||||||
ClosureReflection reflection_data;
|
ClosureReflection reflection_data;
|
||||||
reflection_data.N = N;
|
reflection_data.N = N;
|
||||||
reflection_data.roughness = roughness;
|
reflection_data.roughness = roughness;
|
||||||
vec2 split_sum = brdf_lut(NV, roughness);
|
|
||||||
if (true) {
|
if (true) {
|
||||||
vec3 f0 = base_color.rgb;
|
vec3 f0 = base_color.rgb;
|
||||||
vec3 f90 = vec3(1.0);
|
vec3 f90 = vec3(1.0);
|
||||||
|
vec2 split_sum = brdf_lut(NV, roughness);
|
||||||
vec3 metallic_brdf = (do_multiscatter != 0.0) ? F_brdf_multi_scatter(f0, f90, split_sum) :
|
vec3 metallic_brdf = (do_multiscatter != 0.0) ? F_brdf_multi_scatter(f0, f90, split_sum) :
|
||||||
F_brdf_single_scatter(f0, f90, split_sum);
|
F_brdf_single_scatter(f0, f90, split_sum);
|
||||||
reflection_data.color = weight * metallic * metallic_brdf;
|
reflection_data.color = weight * metallic * metallic_brdf;
|
||||||
@ -123,15 +124,18 @@ void node_bsdf_principled(vec4 base_color,
|
|||||||
|
|
||||||
/* Transmission component */
|
/* Transmission component */
|
||||||
ClosureRefraction refraction_data;
|
ClosureRefraction refraction_data;
|
||||||
/* TODO: change `specular_tint` to rgb. */
|
vec3 reflection_tint = specular_tint.rgb;
|
||||||
vec3 reflection_tint = mix(vec3(1.0), base_color.rgb, specular_tint);
|
|
||||||
if (true) {
|
if (true) {
|
||||||
vec2 bsdf = bsdf_lut(NV, roughness, ior, do_multiscatter);
|
vec3 F0 = vec3(F0_from_ior(ior)) * reflection_tint;
|
||||||
|
vec3 F90 = vec3(1.0);
|
||||||
|
vec3 reflectance, transmittance;
|
||||||
|
bsdf_lut(
|
||||||
|
F0, F90, base_color.rgb, NV, roughness, ior, do_multiscatter, reflectance, transmittance);
|
||||||
|
|
||||||
reflection_data.color += weight * transmission * bsdf.x * reflection_tint;
|
reflection_data.color += weight * transmission * reflectance;
|
||||||
|
|
||||||
refraction_data.weight = weight * transmission * bsdf.y;
|
refraction_data.weight = weight * transmission;
|
||||||
refraction_data.color = base_color.rgb * coat_tint.rgb;
|
refraction_data.color = transmittance * coat_tint.rgb;
|
||||||
refraction_data.N = N;
|
refraction_data.N = N;
|
||||||
refraction_data.roughness = roughness;
|
refraction_data.roughness = roughness;
|
||||||
refraction_data.ior = ior;
|
refraction_data.ior = ior;
|
||||||
@ -141,17 +145,15 @@ void node_bsdf_principled(vec4 base_color,
|
|||||||
|
|
||||||
/* Specular component */
|
/* Specular component */
|
||||||
if (true) {
|
if (true) {
|
||||||
vec3 f0 = vec3(F0_from_ior(ior));
|
vec3 F0 = vec3(F0_from_ior(ior)) * 2.0 * specular * reflection_tint;
|
||||||
/* Gradually increase `f90` from 0 to 1 when IOR is in the range of [1.0, 1.33], to avoid harsh
|
F0 = clamp(F0, vec3(0.0), vec3(1.0));
|
||||||
* transition at `IOR == 1`. */
|
vec3 F90 = vec3(1.0);
|
||||||
vec3 f90 = sqrt(saturate(f0 / 0.02));
|
vec3 reflectance, unused;
|
||||||
f0 *= 2.0 * specular * reflection_tint;
|
bsdf_lut(F0, F90, vec3(0.0), NV, roughness, ior, do_multiscatter, reflectance, unused);
|
||||||
|
|
||||||
vec3 specular_brdf = (do_multiscatter != 0.0) ? F_brdf_multi_scatter(f0, f90, split_sum) :
|
reflection_data.color += weight * reflectance;
|
||||||
F_brdf_single_scatter(f0, f90, split_sum);
|
|
||||||
reflection_data.color += weight * specular_brdf;
|
|
||||||
/* Attenuate lower layers */
|
/* Attenuate lower layers */
|
||||||
weight *= (1.0 - max_v3(specular_brdf));
|
weight *= (1.0 - max_v3(reflectance));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Diffuse component */
|
/* Diffuse component */
|
||||||
|
@ -112,11 +112,10 @@ static void node_declare(NodeDeclarationBuilder &b)
|
|||||||
.max(1.0f)
|
.max(1.0f)
|
||||||
.subtype(PROP_FACTOR);
|
.subtype(PROP_FACTOR);
|
||||||
#define SOCK_SPECULAR_ID 14
|
#define SOCK_SPECULAR_ID 14
|
||||||
spec.add_input<decl::Float>("Specular Tint")
|
spec.add_input<decl::Color>("Specular Tint")
|
||||||
.default_value(0.0f)
|
.default_value({1.0f, 1.0f, 1.0f, 1.0f})
|
||||||
.min(0.0f)
|
.description(
|
||||||
.max(1.0f)
|
"Tint of the specular reflection at normal incidence. Affects dielectric materials");
|
||||||
.subtype(PROP_FACTOR);
|
|
||||||
#define SOCK_SPECULAR_TINT_ID 15
|
#define SOCK_SPECULAR_TINT_ID 15
|
||||||
spec.add_input<decl::Float>("Anisotropic")
|
spec.add_input<decl::Float>("Anisotropic")
|
||||||
.default_value(0.0f)
|
.default_value(0.0f)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user