Cycles: Rework Principled BSDF Emission #111155
|
@ -28,6 +28,9 @@ shader node_principled_bsdf(string distribution = "multi_ggx",
|
|||
color CoatTint = color(1.0, 1.0, 1.0),
|
||||
float IOR = 1.45,
|
||||
float Transmission = 0.0,
|
||||
color Emission = 1.0,
|
||||
float EmissionStrength = 0.0,
|
||||
float Alpha = 1.0,
|
||||
normal Normal = N,
|
||||
normal CoatNormal = N,
|
||||
normal Tangent = normalize(dPdu),
|
||||
|
@ -99,6 +102,10 @@ shader node_principled_bsdf(string distribution = "multi_ggx",
|
|||
BSDF = mix(BSDF, MetallicBSDF, clamp(Metallic, 0.0, 1.0));
|
||||
}
|
||||
|
||||
if (EmissionStrength > 0.0 && Emission != color(0.0)) {
|
||||
BSDF += EmissionStrength * Emission * emission();
|
||||
}
|
||||
|
||||
if (Coat > 1e-5) {
|
||||
float coat_ior = max(CoatIOR, 1.0);
|
||||
if (CoatTint != color(1.0)) {
|
||||
|
@ -117,4 +124,6 @@ shader node_principled_bsdf(string distribution = "multi_ggx",
|
|||
closure color SheenBSDF = sheen(Normal, SheenRoughness);
|
||||
BSDF = layer(SheenTint * Sheen * SheenBSDF, BSDF);
|
||||
}
|
||||
|
||||
BSDF = mix(transparent(), BSDF, Alpha);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ ccl_device_inline int svm_node_closure_bsdf_skip(KernelGlobals kg, int offset, u
|
|||
read_node(kg, &offset);
|
||||
read_node(kg, &offset);
|
||||
read_node(kg, &offset);
|
||||
read_node(kg, &offset);
|
||||
}
|
||||
|
||||
return offset;
|
||||
|
@ -53,6 +54,12 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
return svm_node_closure_bsdf_skip(kg, offset, type);
|
||||
}
|
||||
}
|
||||
else IF_KERNEL_NODES_FEATURE(EMISSION) {
|
||||
if (type != CLOSURE_BSDF_PRINCIPLED_ID) {
|
||||
/* Only principled BSDF can have emission. */
|
||||
return svm_node_closure_bsdf_skip(kg, offset, type);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return svm_node_closure_bsdf_skip(kg, offset, type);
|
||||
}
|
||||
|
@ -70,7 +77,8 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
uint specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset,
|
||||
sheen_offset, sheen_tint_offset, sheen_roughness_offset, coat_offset,
|
||||
coat_roughness_offset, coat_ior_offset, eta_offset, transmission_offset,
|
||||
anisotropic_rotation_offset, coat_tint_offset, coat_normal_offset, dummy;
|
||||
anisotropic_rotation_offset, coat_tint_offset, coat_normal_offset, dummy,
|
||||
alpha_offset, emission_strength_offset, emission_offset;
|
||||
uint4 data_node2 = read_node(kg, &offset);
|
||||
|
||||
float3 T = stack_load_float3(stack, data_node.y);
|
||||
|
@ -129,6 +137,20 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
sd->N;
|
||||
coat_normal = maybe_ensure_valid_specular_reflection(sd, coat_normal);
|
||||
|
||||
uint4 data_alpha_emission = read_node(kg, &offset);
|
||||
svm_unpack_node_uchar4(data_alpha_emission.x,
|
||||
&alpha_offset,
|
||||
&emission_strength_offset,
|
||||
&emission_offset,
|
||||
&dummy);
|
||||
float alpha = stack_valid(alpha_offset) ? stack_load_float(stack, alpha_offset) :
|
||||
__uint_as_float(data_alpha_emission.y);
|
||||
float3 emission = stack_load_float3(stack, emission_offset);
|
||||
/* Emission strength */
|
||||
emission *= stack_valid(emission_strength_offset) ?
|
||||
stack_load_float(stack, emission_strength_offset) :
|
||||
__uint_as_float(data_alpha_emission.z);
|
||||
|
||||
Spectrum weight = closure_weight * mix_weight;
|
||||
|
||||
float alpha_x = sqr(roughness), alpha_y = sqr(roughness);
|
||||
|
@ -151,6 +173,12 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
const bool glass_caustics = true;
|
||||
#endif
|
||||
|
||||
/* Before any actual shader components, apply transparency. */
|
||||
if (alpha < 1.0f) {
|
||||
bsdf_transparent_setup(sd, weight * (1.0f - alpha), path_flag);
|
||||
weight *= alpha;
|
||||
}
|
||||
|
||||
/* First layer: Sheen */
|
||||
if (sheen > CLOSURE_WEIGHT_CUTOFF) {
|
||||
ccl_private SheenBsdf *bsdf = (ccl_private SheenBsdf *)bsdf_alloc(
|
||||
|
@ -217,6 +245,11 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
weight *= power(rgb_to_spectrum(coat_tint), coat * optical_depth);
|
||||
}
|
||||
|
||||
/* Emission (attenuated by sheen and coat) */
|
||||
if (!is_zero(emission)) {
|
||||
emission_setup(sd, rgb_to_spectrum(emission) * weight);
|
||||
}
|
||||
|
||||
/* Metallic component */
|
||||
if (reflective_caustics && metallic > CLOSURE_WEIGHT_CUTOFF) {
|
||||
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
|
||||
|
|
|
@ -133,11 +133,18 @@ static float3 output_estimate_emission(ShaderOutput *output, bool &is_constant)
|
|||
return zero_float3();
|
||||
}
|
||||
else if (node->type == EmissionNode::get_node_type() ||
|
||||
node->type == BackgroundNode::get_node_type())
|
||||
node->type == BackgroundNode::get_node_type() ||
|
||||
node->type == PrincipledBsdfNode::get_node_type())
|
||||
{
|
||||
const bool is_principled = (node->type == PrincipledBsdfNode::get_node_type());
|
||||
/* Emission and Background node. */
|
||||
ShaderInput *color_in = node->input("Color");
|
||||
ShaderInput *strength_in = node->input("Strength");
|
||||
ShaderInput *color_in = node->input(is_principled ? "Emission" : "Color");
|
||||
ShaderInput *strength_in = node->input(is_principled ? "Emission Strength" : "Strength");
|
||||
|
||||
if (is_principled) {
|
||||
/* Too many parameters (coat, sheen, alpha) influence Emission for the Principled BSDF. */
|
||||
is_constant = false;
|
||||
}
|
||||
|
||||
float3 estimate = one_float3();
|
||||
|
||||
|
|
|
@ -2681,8 +2681,8 @@ NODE_DEFINE(PrincipledBsdfNode)
|
|||
SOCKET_IN_FLOAT(ior, "IOR", 0.0f);
|
||||
SOCKET_IN_FLOAT(transmission, "Transmission", 0.0f);
|
||||
SOCKET_IN_FLOAT(anisotropic_rotation, "Anisotropic Rotation", 0.0f);
|
||||
SOCKET_IN_COLOR(emission, "Emission", zero_float3());
|
||||
SOCKET_IN_FLOAT(emission_strength, "Emission Strength", 1.0f);
|
||||
SOCKET_IN_COLOR(emission, "Emission", one_float3());
|
||||
SOCKET_IN_FLOAT(emission_strength, "Emission Strength", 0.0f);
|
||||
SOCKET_IN_FLOAT(alpha, "Alpha", 1.0f);
|
||||
SOCKET_IN_NORMAL(normal, "Normal", zero_float3(), SocketType::LINK_NORMAL);
|
||||
SOCKET_IN_NORMAL(coat_normal, "Coat Normal", zero_float3(), SocketType::LINK_NORMAL);
|
||||
|
@ -2700,60 +2700,33 @@ PrincipledBsdfNode::PrincipledBsdfNode() : BsdfBaseNode(get_node_type())
|
|||
distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
|
||||
}
|
||||
|
||||
void PrincipledBsdfNode::expand(ShaderGraph *graph)
|
||||
void PrincipledBsdfNode::simplify_settings(Scene * /* scene */)
|
||||
{
|
||||
ShaderOutput *principled_out = output("BSDF");
|
||||
|
||||
ShaderInput *emission_in = input("Emission");
|
||||
ShaderInput *emission_strength_in = input("Emission Strength");
|
||||
if ((emission_in->link || emission != zero_float3()) &&
|
||||
(emission_strength_in->link || emission_strength != 0.0f))
|
||||
{
|
||||
/* Create add closure and emission, and relink inputs. */
|
||||
AddClosureNode *add = graph->create_node<AddClosureNode>();
|
||||
EmissionNode *emission_node = graph->create_node<EmissionNode>();
|
||||
ShaderOutput *new_out = add->output("Closure");
|
||||
|
||||
graph->add(add);
|
||||
graph->add(emission_node);
|
||||
|
||||
graph->relink(emission_strength_in, emission_node->input("Strength"));
|
||||
graph->relink(emission_in, emission_node->input("Color"));
|
||||
graph->relink(principled_out, new_out);
|
||||
graph->connect(emission_node->output("Emission"), add->input("Closure1"));
|
||||
graph->connect(principled_out, add->input("Closure2"));
|
||||
|
||||
principled_out = new_out;
|
||||
}
|
||||
else {
|
||||
/* Disconnect unused links if the other value is zero, required before
|
||||
* we remove the input from the node entirely. */
|
||||
if (!has_surface_emission()) {
|
||||
/* Emission will be zero, so optimize away any connected emission input. */
|
||||
ShaderInput *emission_in = input("Emission");
|
||||
ShaderInput *strength_in = input("Emission Strength");
|
||||
if (emission_in->link) {
|
||||
emission_in->disconnect();
|
||||
}
|
||||
if (emission_strength_in->link) {
|
||||
emission_strength_in->disconnect();
|
||||
if (strength_in->link) {
|
||||
strength_in->disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PrincipledBsdfNode::has_surface_transparent()
|
||||
{
|
||||
ShaderInput *alpha_in = input("Alpha");
|
||||
if (alpha_in->link || alpha != 1.0f) {
|
||||
/* Create mix and transparent BSDF for alpha transparency. */
|
||||
MixClosureNode *mix = graph->create_node<MixClosureNode>();
|
||||
TransparentBsdfNode *transparent = graph->create_node<TransparentBsdfNode>();
|
||||
return (alpha_in->link != NULL || alpha < (1.0f - CLOSURE_WEIGHT_CUTOFF));
|
||||
}
|
||||
|
||||
graph->add(mix);
|
||||
graph->add(transparent);
|
||||
|
||||
graph->relink(alpha_in, mix->input("Fac"));
|
||||
graph->relink(principled_out, mix->output("Closure"));
|
||||
graph->connect(transparent->output("BSDF"), mix->input("Closure1"));
|
||||
graph->connect(principled_out, mix->input("Closure2"));
|
||||
}
|
||||
|
||||
remove_input(emission_in);
|
||||
remove_input(emission_strength_in);
|
||||
remove_input(alpha_in);
|
||||
bool PrincipledBsdfNode::has_surface_emission()
|
||||
{
|
||||
ShaderInput *emission_in = input("Emission");
|
||||
ShaderInput *emission_strength_in = input("Emission Strength");
|
||||
return (emission_in->link != NULL || reduce_max(emission) > CLOSURE_WEIGHT_CUTOFF) &&
|
||||
(emission_strength_in->link != NULL || emission_strength > CLOSURE_WEIGHT_CUTOFF);
|
||||
}
|
||||
|
||||
bool PrincipledBsdfNode::has_surface_bssrdf()
|
||||
|
@ -2781,6 +2754,9 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler)
|
|||
ShaderInput *p_metallic = input("Metallic");
|
||||
ShaderInput *p_subsurface = input("Subsurface");
|
||||
|
||||
ShaderInput *emission_strength_in = input("Emission Strength");
|
||||
ShaderInput *alpha_in = input("Alpha");
|
||||
|
||||
float3 weight = one_float3();
|
||||
|
||||
compiler.add_node(NODE_CLOSURE_SET_WEIGHT, weight);
|
||||
|
@ -2806,6 +2782,9 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler)
|
|||
int subsurface_scale_offset = compiler.stack_assign(input("Subsurface Scale"));
|
||||
int subsurface_ior_offset = compiler.stack_assign(input("Subsurface IOR"));
|
||||
int subsurface_anisotropy_offset = compiler.stack_assign(input("Subsurface Anisotropy"));
|
||||
int alpha_offset = compiler.stack_assign_if_linked(alpha_in);
|
||||
int emission_strength_offset = compiler.stack_assign_if_linked(emission_strength_in);
|
||||
int emission_offset = compiler.stack_assign(input("Emission"));
|
||||
|
||||
compiler.add_node(NODE_CLOSURE_BSDF,
|
||||
compiler.encode_uchar4(closure,
|
||||
|
@ -2843,6 +2822,13 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler)
|
|||
subsurface_radius_offset,
|
||||
subsurface_scale_offset,
|
||||
subsurface_anisotropy_offset);
|
||||
|
||||
compiler.add_node(
|
||||
compiler.encode_uchar4(
|
||||
alpha_offset, emission_strength_offset, emission_offset, SVM_STACK_INVALID),
|
||||
__float_as_int(get_float(alpha_in->socket_type)),
|
||||
__float_as_int(get_float(emission_strength_in->socket_type)),
|
||||
SVM_STACK_INVALID);
|
||||
}
|
||||
|
||||
void PrincipledBsdfNode::compile(OSLCompiler &compiler)
|
||||
|
|
|
@ -514,9 +514,9 @@ class PrincipledBsdfNode : public BsdfBaseNode {
|
|||
public:
|
||||
SHADER_NODE_CLASS(PrincipledBsdfNode)
|
||||
|
||||
void expand(ShaderGraph *graph);
|
||||
bool has_surface_bssrdf();
|
||||
bool has_bssrdf_bump();
|
||||
void simplify_settings(Scene *scene);
|
||||
|
||||
NODE_SOCKET_API(float3, base_color)
|
||||
NODE_SOCKET_API(float3, subsurface_radius)
|
||||
|
@ -555,6 +555,8 @@ class PrincipledBsdfNode : public BsdfBaseNode {
|
|||
{
|
||||
return true;
|
||||
}
|
||||
bool has_surface_transparent();
|
||||
bool has_surface_emission();
|
||||
};
|
||||
|
||||
class TranslucentBsdfNode : public BsdfNode {
|
||||
|
|
|
@ -660,6 +660,33 @@ static void version_principled_bsdf_subsurface(bNodeTree *ntree)
|
|||
}
|
||||
}
|
||||
|
||||
/* Convert emission inputs on the Principled BSDF. */
|
||||
static void version_principled_bsdf_emission(bNodeTree *ntree)
|
||||
{
|
||||
/* Blender 3.x and before would default to Emission = 0.0, Emission Strength = 1.0.
|
||||
* Now we default the other way around (1.0 and 0.0), but because the Strength input was added
|
||||
* a bit later, a file that only has the Emission socket would now end up as (1.0, 0.0) instead
|
||||
* of (1.0, 1.0).
|
||||
* Therefore, set strength to 1.0 for those files.
|
||||
*/
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
if (node->type != SH_NODE_BSDF_PRINCIPLED) {
|
||||
continue;
|
||||
}
|
||||
if (!nodeFindSocket(node, SOCK_IN, "Emission")) {
|
||||
/* Old enough to have neither, new defaults are fine. */
|
||||
continue;
|
||||
}
|
||||
if (nodeFindSocket(node, SOCK_IN, "Emission Strength")) {
|
||||
/* New enough to have both, no need to do anything. */
|
||||
continue;
|
||||
}
|
||||
bNodeSocket *sock = nodeAddStaticSocket(
|
||||
ntree, node, SOCK_IN, SOCK_FLOAT, PROP_NONE, "Emission Strength", "Emission Strength");
|
||||
*version_cycles_node_socket_float_value(sock) = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/* Replace old Principled Hair BSDF as a variant in the new Principled Hair BSDF. */
|
||||
static void version_replace_principled_hair_model(bNodeTree *ntree)
|
||||
{
|
||||
|
@ -1178,6 +1205,8 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
version_principled_bsdf_coat(ntree);
|
||||
/* Convert subsurface inputs on the Principled BSDF. */
|
||||
version_principled_bsdf_subsurface(ntree);
|
||||
/* Convert emission on the Principled BSDF. */
|
||||
version_principled_bsdf_emission(ntree);
|
||||
}
|
||||
}
|
||||
FOREACH_NODETREE_END;
|
||||
|
|
|
@ -608,9 +608,12 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
|
|||
for (bNode *node : ma->nodetree->all_nodes()) {
|
||||
if (node->type == SH_NODE_BSDF_PRINCIPLED) {
|
||||
bNodeSocket *roughness_socket = nodeFindSocket(node, SOCK_IN, "Roughness");
|
||||
bNodeSocketValueFloat *roughness_data = static_cast<bNodeSocketValueFloat *>(
|
||||
roughness_socket->default_value);
|
||||
roughness_data->value = 0.5f;
|
||||
*version_cycles_node_socket_float_value(roughness_socket) = 0.5f;
|
||||
bNodeSocket *emission = nodeFindSocket(node, SOCK_IN, "Emission");
|
||||
copy_v4_fl(version_cycles_node_socket_rgba_value(emission), 1.0f);
|
||||
bNodeSocket *emission_strength = nodeFindSocket(node, SOCK_IN, "Emission Strength");
|
||||
*version_cycles_node_socket_float_value(emission_strength) = 0.0f;
|
||||
|
||||
node->custom1 = SHD_GLOSSY_MULTI_GGX;
|
||||
node->custom2 = SHD_SUBSURFACE_RANDOM_WALK;
|
||||
BKE_ntree_update_tag_node_property(ma->nodetree, node);
|
||||
|
|
|
@ -143,9 +143,9 @@ static void node_declare(NodeDeclarationBuilder &b)
|
|||
.max(1.0f)
|
||||
.subtype(PROP_FACTOR);
|
||||
#define SOCK_TRANSMISSION_ID 20
|
||||
b.add_input<decl::Color>("Emission").default_value({0.0f, 0.0f, 0.0f, 1.0f});
|
||||
b.add_input<decl::Color>("Emission").default_value({1.0f, 1.0f, 1.0f, 1.0f});
|
||||
#define SOCK_EMISSION_ID 21
|
||||
b.add_input<decl::Float>("Emission Strength").default_value(1.0).min(0.0f).max(1000000.0f);
|
||||
b.add_input<decl::Float>("Emission Strength").default_value(0.0).min(0.0f).max(1000000.0f);
|
||||
#define SOCK_EMISSION_STRENGTH_ID 22
|
||||
b.add_input<decl::Float>("Alpha").default_value(1.0f).min(0.0f).max(1.0f).subtype(PROP_FACTOR);
|
||||
#define SOCK_ALPHA_ID 23
|
||||
|
|
Loading…
Reference in New Issue