My friend and I are trying to create a very simple custom node with OSL. The node we are making looks like this:
It has very simple code, and it's only switching input data to output according to the index:
shader mySwitch(
color map1 = 0,
color map2 = 0,
color map3 = 0,
int index = 0,
output closure color BSDF = diffuse(N)
)
{
if (index == 0)
BSDF = map1 * diffuse(N);
else if (index == 1)
BSDF = map2 * diffuse(N);
else
BSDF = map3 * diffuse(N);
}
However, we cannot see the maps (textures) in the 3Dview port (OSL is not supported by GPU), so it must be programmed with the Blender API to create a custom shader, which is what we did. This is what's in the file gpu_shader_material.glsl
…
void node_switch_shader(
int index,
vec4 shader0,
vec4 shader2,
vec4 shader3,
vec4 shader4,
vec4 shader5,
vec4 shader6,
vec4 shader7,
vec4 shader8,
vec4 shader9,
out vec4 shader
)
{
switch (index) {
case 0: shader = shader0; break;
case 1: shader = shader1; break;
case 2: shader = shader2; break;
case 3: shader = shader3; break;
case 4: shader = shader4; break;
case 5: shader = shader5; break;
case 6: shader = shader6; break;
case 7: shader = shader7; break;
case 8: shader = shader8; break;
case 9: shader = shader9; break;
default: shader = shader0;
}
}
...
After that, we tried to create the node with C++ by changing 7 files and compiling Blender. However, this process is possible because my smart friend is a very good programmer and we did it only for Ios. For now, we don't know if it is fully functional but maybe it is. But creators and gurus will know.
So is it possible to create something like this in a simpler way? We only want to change the output color data depending on the index, nothing else. For the puppets it can be a game changer.
I am adding the .diff
file to show the changes on files for C++. Or please can you add this for next day release?
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 8a736c9..8957791 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -792,6 +792,7 @@ struct ShadeResult;
#define SH_NODE_BEVEL 197
#define SH_NODE_DISPLACEMENT 198
#define SH_NODE_VECTOR_DISPLACEMENT 199
+#define SH_NODE_SWITCH_SHADER 600
/* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 1f5ffbd..4f134a8 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -2819,6 +2819,40 @@ void node_add_shader(vec4 shader1, vec4 shader2, out vec4 shader)
shader = shader1 + shader2;
}
+void node_switch_shader(
+ int index,
+ vec4 shader0,
+ vec4 shader2,
+ vec4 shader3,
+ vec4 shader4,
+ vec4 shader5,
+ vec4 shader6,
+ vec4 shader7,
+ vec4 shader8,
+ vec4 shader9,
+ out vec4 shader
+)
+{
+
+ switch (index) {
+
+ case 0: shader = shader0; break;
+ case 1: shader = shader1; break;
+ case 2: shader = shader2; break;
+ case 3: shader = shader3; break;
+ case 4: shader = shader4; break;
+ case 5: shader = shader5; break;
+ case 6: shader = shader6; break;
+ case 7: shader = shader7; break;
+ case 8: shader = shader8; break;
+ case 9: shader = shader9; break;
+
+ default: shader = shader0;
+
+ }
+
+}
+
/* fresnel */
void node_fresnel(float ior, vec3 N, vec3 I, out float result)
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 1acd1c4..3e4a9d3 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -181,6 +181,7 @@ set(SRC
shader/nodes/node_shader_light_falloff.c
shader/nodes/node_shader_light_path.c
shader/nodes/node_shader_mix_shader.c
+ shader/nodes/node_shader_switch_shader.c
shader/nodes/node_shader_normal_map.c
shader/nodes/node_shader_object_info.c
shader/nodes/node_shader_hair_info.c
diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h
index 6ed71e0..7734205 100644
--- a/source/blender/nodes/NOD_shader.h
+++ b/source/blender/nodes/NOD_shader.h
@@ -117,6 +117,7 @@ void register_node_type_sh_volume_scatter(void);
void register_node_type_sh_bsdf_hair(void);
void register_node_type_sh_subsurface_scattering(void);
void register_node_type_sh_mix_shader(void);
+void register_node_type_sh_switch_shader(void);
void register_node_type_sh_add_shader(void);
void register_node_type_sh_uvmap(void);
void register_node_type_sh_uvalongstroke(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 2db23c2..e7d3c03 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -73,6 +73,7 @@ DefNode( ShaderNode, SH_NODE_OUTPUT_LINESTYLE, def_sh_output_linestyle,"OU
DefNode( ShaderNode, SH_NODE_FRESNEL, 0, "FRESNEL", Fresnel, "Fresnel", "" )
DefNode( ShaderNode, SH_NODE_LAYER_WEIGHT, 0, "LAYER_WEIGHT", LayerWeight, "Layer Weight", "" )
DefNode( ShaderNode, SH_NODE_MIX_SHADER, 0, "MIX_SHADER", MixShader, "Mix Shader", "" )
+DefNode( ShaderNode, SH_NODE_SWITCH_SHADER, 0, "SWITCH_SHADER", SwitchShader, "Switch Shader", "" )
DefNode( ShaderNode, SH_NODE_ADD_SHADER, 0, "ADD_SHADER", AddShader, "Add Shader", "" )
DefNode( ShaderNode, SH_NODE_ATTRIBUTE, def_sh_attribute, "ATTRIBUTE", Attribute, "Attribute", "" )
DefNode( ShaderNode, SH_NODE_AMBIENT_OCCLUSION, 0, "AMBIENT_OCCLUSION", AmbientOcclusion, "Ambient Occlusion", "" )
eddited Diff 02/15/2018 15:30
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 3338470..2ecfadb 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -382,6 +382,9 @@ static ShaderNode *add_node(Scene *scene,
else if(b_node.is_a(&RNA_ShaderNodeMixShader)) {
node = new MixClosureNode();
}
+ else if(b_node.is_a(&RNA_ShaderNodeSwitchShader)) {
+ node = new SwitchClosureNode();
+ }
else if(b_node.is_a(&RNA_ShaderNodeAttribute)) {
BL::ShaderNodeAttribute b_attr_node(b_node);
AttributeNode *attr = new AttributeNode();
diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt
index 19b7769..e781017 100644
--- a/intern/cycles/kernel/shaders/CMakeLists.txt
+++ b/intern/cycles/kernel/shaders/CMakeLists.txt
@@ -48,6 +48,7 @@ set(SRC_OSL
node_math.osl
node_mix.osl
node_mix_closure.osl
+ node_switch_closure.osl
node_musgrave_texture.osl
node_noise_texture.osl
node_normal.osl
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 48613a9..db75c59 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -3819,6 +3819,51 @@ void MixClosureNode::constant_fold(const ConstantFolder& folder)
}
}
+/* Switch Closure */
+
+NODE_DEFINE(SwitchClosureNode)
+{
+ NodeType* type = NodeType::add("switch_closure", create, NodeType::SHADER);
+
+ SOCKET_IN_FLOAT(index, "Index", 1.0f);
+ SOCKET_IN_CLOSURE(closure1, "Closure1");
+ SOCKET_IN_CLOSURE(closure2, "Closure2");
+ SOCKET_IN_CLOSURE(closure3, "Closure3");
+ SOCKET_IN_CLOSURE(closure4, "Closure4");
+ SOCKET_IN_CLOSURE(closure5, "Closure5");
+ SOCKET_IN_CLOSURE(closure6, "Closure6");
+ SOCKET_IN_CLOSURE(closure7, "Closure7");
+ SOCKET_IN_CLOSURE(closure8, "Closure8");
+ SOCKET_IN_CLOSURE(closure9, "Closure9");
+ SOCKET_IN_CLOSURE(closure10, "Closure10");
+
+ SOCKET_OUT_CLOSURE(closure, "Closure");
+
+ return type;
+}
+
+SwitchClosureNode::SwitchClosureNode()
+: ShaderNode(node_type)
+{
+ // special_type = SHADER_SPECIAL_TYPE_CLOSURE;
+ // Don't know which type to use
+}
+
+void SwitchClosureNode::compile(SVMCompiler& compiler)
+{
+ // How to achieve the same behaviour as in OSL node_switch_closure using SVM?
+}
+
+void SwitchClosureNode::compile(OSLCompiler& compiler)
+{
+ compiler.add(this, "node_switch_closure");
+}
+
+void SwitchClosureNode::constant_fold(const ConstantFolder& folder)
+{
+ // Do not need to modify folder, probably
+}
+
/* Mix Closure */
NODE_DEFINE(MixClosureWeightNode)
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index f664ebf..5650e2a 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -674,6 +674,14 @@ public:
float fac;
};
+class SwitchClosureNode : public ShaderNode {
+public:
+ SHADER_NODE_CLASS(SwitchClosureNode)
+ void constant_fold(const ConstantFolder& folder);
+
+ float index;
+};
+
class MixClosureWeightNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MixClosureWeightNode)
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 8a736c9..887062e 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -792,6 +792,7 @@ struct ShadeResult;
#define SH_NODE_BEVEL 197
#define SH_NODE_DISPLACEMENT 198
#define SH_NODE_VECTOR_DISPLACEMENT 199
+#define SH_NODE_SWITCH_SHADER 924
/* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 74766be..45478d9 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -3618,6 +3618,7 @@ static void registerShaderNodes(void)
register_node_type_sh_volume_scatter();
register_node_type_sh_subsurface_scattering();
register_node_type_sh_mix_shader();
+ register_node_type_sh_switch_shader();
register_node_type_sh_add_shader();
register_node_type_sh_uvmap();
register_node_type_sh_uvalongstroke();
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 1f5ffbd..b7200d4 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -2819,6 +2819,47 @@ void node_add_shader(vec4 shader1, vec4 shader2, out vec4 shader)
shader = shader1 + shader2;
}
+void node_switch_shader(
+ float index,
+ vec4 shader1,
+ vec4 shader2,
+ vec4 shader3,
+ vec4 shader4,
+ vec4 shader5,
+ vec4 shader6,
+ vec4 shader7,
+ vec4 shader8,
+ vec4 shader9,
+ vec4 shader10,
+ out vec4 shader
+)
+{
+
+ vec4 _placeholder = vec4(0.0, 0.0, 0.0, 0.0);
+ float _index = ceil(index);
+
+ if(_index == 2)
+ shader = mix(shader2, _placeholder, 0.0);
+ else if(_index == 3)
+ shader = mix(shader3, _placeholder, 0.0);
+ else if(_index == 4)
+ shader = mix(shader4, _placeholder, 0.0);
+ else if(_index == 5)
+ shader = mix(shader5, _placeholder, 0.0);
+ else if(_index == 6)
+ shader = mix(shader6, _placeholder, 0.0);
+ else if(_index == 7)
+ shader = mix(shader7, _placeholder, 0.0);
+ else if(_index == 8)
+ shader = mix(shader8, _placeholder, 0.0);
+ else if(_index == 9)
+ shader = mix(shader9, _placeholder, 0.0);
+ else if(_index == 10)
+ shader = mix(shader10, _placeholder, 0.0);
+ else
+ shader = mix(shader1, _placeholder, 0.0);
+}
+
/* fresnel */
void node_fresnel(float ior, vec3 N, vec3 I, out float result)
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 1acd1c4..3e4a9d3 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -181,6 +181,7 @@ set(SRC
shader/nodes/node_shader_light_falloff.c
shader/nodes/node_shader_light_path.c
shader/nodes/node_shader_mix_shader.c
+ shader/nodes/node_shader_switch_shader.c
shader/nodes/node_shader_normal_map.c
shader/nodes/node_shader_object_info.c
shader/nodes/node_shader_hair_info.c
diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h
index 6ed71e0..7734205 100644
--- a/source/blender/nodes/NOD_shader.h
+++ b/source/blender/nodes/NOD_shader.h
@@ -117,6 +117,7 @@ void register_node_type_sh_volume_scatter(void);
void register_node_type_sh_bsdf_hair(void);
void register_node_type_sh_subsurface_scattering(void);
void register_node_type_sh_mix_shader(void);
+void register_node_type_sh_switch_shader(void);
void register_node_type_sh_add_shader(void);
void register_node_type_sh_uvmap(void);
void register_node_type_sh_uvalongstroke(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 2db23c2..e7d3c03 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -73,6 +73,7 @@ DefNode( ShaderNode, SH_NODE_OUTPUT_LINESTYLE, def_sh_output_linestyle,"OU
DefNode( ShaderNode, SH_NODE_FRESNEL, 0, "FRESNEL", Fresnel, "Fresnel", "" )
DefNode( ShaderNode, SH_NODE_LAYER_WEIGHT, 0, "LAYER_WEIGHT", LayerWeight, "Layer Weight", "" )
DefNode( ShaderNode, SH_NODE_MIX_SHADER, 0, "MIX_SHADER", MixShader, "Mix Shader", "" )
+DefNode( ShaderNode, SH_NODE_SWITCH_SHADER, 0, "SWITCH_SHADER", SwitchShader, "Switch Shader", "" )
DefNode( ShaderNode, SH_NODE_ADD_SHADER, 0, "ADD_SHADER", AddShader, "Add Shader", "" )
DefNode( ShaderNode, SH_NODE_ATTRIBUTE, def_sh_attribute, "ATTRIBUTE", Attribute, "Attribute", "" )
DefNode( ShaderNode, SH_NODE_AMBIENT_OCCLUSION, 0, "AMBIENT_OCCLUSION", AmbientOcclusion, "Ambient Occlusion", "" )