Cycles: Merge Anisotropic BSDF node into Glossy BSDF node

Used to be https://archive.blender.org/developer/D17123.

Internally these are already using the same code path anyways, there's no point in maintaining two distinct nodes.

The obvious approach would be to add Anisotropy controls to the Glossy BSDF node and remove the Anisotropic BSDF node. However, that would break forward compability, since older Blender versions don't know how to handle the Anisotropy input on the Glossy BSDF node.

Therefore, this commit technically removes the Glossy BSDF node, uses versioning to replace them with an Anisotropic BSDF node, and renames that node to "Glossy BSDF".

That way, when you open a new file in an older version, all the nodes show up as Anisotropic BSDF nodes and render correctly.

This is a bit ugly internally since we need to preserve the old `idname` which now no longer matches the UI name, but that's not too bad.

Also removes the "Sharp" distribution option and replaces it with GGX, sets Roughness to zero and disconnects any input to the Roughness socket.

Pull Request: https://projects.blender.org/blender/blender/pulls/104445
This commit is contained in:
Lukas Stockner 2023-05-18 23:12:20 +02:00 committed by Lukas Stockner
parent 3a839cc52b
commit 8cde7d8f8a
28 changed files with 197 additions and 344 deletions

@ -523,27 +523,6 @@ static ShaderNode *add_node(Scene *scene,
else if (b_node.is_a(&RNA_ShaderNodeHoldout)) {
node = graph->create_node<HoldoutNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfAnisotropic)) {
BL::ShaderNodeBsdfAnisotropic b_aniso_node(b_node);
AnisotropicBsdfNode *aniso = graph->create_node<AnisotropicBsdfNode>();
switch (b_aniso_node.distribution()) {
case BL::ShaderNodeBsdfAnisotropic::distribution_BECKMANN:
aniso->set_distribution(CLOSURE_BSDF_MICROFACET_BECKMANN_ID);
break;
case BL::ShaderNodeBsdfAnisotropic::distribution_GGX:
aniso->set_distribution(CLOSURE_BSDF_MICROFACET_GGX_ID);
break;
case BL::ShaderNodeBsdfAnisotropic::distribution_MULTI_GGX:
aniso->set_distribution(CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID);
break;
case BL::ShaderNodeBsdfAnisotropic::distribution_ASHIKHMIN_SHIRLEY:
aniso->set_distribution(CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID);
break;
}
node = aniso;
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfDiffuse)) {
node = graph->create_node<DiffuseBsdfNode>();
}
@ -566,24 +545,21 @@ static ShaderNode *add_node(Scene *scene,
node = subsurface;
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfGlossy)) {
BL::ShaderNodeBsdfGlossy b_glossy_node(b_node);
else if (b_node.is_a(&RNA_ShaderNodeBsdfAnisotropic)) {
BL::ShaderNodeBsdfAnisotropic b_glossy_node(b_node);
GlossyBsdfNode *glossy = graph->create_node<GlossyBsdfNode>();
switch (b_glossy_node.distribution()) {
case BL::ShaderNodeBsdfGlossy::distribution_SHARP:
glossy->set_distribution(CLOSURE_BSDF_REFLECTION_ID);
break;
case BL::ShaderNodeBsdfGlossy::distribution_BECKMANN:
case BL::ShaderNodeBsdfAnisotropic::distribution_BECKMANN:
glossy->set_distribution(CLOSURE_BSDF_MICROFACET_BECKMANN_ID);
break;
case BL::ShaderNodeBsdfGlossy::distribution_GGX:
case BL::ShaderNodeBsdfAnisotropic::distribution_GGX:
glossy->set_distribution(CLOSURE_BSDF_MICROFACET_GGX_ID);
break;
case BL::ShaderNodeBsdfGlossy::distribution_ASHIKHMIN_SHIRLEY:
case BL::ShaderNodeBsdfAnisotropic::distribution_ASHIKHMIN_SHIRLEY:
glossy->set_distribution(CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID);
break;
case BL::ShaderNodeBsdfGlossy::distribution_MULTI_GGX:
case BL::ShaderNodeBsdfAnisotropic::distribution_MULTI_GGX:
glossy->set_distribution(CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID);
break;
}
@ -593,9 +569,6 @@ static ShaderNode *add_node(Scene *scene,
BL::ShaderNodeBsdfGlass b_glass_node(b_node);
GlassBsdfNode *glass = graph->create_node<GlassBsdfNode>();
switch (b_glass_node.distribution()) {
case BL::ShaderNodeBsdfGlass::distribution_SHARP:
glass->set_distribution(CLOSURE_BSDF_SHARP_GLASS_ID);
break;
case BL::ShaderNodeBsdfGlass::distribution_BECKMANN:
glass->set_distribution(CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID);
break;
@ -612,9 +585,6 @@ static ShaderNode *add_node(Scene *scene,
BL::ShaderNodeBsdfRefraction b_refraction_node(b_node);
RefractionBsdfNode *refraction = graph->create_node<RefractionBsdfNode>();
switch (b_refraction_node.distribution()) {
case BL::ShaderNodeBsdfRefraction::distribution_SHARP:
refraction->set_distribution(CLOSURE_BSDF_REFRACTION_ID);
break;
case BL::ShaderNodeBsdfRefraction::distribution_BECKMANN:
refraction->set_distribution(CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID);
break;

@ -6,7 +6,6 @@
set(SRC_OSL
node_add_closure.osl
node_ambient_occlusion.osl
node_anisotropic_bsdf.osl
node_attribute.osl
node_background.osl
node_bevel.osl

@ -1,45 +0,0 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#include "stdcycles.h"
shader node_anisotropic_bsdf(color Color = 0.0,
string distribution = "GGX",
float Roughness = 0.0,
float Anisotropy = 0.0,
float Rotation = 0.0,
normal Normal = N,
normal Tangent = normalize(dPdu),
output closure color BSDF = 0)
{
/* rotate tangent around normal */
vector T = Tangent;
if (Rotation != 0.0)
T = rotate(T, Rotation * M_2PI, point(0.0, 0.0, 0.0), Normal);
/* compute roughness */
float roughness = Roughness * Roughness;
float roughness_u, roughness_v;
float aniso = clamp(Anisotropy, -0.99, 0.99);
if (aniso < 0.0) {
roughness_u = roughness / (1.0 + aniso);
roughness_v = roughness * (1.0 + aniso);
}
else {
roughness_u = roughness * (1.0 - aniso);
roughness_v = roughness / (1.0 - aniso);
}
if (distribution == "sharp")
BSDF = Color * reflection(Normal);
else if (distribution == "beckmann")
BSDF = Color * microfacet_beckmann_aniso(Normal, T, roughness_u, roughness_v);
else if (distribution == "GGX")
BSDF = Color * microfacet_ggx_aniso(Normal, T, roughness_u, roughness_v);
else if (distribution == "Multiscatter GGX")
BSDF = Color * microfacet_multi_ggx_aniso(Normal, T, roughness_u, roughness_v, Color);
else
BSDF = Color * ashikhmin_shirley(Normal, T, roughness_u, roughness_v);
}

@ -7,13 +7,40 @@
shader node_glossy_bsdf(color Color = 0.8,
string distribution = "ggx",
float Roughness = 0.2,
float Anisotropy = 0.0,
float Rotation = 0.0,
normal Normal = N,
normal Tangent = 0.0,
output closure color BSDF = 0)
{
/* compute roughness */
float roughness = Roughness * Roughness;
float roughness_u, roughness_v;
float aniso = clamp(Anisotropy, -0.99, 0.99);
/* rotate tangent around normal */
vector T = Tangent;
if (abs(aniso) <= 1e-4) {
roughness_u = roughness;
roughness_v = roughness;
}
else {
if (Rotation != 0.0)
T = rotate(T, Rotation * M_2PI, point(0.0, 0.0, 0.0), Normal);
if (aniso < 0.0) {
roughness_u = roughness / (1.0 + aniso);
roughness_v = roughness * (1.0 + aniso);
}
else {
roughness_u = roughness * (1.0 - aniso);
roughness_v = roughness / (1.0 - aniso);
}
}
if (distribution == "Multiscatter GGX")
BSDF = Color * microfacet_multi_ggx(Normal, roughness, Color);
else
BSDF = Color * microfacet(distribution, Normal, roughness, 0.0, 0);
BSDF = Color * microfacet(distribution, Normal, T, roughness_u, roughness_v, 0.0, 0);
}

@ -494,7 +494,10 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
bsdf->ior = 1.0f;
bsdf->fresnel = NULL;
if (data_node.y == SVM_STACK_INVALID) {
/* compute roughness */
float anisotropy = clamp(param2, -0.99f, 0.99f);
if (data_node.y == SVM_STACK_INVALID || fabsf(anisotropy) <= 1e-4f) {
/* Isotropic case. */
bsdf->T = zero_float3();
bsdf->alpha_x = roughness;
bsdf->alpha_y = roughness;
@ -507,8 +510,6 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
if (rotation != 0.0f)
bsdf->T = rotate_around_axis(bsdf->T, bsdf->N, rotation * M_2PI_F);
/* compute roughness */
float anisotropy = clamp(param2, -0.99f, 0.99f);
if (anisotropy < 0.0f) {
bsdf->alpha_x = roughness / (1.0f + anisotropy);
bsdf->alpha_y = roughness * (1.0f + anisotropy);

@ -2335,68 +2335,6 @@ void BsdfNode::compile(OSLCompiler & /*compiler*/)
assert(0);
}
/* Anisotropic BSDF Closure */
NODE_DEFINE(AnisotropicBsdfNode)
{
NodeType *type = NodeType::add("anisotropic_bsdf", create, NodeType::SHADER);
SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
SOCKET_IN_NORMAL(normal, "Normal", zero_float3(), SocketType::LINK_NORMAL);
SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
static NodeEnum distribution_enum;
distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ID);
distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ID);
distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID);
distribution_enum.insert("ashikhmin_shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID);
SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_ID);
SOCKET_IN_VECTOR(tangent, "Tangent", zero_float3(), SocketType::LINK_TANGENT);
SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.5f);
SOCKET_IN_FLOAT(rotation, "Rotation", 0.0f);
SOCKET_OUT_CLOSURE(BSDF, "BSDF");
return type;
}
AnisotropicBsdfNode::AnisotropicBsdfNode() : BsdfNode(get_node_type())
{
closure = CLOSURE_BSDF_MICROFACET_GGX_ID;
}
void AnisotropicBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
if (shader->has_surface_link()) {
ShaderInput *tangent_in = input("Tangent");
if (!tangent_in->link)
attributes->add(ATTR_STD_GENERATED);
}
ShaderNode::attributes(shader, attributes);
}
void AnisotropicBsdfNode::compile(SVMCompiler &compiler)
{
closure = distribution;
if (closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID)
BsdfNode::compile(
compiler, input("Roughness"), input("Anisotropy"), input("Rotation"), input("Color"));
else
BsdfNode::compile(compiler, input("Roughness"), input("Anisotropy"), input("Rotation"));
}
void AnisotropicBsdfNode::compile(OSLCompiler &compiler)
{
compiler.parameter(this, "distribution");
compiler.add(this, "node_anisotropic_bsdf");
}
/* Glossy BSDF Closure */
NODE_DEFINE(GlossyBsdfNode)
@ -2414,7 +2352,12 @@ NODE_DEFINE(GlossyBsdfNode)
distribution_enum.insert("ashikhmin_shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID);
distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID);
SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_ID);
SOCKET_IN_VECTOR(tangent, "Tangent", zero_float3(), SocketType::LINK_TANGENT);
SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.0f);
SOCKET_IN_FLOAT(rotation, "Rotation", 0.0f);
SOCKET_OUT_CLOSURE(BSDF, "BSDF");
@ -2427,8 +2370,32 @@ GlossyBsdfNode::GlossyBsdfNode() : BsdfNode(get_node_type())
distribution_orig = NBUILTIN_CLOSURES;
}
bool GlossyBsdfNode::is_isotropic()
{
ShaderInput *anisotropy_input = input("Anisotropy");
/* Keep in sync with the thresholds in OSL's node_glossy_bsdf and SVM's svm_node_closure_bsdf. */
return (!anisotropy_input->link && fabsf(anisotropy) <= 1e-4f);
}
void GlossyBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
if (shader->has_surface_link()) {
ShaderInput *tangent_in = input("Tangent");
if (!tangent_in->link && !is_isotropic())
attributes->add(ATTR_STD_GENERATED);
}
ShaderNode::attributes(shader, attributes);
}
void GlossyBsdfNode::simplify_settings(Scene *scene)
{
/* If the anisotropy is close enough to zero, fall back to the isotropic case. */
ShaderInput *tangent_input = input("Tangent");
if (tangent_input->link && is_isotropic()) {
tangent_input->disconnect();
}
if (distribution_orig == NBUILTIN_CLOSURES) {
roughness_orig = roughness;
distribution_orig = distribution;
@ -2478,9 +2445,10 @@ void GlossyBsdfNode::compile(SVMCompiler &compiler)
if (closure == CLOSURE_BSDF_REFLECTION_ID)
BsdfNode::compile(compiler, NULL, NULL);
else if (closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID)
BsdfNode::compile(compiler, input("Roughness"), NULL, NULL, input("Color"));
BsdfNode::compile(
compiler, input("Roughness"), input("Anisotropy"), input("Rotation"), input("Color"));
else
BsdfNode::compile(compiler, input("Roughness"), NULL);
BsdfNode::compile(compiler, input("Roughness"), input("Anisotropy"), input("Rotation"));
}
void GlossyBsdfNode::compile(OSLCompiler &compiler)

@ -495,27 +495,6 @@ class BsdfNode : public BsdfBaseNode {
NODE_SOCKET_API(float, surface_mix_weight)
};
class AnisotropicBsdfNode : public BsdfNode {
public:
SHADER_NODE_CLASS(AnisotropicBsdfNode)
NODE_SOCKET_API(float3, tangent)
NODE_SOCKET_API(float, roughness)
NODE_SOCKET_API(float, anisotropy)
NODE_SOCKET_API(float, rotation)
NODE_SOCKET_API(ClosureType, distribution)
ClosureType get_closure_type()
{
return distribution;
}
void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_attribute_dependency()
{
return true;
}
};
class DiffuseBsdfNode : public BsdfNode {
public:
SHADER_NODE_CLASS(DiffuseBsdfNode)
@ -624,12 +603,23 @@ class GlossyBsdfNode : public BsdfNode {
return distribution;
}
NODE_SOCKET_API(float3, tangent)
NODE_SOCKET_API(float, roughness)
NODE_SOCKET_API(float, anisotropy)
NODE_SOCKET_API(float, rotation)
NODE_SOCKET_API(ClosureType, distribution)
void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_attribute_dependency()
{
return true;
}
private:
float roughness_orig;
ClosureType distribution_orig;
bool is_isotropic();
};
class GlassBsdfNode : public BsdfNode {

@ -191,7 +191,6 @@ shader_node_categories = [
NodeItem("ShaderNodeBsdfRefraction", poll=object_eevee_cycles_shader_nodes_poll),
NodeItem("ShaderNodeBsdfGlass", poll=object_eevee_cycles_shader_nodes_poll),
NodeItem("ShaderNodeBsdfTranslucent", poll=object_eevee_cycles_shader_nodes_poll),
NodeItem("ShaderNodeBsdfAnisotropic", poll=object_cycles_shader_nodes_poll),
NodeItem("ShaderNodeBsdfVelvet", poll=object_cycles_shader_nodes_poll),
NodeItem("ShaderNodeBsdfToon", poll=object_cycles_shader_nodes_poll),
NodeItem("ShaderNodeSubsurfaceScattering", poll=object_eevee_cycles_shader_nodes_poll),

@ -554,8 +554,10 @@ struct bNodeSocket *ntreeAddSocketInterface(struct bNodeTree *ntree,
* \{ */
struct bNodeType *nodeTypeFind(const char *idname);
const char *nodeTypeFindAlias(const char *idname);
void nodeRegisterType(struct bNodeType *ntype);
void nodeUnregisterType(struct bNodeType *ntype);
void nodeRegisterAlias(struct bNodeType *nt, const char *alias);
struct GHashIterator *nodeTypeGetIterator(void);
/* Helper macros for iterating over node types. */
@ -893,9 +895,9 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
#define SH_NODE_MIX_SHADER 128
#define SH_NODE_ATTRIBUTE 129
#define SH_NODE_BACKGROUND 130
#define SH_NODE_BSDF_ANISOTROPIC 131
#define SH_NODE_BSDF_GLOSSY 131
#define SH_NODE_BSDF_DIFFUSE 132
#define SH_NODE_BSDF_GLOSSY 133
#define SH_NODE_BSDF_GLOSSY_LEGACY 133
#define SH_NODE_BSDF_GLASS 134
#define SH_NODE_BSDF_TRANSLUCENT 137
#define SH_NODE_BSDF_TRANSPARENT 138

@ -1352,6 +1352,7 @@ namespace blender::bke {
static GHash *nodetreetypes_hash = nullptr;
static GHash *nodetypes_hash = nullptr;
static GHash *nodetypes_alias_hash = nullptr;
static GHash *nodesockettypes_hash = nullptr;
} // namespace blender::bke
@ -1416,6 +1417,19 @@ bNodeType *nodeTypeFind(const char *idname)
return nullptr;
}
const char *nodeTypeFindAlias(const char *alias)
{
if (alias[0]) {
const char *idname = static_cast<const char *>(
BLI_ghash_lookup(blender::bke::nodetypes_alias_hash, alias));
if (idname) {
return idname;
}
}
return alias;
}
static void node_free_type(void *nodetype_v)
{
bNodeType *nodetype = static_cast<bNodeType *>(nodetype_v);
@ -1458,6 +1472,11 @@ void nodeUnregisterType(bNodeType *nt)
BLI_ghash_remove(blender::bke::nodetypes_hash, nt->idname, nullptr, node_free_type);
}
void nodeRegisterAlias(bNodeType *nt, const char *alias)
{
BLI_ghash_insert(blender::bke::nodetypes_alias_hash, BLI_strdup(alias), BLI_strdup(nt->idname));
}
namespace blender::bke {
bool node_type_is_undefined(const bNode *node)
@ -4389,6 +4408,7 @@ void BKE_node_system_init()
{
blender::bke::nodetreetypes_hash = BLI_ghash_str_new("nodetreetypes_hash gh");
blender::bke::nodetypes_hash = BLI_ghash_str_new("nodetypes_hash gh");
blender::bke::nodetypes_alias_hash = BLI_ghash_str_new("nodetypes_alias_hash gh");
blender::bke::nodesockettypes_hash = BLI_ghash_str_new("nodesockettypes_hash gh");
register_nodes();
@ -4396,6 +4416,11 @@ void BKE_node_system_init()
void BKE_node_system_exit()
{
if (blender::bke::nodetypes_alias_hash) {
BLI_ghash_free(blender::bke::nodetypes_alias_hash, MEM_freeN, MEM_freeN);
blender::bke::nodetypes_alias_hash = nullptr;
}
if (blender::bke::nodetypes_hash) {
NODE_TYPES_BEGIN (nt) {
if (nt->rna_ext.free) {

@ -2176,6 +2176,46 @@ static void versioning_replace_legacy_mix_rgb_node(bNodeTree *ntree)
}
}
static void versioning_replace_legacy_glossy_node(bNodeTree *ntree)
{
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->type == SH_NODE_BSDF_GLOSSY_LEGACY) {
strcpy(node->idname, "ShaderNodeBsdfAnisotropic");
node->type = SH_NODE_BSDF_GLOSSY;
}
}
}
static void versioning_remove_microfacet_sharp_distribution(bNodeTree *ntree)
{
/* Find all glossy, glass and refraction BSDF nodes that have their distribution
* set to SHARP and set them to GGX, disconnect any link to the Roughness input
* and set its value to zero. */
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (!ELEM(node->type, SH_NODE_BSDF_GLOSSY, SH_NODE_BSDF_GLASS, SH_NODE_BSDF_REFRACTION)) {
continue;
}
if (node->custom1 != SHD_GLOSSY_SHARP_DEPRECATED) {
continue;
}
node->custom1 = SHD_GLOSSY_GGX;
LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
if (!STREQ(socket->identifier, "Roughness")) {
continue;
}
if (socket->link != nullptr) {
nodeRemLink(ntree, socket->link);
}
bNodeSocketValueFloat *socket_value = (bNodeSocketValueFloat *)socket->default_value;
socket_value->value = 0.0f;
break;
}
}
}
static void version_fix_image_format_copy(Main *bmain, ImageFormatData *format)
{
/* Fix bug where curves in image format were not properly copied to file output
@ -4371,5 +4411,12 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
*/
{
/* Keep this block, even when empty. */
/* Convert anisotropic BSDF node to glossy BSDF. */
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
versioning_replace_legacy_glossy_node(ntree);
versioning_remove_microfacet_sharp_distribution(ntree);
}
FOREACH_NODETREE_END;
}
}

@ -181,8 +181,8 @@ static void displacement_principled_nodes(bNode *node)
static bool node_has_roughness(const bNode *node)
{
return ELEM(node->type,
SH_NODE_BSDF_ANISOTROPIC,
SH_NODE_BSDF_GLASS,
SH_NODE_BSDF_GLOSSY_LEGACY,
SH_NODE_BSDF_GLOSSY,
SH_NODE_BSDF_REFRACTION);
}

@ -504,7 +504,6 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_VECTOR_DISPLACEMENT:
ntype->draw_buttons = node_shader_buts_displacement;
break;
case SH_NODE_BSDF_GLOSSY:
case SH_NODE_BSDF_GLASS:
case SH_NODE_BSDF_REFRACTION:
ntype->draw_buttons = node_shader_buts_glossy;

@ -464,7 +464,6 @@ set(GLSL_SRC
shaders/material/gpu_shader_material_add_shader.glsl
shaders/material/gpu_shader_material_ambient_occlusion.glsl
shaders/material/gpu_shader_material_anisotropic.glsl
shaders/material/gpu_shader_material_attribute.glsl
shaders/material/gpu_shader_material_background.glsl
shaders/material/gpu_shader_material_bevel.glsl

@ -1,27 +0,0 @@
void node_bsdf_anisotropic(vec4 color,
float roughness,
float anisotropy,
float rotation,
vec3 N,
vec3 T,
float weight,
const float do_multiscatter,
out Closure result)
{
N = safe_normalize(N);
vec3 V = cameraVec(g_data.P);
float NV = dot(N, V);
vec2 split_sum = brdf_lut(NV, roughness);
ClosureReflection reflection_data;
reflection_data.weight = weight;
reflection_data.color = (do_multiscatter != 0.0) ?
F_brdf_multi_scatter(color.rgb, color.rgb, split_sum) :
F_brdf_single_scatter(color.rgb, color.rgb, split_sum);
reflection_data.N = N;
reflection_data.roughness = roughness;
result = closure_eval(reflection_data);
}

@ -1,6 +1,13 @@
void node_bsdf_glossy(
vec4 color, float roughness, vec3 N, float weight, float do_multiscatter, out Closure result)
void node_bsdf_glossy(vec4 color,
float roughness,
float anisotropy,
float rotation,
vec3 N,
vec3 T,
float weight,
const float do_multiscatter,
out Closure result)
{
N = safe_normalize(N);
vec3 V = cameraVec(g_data.P);

@ -1698,7 +1698,7 @@ typedef struct NodeShaderMix {
/* glossy distributions */
#define SHD_GLOSSY_BECKMANN 0
#define SHD_GLOSSY_SHARP 1
#define SHD_GLOSSY_SHARP_DEPRECATED 1 /* deprecated */
#define SHD_GLOSSY_GGX 2
#define SHD_GLOSSY_ASHIKHMIN_SHIRLEY 3
#define SHD_GLOSSY_MULTI_GGX 4

@ -1185,6 +1185,9 @@ static bNode *rna_NodeTree_node_new(bNodeTree *ntree,
return NULL;
}
/* If the given idname is an alias, translate it to the proper idname. */
type = nodeTypeFindAlias(type);
ntype = nodeTypeFind(type);
if (!ntype) {
BKE_reportf(reports, RPT_ERROR, "Node type %s undefined", type);
@ -4740,11 +4743,6 @@ static const EnumPropertyItem node_ycc_items[] = {
};
static const EnumPropertyItem node_glossy_items[] = {
{SHD_GLOSSY_SHARP,
"SHARP",
0,
"Sharp",
"Results in perfectly sharp reflections like a mirror. The Roughness value is not used"},
{SHD_GLOSSY_BECKMANN, "BECKMANN", 0, "Beckmann", ""},
{SHD_GLOSSY_GGX, "GGX", 0, "GGX", ""},
{SHD_GLOSSY_ASHIKHMIN_SHIRLEY, "ASHIKHMIN_SHIRLEY", 0, "Ashikhmin-Shirley", ""},
@ -4757,25 +4755,7 @@ static const EnumPropertyItem node_glossy_items[] = {
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem node_anisotropic_items[] = {
{SHD_GLOSSY_BECKMANN, "BECKMANN", 0, "Beckmann", ""},
{SHD_GLOSSY_GGX, "GGX", 0, "GGX", ""},
{SHD_GLOSSY_MULTI_GGX,
"MULTI_GGX",
0,
"Multiscatter GGX",
"Slower than GGX but gives a more energy conserving results, which would otherwise be "
"visible as excessive darkening"},
{SHD_GLOSSY_ASHIKHMIN_SHIRLEY, "ASHIKHMIN_SHIRLEY", 0, "Ashikhmin-Shirley", ""},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem node_glass_items[] = {
{SHD_GLOSSY_SHARP,
"SHARP",
0,
"Sharp",
"Results in perfectly sharp reflections like a mirror. The Roughness value is not used"},
{SHD_GLOSSY_BECKMANN, "BECKMANN", 0, "Beckmann", ""},
{SHD_GLOSSY_GGX, "GGX", 0, "GGX", ""},
{SHD_GLOSSY_MULTI_GGX,
@ -4788,11 +4768,6 @@ static const EnumPropertyItem node_glass_items[] = {
};
static const EnumPropertyItem node_refraction_items[] = {
{SHD_GLOSSY_SHARP,
"SHARP",
0,
"Sharp",
"Results in perfectly sharp reflections like a mirror. The Roughness value is not used"},
{SHD_GLOSSY_BECKMANN, "BECKMANN", 0, "Beckmann", ""},
{SHD_GLOSSY_GGX, "GGX", 0, "GGX", ""},
{0, NULL, 0, NULL, NULL},
@ -6301,17 +6276,6 @@ static void def_refraction(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_anisotropic(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_anisotropic_items);
RNA_def_property_ui_text(prop, "Distribution", "Light scattering distribution on rough surface");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_toon(StructRNA *srna)
{
PropertyRNA *prop;

@ -59,10 +59,9 @@ DefNode(ShaderNode, SH_NODE_ATTRIBUTE, def_sh_attribute, "ATT
DefNode(ShaderNode, SH_NODE_AMBIENT_OCCLUSION, def_sh_ambient_occlusion,"AMBIENT_OCCLUSION", AmbientOcclusion, "Ambient Occlusion", "Compute how much the hemisphere above the shading point is occluded, for example to add weathering effects to corners.\nNote: For Cycles, this may slow down renders significantly")
DefNode(ShaderNode, SH_NODE_BACKGROUND, 0, "BACKGROUND", Background, "Background", "Add background light emission.\nNote: This node should only be used for the world surface output")
DefNode(ShaderNode, SH_NODE_HOLDOUT, 0, "HOLDOUT", Holdout, "Holdout", "Create a \"hole\" in the image with zero alpha transparency, which is useful for compositing.\nNote: the holdout shader can only create alpha when transparency is enabled in the film settings")
DefNode(ShaderNode, SH_NODE_BSDF_ANISOTROPIC, def_anisotropic, "BSDF_ANISOTROPIC", BsdfAnisotropic, "Anisotropic BSDF", "Glossy reflection with separate control over U and V direction roughness")
DefNode(ShaderNode, SH_NODE_BSDF_DIFFUSE, 0, "BSDF_DIFFUSE", BsdfDiffuse, "Diffuse BSDF", "Lambertian and Oren-Nayar diffuse reflection")
DefNode(ShaderNode, SH_NODE_BSDF_PRINCIPLED, def_principled, "BSDF_PRINCIPLED", BsdfPrincipled, "Principled BSDF", "Physically-based, easy-to-use shader for rendering surface materials, based on the Disney principled model also known as the \"PBR\" shader")
DefNode(ShaderNode, SH_NODE_BSDF_GLOSSY, def_glossy, "BSDF_GLOSSY", BsdfGlossy, "Glossy BSDF", "Reflection with microfacet distribution, used for materials such as metal or mirrors")
DefNode(ShaderNode, SH_NODE_BSDF_GLOSSY, def_glossy, "BSDF_GLOSSY", BsdfAnisotropic, "Glossy BSDF", "Reflection with microfacet distribution, used for materials such as metal or mirrors")
DefNode(ShaderNode, SH_NODE_BSDF_GLASS, def_glass, "BSDF_GLASS", BsdfGlass, "Glass BSDF", "Glass-like shader mixing refraction and reflection at grazing angles")
DefNode(ShaderNode, SH_NODE_BSDF_REFRACTION, def_refraction, "BSDF_REFRACTION", BsdfRefraction, "Refraction BSDF", "Glossy refraction with sharp or microfacet distribution, typically used for materials that transmit light")
DefNode(ShaderNode, SH_NODE_BSDF_TRANSLUCENT, 0, "BSDF_TRANSLUCENT", BsdfTranslucent, "Translucent BSDF", "Lambertian diffuse transmission")

@ -32,7 +32,6 @@ set(SRC
nodes/node_shader_bevel.cc
nodes/node_shader_blackbody.cc
nodes/node_shader_brightness.cc
nodes/node_shader_bsdf_anisotropic.cc
nodes/node_shader_bsdf_diffuse.cc
nodes/node_shader_bsdf_glass.cc
nodes/node_shader_bsdf_glossy.cc

@ -17,7 +17,6 @@ void register_shader_nodes()
register_node_type_sh_bevel();
register_node_type_sh_blackbody();
register_node_type_sh_brightcontrast();
register_node_type_sh_bsdf_anisotropic();
register_node_type_sh_bsdf_diffuse();
register_node_type_sh_bsdf_glass();
register_node_type_sh_bsdf_glossy();

@ -13,7 +13,6 @@ void register_node_type_sh_background();
void register_node_type_sh_bevel();
void register_node_type_sh_blackbody();
void register_node_type_sh_brightcontrast();
void register_node_type_sh_bsdf_anisotropic();
void register_node_type_sh_bsdf_diffuse();
void register_node_type_sh_bsdf_glass();
void register_node_type_sh_bsdf_glossy();

@ -884,7 +884,6 @@ static void ntree_shader_weight_tree_invert(bNodeTree *ntree, bNode *output_node
break;
}
case SH_NODE_BACKGROUND:
case SH_NODE_BSDF_ANISOTROPIC:
case SH_NODE_BSDF_DIFFUSE:
case SH_NODE_BSDF_GLASS:
case SH_NODE_BSDF_GLOSSY:
@ -942,7 +941,6 @@ static bool closure_node_filter(const bNode *node)
case SH_NODE_ADD_SHADER:
case SH_NODE_MIX_SHADER:
case SH_NODE_BACKGROUND:
case SH_NODE_BSDF_ANISOTROPIC:
case SH_NODE_BSDF_DIFFUSE:
case SH_NODE_BSDF_GLASS:
case SH_NODE_BSDF_GLOSSY:

@ -1,77 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2005 Blender Foundation */
#include "node_shader_util.hh"
#include "UI_interface.h"
#include "UI_resources.h"
namespace blender::nodes::node_shader_bsdf_anisotropic_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Color>("Color").default_value({0.8f, 0.8f, 0.8f, 1.0f});
b.add_input<decl::Float>("Roughness")
.default_value(0.5f)
.min(0.0f)
.max(1.0f)
.subtype(PROP_FACTOR);
b.add_input<decl::Float>("Anisotropy").default_value(0.5f).min(-1.0f).max(1.0f);
b.add_input<decl::Float>("Rotation")
.default_value(0.0f)
.min(0.0f)
.max(1.0f)
.subtype(PROP_FACTOR);
b.add_input<decl::Vector>("Normal").hide_value();
b.add_input<decl::Vector>("Tangent").hide_value();
b.add_input<decl::Float>("Weight").unavailable();
b.add_output<decl::Shader>("BSDF");
}
static void node_shader_buts_anisotropic(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
{
uiItemR(layout, ptr, "distribution", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
}
static void node_shader_init_anisotropic(bNodeTree * /*ntree*/, bNode *node)
{
node->custom1 = SHD_GLOSSY_GGX;
}
static int node_shader_gpu_bsdf_anisotropic(GPUMaterial *mat,
bNode *node,
bNodeExecData * /*execdata*/,
GPUNodeStack *in,
GPUNodeStack *out)
{
if (!in[4].link) {
GPU_link(mat, "world_normals_get", &in[4].link);
}
GPU_material_flag_set(mat, GPU_MATFLAG_GLOSSY);
float use_multi_scatter = (node->custom1 == SHD_GLOSSY_MULTI_GGX) ? 1.0f : 0.0f;
return GPU_stack_link(
mat, node, "node_bsdf_anisotropic", in, out, GPU_constant(&use_multi_scatter));
}
} // namespace blender::nodes::node_shader_bsdf_anisotropic_cc
/* node type definition */
void register_node_type_sh_bsdf_anisotropic()
{
namespace file_ns = blender::nodes::node_shader_bsdf_anisotropic_cc;
static bNodeType ntype;
sh_node_type_base(&ntype, SH_NODE_BSDF_ANISOTROPIC, "Anisotropic BSDF", NODE_CLASS_SHADER);
ntype.declare = file_ns::node_declare;
ntype.add_ui_poll = object_cycles_shader_nodes_poll;
ntype.draw_buttons = file_ns::node_shader_buts_anisotropic;
blender::bke::node_type_size_preset(&ntype, blender::bke::eNodeSizePreset::MIDDLE);
ntype.initfunc = file_ns::node_shader_init_anisotropic;
ntype.gpu_fn = file_ns::node_shader_gpu_bsdf_anisotropic;
nodeRegisterType(&ntype);
}

@ -34,10 +34,6 @@ static int node_shader_gpu_bsdf_glass(GPUMaterial *mat,
GPU_link(mat, "world_normals_get", &in[3].link);
}
if (node->custom1 == SHD_GLOSSY_SHARP) {
GPU_link(mat, "set_value_zero", &in[1].link);
}
GPU_material_flag_set(mat, GPU_MATFLAG_GLOSSY | GPU_MATFLAG_REFRACT);
float use_multi_scatter = (node->custom1 == SHD_GLOSSY_MULTI_GGX) ? 1.0f : 0.0f;

@ -3,6 +3,9 @@
#include "node_shader_util.hh"
#include "UI_interface.h"
#include "UI_resources.h"
namespace blender::nodes::node_shader_bsdf_glossy_cc {
static void node_declare(NodeDeclarationBuilder &b)
@ -13,11 +16,23 @@ static void node_declare(NodeDeclarationBuilder &b)
.min(0.0f)
.max(1.0f)
.subtype(PROP_FACTOR);
b.add_input<decl::Float>("Anisotropy").default_value(0.0f).min(-1.0f).max(1.0f);
b.add_input<decl::Float>("Rotation")
.default_value(0.0f)
.min(0.0f)
.max(1.0f)
.subtype(PROP_FACTOR);
b.add_input<decl::Vector>("Normal").hide_value();
b.add_input<decl::Vector>("Tangent").hide_value();
b.add_input<decl::Float>("Weight").unavailable();
b.add_output<decl::Shader>("BSDF");
}
static void node_shader_buts_glossy(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
{
uiItemR(layout, ptr, "distribution", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
}
static void node_shader_init_glossy(bNodeTree * /*ntree*/, bNode *node)
{
node->custom1 = SHD_GLOSSY_GGX;
@ -29,12 +44,8 @@ static int node_shader_gpu_bsdf_glossy(GPUMaterial *mat,
GPUNodeStack *in,
GPUNodeStack *out)
{
if (!in[2].link) {
GPU_link(mat, "world_normals_get", &in[2].link);
}
if (node->custom1 == SHD_GLOSSY_SHARP) {
GPU_link(mat, "set_value_zero", &in[1].link);
if (!in[4].link) {
GPU_link(mat, "world_normals_get", &in[4].link);
}
GPU_material_flag_set(mat, GPU_MATFLAG_GLOSSY);
@ -56,9 +67,14 @@ void register_node_type_sh_bsdf_glossy()
sh_node_type_base(&ntype, SH_NODE_BSDF_GLOSSY, "Glossy BSDF", NODE_CLASS_SHADER);
ntype.declare = file_ns::node_declare;
ntype.add_ui_poll = object_shader_nodes_poll;
ntype.draw_buttons = file_ns::node_shader_buts_glossy;
blender::bke::node_type_size_preset(&ntype, blender::bke::eNodeSizePreset::MIDDLE);
ntype.initfunc = file_ns::node_shader_init_glossy;
ntype.gpu_fn = file_ns::node_shader_gpu_bsdf_glossy;
nodeRegisterType(&ntype);
/* Needed to preserve API compatibility with older versions which had separate
* Glossy and Anisotropic nodes. */
nodeRegisterAlias(&ntype, "ShaderNodeBsdfGlossy");
}

@ -34,10 +34,6 @@ static int node_shader_gpu_bsdf_refraction(GPUMaterial *mat,
GPU_link(mat, "world_normals_get", &in[3].link);
}
if (node->custom1 == SHD_GLOSSY_SHARP) {
GPU_link(mat, "set_value_zero", &in[1].link);
}
GPU_material_flag_set(mat, GPU_MATFLAG_REFRACT);
return GPU_stack_link(mat, node, "node_bsdf_refraction", in, out);

@ -4086,6 +4086,9 @@ static PyObject *pyrna_struct_bl_rna_get_subclass(PyObject *cls, PyObject *args)
PointerRNA ptr;
if (srna_base == &RNA_Node) {
/* If the given idname is an alias, translate it to the proper idname. */
id = nodeTypeFindAlias(id);
bNodeType *nt = nodeTypeFind(id);
if (nt) {
RNA_pointer_create(NULL, &RNA_Struct, nt->rna_ext.srna, &ptr);