WIP: Shader: Add Artistic Conductor Fresnel type to Metallic BSDF #126871
@ -565,6 +565,9 @@ static ShaderNode *add_node(Scene *scene,
|
||||
}
|
||||
|
||||
switch (b_metallic_node.fresnel_type()) {
|
||||
case BL::ShaderNodeBsdfMetallic::fresnel_type_ARTISTIC_CONDUCTOR:
|
||||
metal->set_fresnel_type(CLOSURE_BSDF_ARTISTIC_CONDUCTOR);
|
||||
break;
|
||||
case BL::ShaderNodeBsdfMetallic::fresnel_type_PHYSICAL_CONDUCTOR:
|
||||
metal->set_fresnel_type(CLOSURE_BSDF_PHYSICAL_CONDUCTOR);
|
||||
break;
|
||||
|
@ -103,6 +103,42 @@ ccl_device Spectrum fresnel_conductor(float cosi, const Spectrum eta, const Spec
|
||||
return (Rparl2 + Rperp2) * 0.5f;
|
||||
}
|
||||
|
||||
/* Equations to map color to complex IOR, from "Artist Friendly Metallic Fresnel",
|
||||
* Ole Gulbrandsen,2014 https://jcgt.org/published/0003/04/03/paper.pdf */
|
||||
ccl_device float3 conductor_ior_from_color(float3 r, const float3 edge_tint)
|
||||
{
|
||||
r = clamp(r, zero_float3(), make_float3(0.99f));
|
||||
const float3 r_sqrt = sqrt(r);
|
||||
const float3 one = one_float3();
|
||||
|
||||
const float3 n_min = (one - r) / (one + r);
|
||||
const float3 n_max = (one + r_sqrt) / (one - r_sqrt);
|
||||
|
||||
return mix(n_max, n_min, edge_tint);
|
||||
}
|
||||
|
||||
ccl_device float3 conductor_extinction_from_color(float3 r, const float3 eta)
|
||||
{
|
||||
r = clamp(r, zero_float3(), make_float3(0.99f));
|
||||
const float3 one = one_float3();
|
||||
|
||||
const float3 np1 = eta + one;
|
||||
const float3 nm1 = eta - one;
|
||||
float3 k2 = ((r * np1 * np1) - (nm1 * nm1)) / (one - r);
|
||||
k2 = max(k2, zero_float3());
|
||||
|
||||
return sqrt(k2);
|
||||
}
|
||||
|
||||
ccl_device void complex_ior_from_base_edge(const float3 reflectivity,
|
||||
const float3 edge_tint,
|
||||
ccl_private float3 *eta,
|
||||
ccl_private float3 *k)
|
||||
{
|
||||
*eta = conductor_ior_from_color(reflectivity, edge_tint);
|
||||
*k = conductor_extinction_from_color(reflectivity, *eta);
|
||||
}
|
||||
|
||||
ccl_device float ior_from_F0(float f0)
|
||||
{
|
||||
const float sqrt_f0 = sqrtf(clamp(f0, 0.0f, 0.99f));
|
||||
|
@ -37,6 +37,32 @@ color fresnel_conductor(float cosi, color eta, color k)
|
||||
return (Rparl2 + Rperp2) * 0.5;
|
||||
}
|
||||
|
||||
/* Equations to map color to complex IOR, from "Artist Friendly Metallic Fresnel",
|
||||
* Ole Gulbrandsen,2014 https://jcgt.org/published/0003/04/03/paper.pdf */
|
||||
vector conductor_ior_from_color(color reflectivity, color edge_tint)
|
||||
{
|
||||
vector r = clamp(reflectivity, 0.0, 0.99);
|
||||
vector r_sqrt = sqrt(r);
|
||||
vector one = 1.0;
|
||||
|
||||
vector n_min = (one - r) / (one + r);
|
||||
vector n_max = (one + r_sqrt) / (one - r_sqrt);
|
||||
|
||||
return mix(n_max, n_min, edge_tint);
|
||||
}
|
||||
|
||||
vector conductor_extinction_from_color(color reflectivity, vector n)
|
||||
{
|
||||
vector r = clamp(reflectivity, 0.0, 0.99);
|
||||
|
||||
vector np1 = n + 1.0;
|
||||
vector nm1 = n - 1.0;
|
||||
vector k2 = ((r * np1 * np1) - (nm1 * nm1)) / (1.0 - r);
|
||||
k2 = max(k2, 0.0);
|
||||
|
||||
return sqrt(k2);
|
||||
}
|
||||
|
||||
float F0_from_ior(float eta)
|
||||
{
|
||||
float f0 = (eta - 1.0) / (eta + 1.0);
|
||||
|
@ -32,13 +32,23 @@ shader node_metallic_bsdf(color BaseColor = color(0.617, 0.577, 0.540),
|
||||
T = rotate(T, Rotation * M_2PI, point(0.0, 0.0, 0.0), Normal);
|
||||
}
|
||||
|
||||
color F0 = clamp(BaseColor, color(0.0), color(1.0));
|
||||
color F82 = clamp(EdgeTint, color(0.0), color(1.0));
|
||||
|
||||
if (fresnel_type == "f82") {
|
||||
color F0 = clamp(BaseColor, color(0.0), color(1.0));
|
||||
color F82 = clamp(EdgeTint, color(0.0), color(1.0));
|
||||
BSDF = microfacet_f82_tint(distribution, Normal, T, alpha_x, alpha_y, F0, F82);
|
||||
}
|
||||
else {
|
||||
BSDF = conductor_bsdf(
|
||||
Normal, T, alpha_x, alpha_y, max(IOR, 0.0), max(Extinction, 0.0), distribution);
|
||||
vector n, k;
|
||||
if (fresnel_type == "physical_conductor") {
|
||||
n = max(IOR, 0.0);
|
||||
k = max(Extinction, 0.0);
|
||||
}
|
||||
else {
|
||||
n = conductor_ior_from_color(F0, F82);
|
||||
k = conductor_extinction_from_color(F0, n);
|
||||
}
|
||||
|
||||
BSDF = conductor_bsdf(Normal, T, alpha_x, alpha_y, n, k, distribution);
|
||||
}
|
||||
}
|
||||
|
@ -480,7 +480,8 @@ ccl_device
|
||||
break;
|
||||
}
|
||||
case CLOSURE_BSDF_PHYSICAL_CONDUCTOR:
|
||||
case CLOSURE_BSDF_F82_CONDUCTOR: {
|
||||
case CLOSURE_BSDF_F82_CONDUCTOR:
|
||||
case CLOSURE_BSDF_ARTISTIC_CONDUCTOR: {
|
||||
#ifdef __CAUSTICS_TRICKS__
|
||||
if (!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
|
||||
break;
|
||||
@ -525,12 +526,20 @@ ccl_device
|
||||
|
||||
const bool is_multiggx = (distribution == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID);
|
||||
|
||||
if (type == CLOSURE_BSDF_PHYSICAL_CONDUCTOR) {
|
||||
if (type == CLOSURE_BSDF_PHYSICAL_CONDUCTOR || type == CLOSURE_BSDF_ARTISTIC_CONDUCTOR) {
|
||||
ccl_private FresnelConductor *fresnel = (ccl_private FresnelConductor *)
|
||||
closure_alloc_extra(sd, sizeof(FresnelConductor));
|
||||
|
||||
const float3 n = max(stack_load_float3(stack, base_ior_offset), zero_float3());
|
||||
const float3 k = max(stack_load_float3(stack, edge_tint_k_offset), zero_float3());
|
||||
float3 n, k;
|
||||
if (type == CLOSURE_BSDF_PHYSICAL_CONDUCTOR) {
|
||||
n = max(stack_load_float3(stack, base_ior_offset), zero_float3());
|
||||
k = max(stack_load_float3(stack, edge_tint_k_offset), zero_float3());
|
||||
}
|
||||
else {
|
||||
const float3 color = saturate(stack_load_float3(stack, base_ior_offset));
|
||||
const float3 tint = saturate(stack_load_float3(stack, edge_tint_k_offset));
|
||||
complex_ior_from_base_edge(color, tint, &n, &k);
|
||||
}
|
||||
|
||||
fresnel->n = rgb_to_spectrum(n);
|
||||
fresnel->k = rgb_to_spectrum(k);
|
||||
|
@ -432,6 +432,7 @@ typedef enum ClosureType {
|
||||
|
||||
/* Glossy */
|
||||
CLOSURE_BSDF_PHYSICAL_CONDUCTOR, /* virtual closure */
|
||||
CLOSURE_BSDF_ARTISTIC_CONDUCTOR, /* virtual closure */
|
||||
CLOSURE_BSDF_F82_CONDUCTOR, /* virtual closure */
|
||||
CLOSURE_BSDF_MICROFACET_GGX_ID,
|
||||
CLOSURE_BSDF_MICROFACET_BECKMANN_ID,
|
||||
|
@ -1199,6 +1199,7 @@ int ShaderGraph::get_num_closures()
|
||||
num_closures += MAX_VOLUME_STACK_SIZE;
|
||||
}
|
||||
else if (closure_type == CLOSURE_BSDF_PHYSICAL_CONDUCTOR ||
|
||||
closure_type == CLOSURE_BSDF_ARTISTIC_CONDUCTOR ||
|
||||
closure_type == CLOSURE_BSDF_F82_CONDUCTOR ||
|
||||
closure_type == CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID ||
|
||||
closure_type == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID ||
|
||||
|
@ -2461,6 +2461,7 @@ NODE_DEFINE(MetallicBsdfNode)
|
||||
static NodeEnum fresnel_type_enum;
|
||||
fresnel_type_enum.insert("f82", CLOSURE_BSDF_F82_CONDUCTOR);
|
||||
fresnel_type_enum.insert("physical_conductor", CLOSURE_BSDF_PHYSICAL_CONDUCTOR);
|
||||
fresnel_type_enum.insert("artist_conductor", CLOSURE_BSDF_ARTISTIC_CONDUCTOR);
|
||||
SOCKET_ENUM(fresnel_type, "fresnel_type", fresnel_type_enum, CLOSURE_BSDF_F82_CONDUCTOR);
|
||||
|
||||
SOCKET_IN_COLOR(edge_tint, "Edge Tint", make_float3(0.695f, 0.726f, 0.770f));
|
||||
|
@ -347,6 +347,11 @@ ccl_device_inline float3 mix(const float3 a, const float3 b, float t)
|
||||
return a + t * (b - a);
|
||||
}
|
||||
|
||||
ccl_device_inline float3 mix(const float3 a, const float3 b, float3 t)
|
||||
{
|
||||
return a + t * (b - a);
|
||||
}
|
||||
|
||||
ccl_device_inline float3 rcp(const float3 a)
|
||||
{
|
||||
# ifdef __KERNEL_SSE__
|
||||
|
@ -2115,6 +2115,7 @@ enum {
|
||||
enum {
|
||||
SHD_PHYSICAL_CONDUCTOR = 0,
|
||||
SHD_CONDUCTOR_F82 = 1,
|
||||
SHD_ARTISTIC_CONDUCTOR = 2,
|
||||
};
|
||||
|
||||
/* glossy distributions */
|
||||
|
@ -4134,6 +4134,11 @@ static const EnumPropertyItem node_metallic_fresnel_type_items[] = {
|
||||
0,
|
||||
"Physical Conductor",
|
||||
"Fresnel conductor based on the complex refractive index per color channel"},
|
||||
{SHD_ARTISTIC_CONDUCTOR,
|
||||
"ARTISTIC_CONDUCTOR",
|
||||
0,
|
||||
"Artistic Conductor",
|
||||
"Fresnel conductor with artist friendly color inputs"},
|
||||
{SHD_CONDUCTOR_F82,
|
||||
"F82",
|
||||
0,
|
||||
|
Loading…
Reference in New Issue
Block a user