Cycles: add OSL support for hiding input socket value

When either initializing with a non-constant value, or using the standard
[[ string widget = "null" ]] metadata. This can be used for inputs like
normals and texture coordinates, where you don't want to default to a
constant value.

In previous OSL versions the input value was automatically ignore when it
was left unchanged for such inputs. However that's no longer the case in
the latest version, breaking existing nodes. There is no good entirely
backwards compatible fix, but I believe the new behavior is better and will
keep most existing cases working.

Fix T102450: OSL node with normal input not working
This commit is contained in:
Brecht Van Lommel 2022-11-23 18:02:45 +01:00
parent 962e221cd3
commit dc1ed9c1aa
Notes: blender-bot 2023-02-14 05:53:38 +01:00
Referenced by issue #102450, Some refractive materials no longer work in OSL
5 changed files with 36 additions and 6 deletions

View File

@ -478,6 +478,7 @@ static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args)
/* Read metadata. */
bool is_bool_param = false;
bool hide_value = !param->validdefault;
ustring param_label = param->name;
for (const OSL::OSLQuery::Parameter &metadata : param->metadata) {
@ -487,6 +488,9 @@ static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args)
if (metadata.sdefault[0] == "boolean" || metadata.sdefault[0] == "checkBox") {
is_bool_param = true;
}
else if (metadata.sdefault[0] == "null") {
hide_value = true;
}
}
else if (metadata.name == "label") {
/* Socket label. */
@ -596,6 +600,9 @@ static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args)
if (b_sock.name() != param_label) {
b_sock.name(param_label.string());
}
if (b_sock.hide_value() != hide_value) {
b_sock.hide_value(hide_value);
}
used_sockets.insert(b_sock.ptr.data);
found_existing = true;
}
@ -635,6 +642,8 @@ static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args)
set_boolean(b_sock.ptr, "default_value", default_boolean);
}
b_sock.hide_value(hide_value);
used_sockets.insert(b_sock.ptr.data);
}
}

View File

@ -66,7 +66,9 @@ struct SocketType {
LINK_NORMAL = (1 << 8),
LINK_POSITION = (1 << 9),
LINK_TANGENT = (1 << 10),
DEFAULT_LINK_MASK = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10)
LINK_OSL_INITIALIZER = (1 << 11),
DEFAULT_LINK_MASK = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) |
(1 << 10) | (1 << 11)
};
ustring name;

View File

@ -525,6 +525,7 @@ OSLNode *OSLShaderManager::osl_node(ShaderGraph *graph,
SocketType::Type socket_type;
/* Read type and default value. */
if (param->isclosure) {
socket_type = SocketType::CLOSURE;
}
@ -579,7 +580,21 @@ OSLNode *OSLShaderManager::osl_node(ShaderGraph *graph,
node->add_output(param->name, socket_type);
}
else {
node->add_input(param->name, socket_type);
/* Detect if we should leave parameter initialization to OSL, either though
* not constant default or widget metadata. */
int socket_flags = 0;
if (!param->validdefault) {
socket_flags |= SocketType::LINK_OSL_INITIALIZER;
}
for (const OSL::OSLQuery::Parameter &metadata : param->metadata) {
if (metadata.type == TypeDesc::STRING) {
if (metadata.name == "widget" && metadata.sdefault[0] == "null") {
socket_flags |= SocketType::LINK_OSL_INITIALIZER;
}
}
}
node->add_input(param->name, socket_type, socket_flags);
}
}
@ -702,8 +717,12 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath)
foreach (ShaderInput *input, node->inputs) {
if (!input->link) {
/* checks to untangle graphs */
if (node_skip_input(node, input))
if (node_skip_input(node, input)) {
continue;
}
if (input->flags() & SocketType::LINK_OSL_INITIALIZER) {
continue;
}
string param_name = compatible_name(node, input);
const SocketType &socket = input->socket_type;

View File

@ -7257,12 +7257,12 @@ char *OSLNode::input_default_value()
return (char *)this + align_up(sizeof(OSLNode), 16) + inputs_size;
}
void OSLNode::add_input(ustring name, SocketType::Type socket_type)
void OSLNode::add_input(ustring name, SocketType::Type socket_type, const int flags)
{
char *memory = input_default_value();
size_t offset = memory - (char *)this;
const_cast<NodeType *>(type)->register_input(
name, name, socket_type, offset, memory, NULL, NULL, SocketType::LINKABLE);
name, name, socket_type, offset, memory, NULL, NULL, flags | SocketType::LINKABLE);
}
void OSLNode::add_output(ustring name, SocketType::Type socket_type)

View File

@ -1525,7 +1525,7 @@ class OSLNode final : public ShaderNode {
ShaderNode *clone(ShaderGraph *graph) const;
char *input_default_value();
void add_input(ustring name, SocketType::Type type);
void add_input(ustring name, SocketType::Type type, const int flags = 0);
void add_output(ustring name, SocketType::Type type);
SHADER_NODE_NO_CLONE_CLASS(OSLNode)