Преглед на файлове

Added 2 new blender nodes and fixed some Godot shader issues (#405)

* Added HueSaturation and Invert (only for color input) nodes
Fix normal mapping node to Godot shader
Fix albedo textures not receiving hint_albedo in Godot

* convert tabs into spaces
Wagner преди 4 години
родител
ревизия
3b0870e7d4

+ 88 - 9
io_scene_godot/converters/material/script_shader/node_converters.py

@@ -58,6 +58,26 @@ def filter_id_illegal_char(string):
     to lower case"""
     return re.sub(r'\W', '', string).lower()
 
+def is_albedo_texture(image_texture_node):
+    """check whether the texture in a TexImage node is albedo texture"""
+    assert image_texture_node.bl_idname == 'ShaderNodeTexImage'
+    node_queue = deque()
+    for link in image_texture_node.outputs['Color'].links:
+        node_queue.append((link.to_node, link.to_socket))
+
+    while node_queue:
+        node, socket = node_queue.popleft()
+        if ((socket.name == 'Base Color' and
+                node.bl_idname == 'ShaderNodeBsdfPrincipled') or
+            (socket.name == 'Color' and
+                node.bl_idname == 'ShaderNodeBsdfDiffuse'
+            )):
+            return True
+        for sock in node.outputs:
+            for link in sock.links:
+                node_queue.append((link.to_node, link.to_socket))
+
+    return False
 
 def is_normal_texture(image_texture_node):
     """check whether the texture in a TexImage node is normal texture"""
@@ -80,20 +100,27 @@ def is_normal_texture(image_texture_node):
 
 class Texture:
     """A texture"""
+    
+    class Hint:
+        NONE   = 0
+        ALBEDO = 1
+        NORMAL = 2
 
-    def __init__(self, bl_image, identifier, hint_normal):
+    def __init__(self, bl_image, identifier, **kwargs):
         # note that image could be None, it need to be safely handled
         self.image = bl_image
-        self.hint_normal = hint_normal
         # identifier is the variable name in scripts
         self.tmp_identifier = identifier
+        self.hint = kwargs.get("hint", self.Hint.NONE)
 
     def __hash__(self):
-        return hash((self.image, self.hint_normal))
+        return hash((self.image, self.hint))
 
     def hint_str(self):
         """form all the hints into a string"""
-        if self.hint_normal:
+        if self.hint == self.Hint.ALBEDO:
+            return ": hint_albedo"
+        elif self.hint == self.Hint.NORMAL:
             return ": hint_normal"
         return ""
 
@@ -795,12 +822,14 @@ class ImageTextureNodeConverter(NodeConverterBase):
             self.local_code.append("%s = vec3(UV, 0.0)" % tex_coord)
 
         tex_var = self.generate_tmp_texture_id(self.bl_node.name)
-        if self.bl_node.image is not None:
-            is_normal = is_normal_texture(self.bl_node)
-        else:
-            is_normal = False
+        texture_hint = Texture.Hint.NONE
+        if is_normal_texture(self.bl_node):
+            texture_hint = Texture.Hint.NORMAL
+        elif is_albedo_texture(self.bl_node):
+            texture_hint = Texture.Hint.ALBEDO
+
         self.textures.append(
-            Texture(self.bl_node.image, tex_var, is_normal)
+            Texture(self.bl_node.image, tex_var, hint=texture_hint)
         )
 
         in_arguments.append(tex_coord)
@@ -973,6 +1002,54 @@ class GeometryNodeConverter(NodeConverterBase):
         self._convert('Tangent', 'TANGENT', True)
 
 
+class HueSaturationNodeConverter(NodeConverterBase):
+    """Converter for ShaderNodeHueSaturation"""
+
+    def parse_node_to_fragment(self):
+        hue_socket = self.bl_node.inputs['Hue']
+        saturation_socket = self.bl_node.inputs['Saturation']
+        value_socket = self.bl_node.inputs['Value']
+        fac_socket = self.bl_node.inputs['Fac']
+        color_socket = self.bl_node.inputs['Color']
+
+        hue_id = self.in_sockets_map[hue_socket]
+        saturation_id = self.in_sockets_map[saturation_socket]
+        value_id = self.in_sockets_map[value_socket]
+        fac_id = self.in_sockets_map[fac_socket]
+        color_id = self.in_sockets_map[color_socket]
+
+        function = find_function_by_name('node_hsv')
+
+        out_color_socket = self.bl_node.outputs['Color']
+        out_color_id = self.generate_socket_id_str(out_color_socket)
+
+        in_args = (fac_id, hue_id, saturation_id, value_id, color_id)
+        out_args = (out_color_id,)
+        self.add_function_call(function, in_args, out_args)
+
+        self.out_sockets_map[out_color_socket] = out_color_id
+
+class InvertNodeConverter(NodeConverterBase):
+    """Converter for ShaderNodeInvert"""
+
+    def parse_node_to_fragment(self):
+        fac_socket = self.bl_node.inputs['Fac']
+        color_socket = self.bl_node.inputs['Color']
+        
+        fac_id = self.in_sockets_map[fac_socket]
+        color_id = self.in_sockets_map[color_socket]
+
+        function = find_function_by_name('node_invert')
+
+        out_color_socket = self.bl_node.outputs['Color']
+        out_color_id = self.generate_socket_id_str(out_color_socket)
+
+        in_args = (fac_id, color_id)
+        out_args = (out_color_id,)
+        self.add_function_call(function, in_args, out_args)
+
+        self.out_sockets_map[out_color_socket] = out_color_id
+
 class GeneralNodeConverter(NodeConverterBase):
     """Converter for general converter node, they all use functions"""
 
@@ -1009,6 +1086,8 @@ NODE_CONVERTERS = {
     'ShaderNodeUVMap': UvmapNodeConverter,
     'ShaderNodeValue': ValueNodeConverter,
     'ShaderNodeNewGeometry': GeometryNodeConverter,
+    'ShaderNodeHueSaturation': HueSaturationNodeConverter,
+    'ShaderNodeInvert': InvertNodeConverter,
 }
 
 

+ 36 - 1
io_scene_godot/converters/material/script_shader/shader_functions.py

@@ -245,6 +245,41 @@ void node_separate_rgb(vec4 color, out float r, out float g, out float b) {
 void node_combine_rgb(float r, float g, float b, out vec4 color) {
     color = vec4(r, g, b, 1.0);
 }
+"""),
+
+    ShaderFunction(code="""
+void node_hsv(float fac, float in_hue, float in_saturation, float in_value,
+                        vec4 in_color, out vec4 out_color) {
+    
+    vec3 rgb = in_color.rgb;
+    vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
+    vec4 p = mix(vec4(rgb.bg, K.wz), vec4(rgb.gb, K.xy), step(rgb.b, rgb.g));
+    vec4 q = mix(vec4(p.xyw, rgb.r), vec4(rgb.r, p.yzx), step(p.x, rgb.r));
+
+    float d = q.x - min(q.w, q.y);
+    float e = 1.0e-10;
+    vec3 hsv = vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
+    
+    hsv.x = hsv.x + in_hue - 0.5;
+    hsv.y = clamp(hsv.y * in_saturation, 0.0, 1.0);
+    hsv.z = clamp(hsv.z * in_value, 0.0, 1.0);
+    
+    K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
+    vec3 p2 = abs(fract(hsv.xxx + K.xyz) * 6.0 - K.www);
+    rgb = hsv.z * mix(K.xxx, clamp(p2 - K.xxx, 0.0, 1.0), hsv.y);
+    
+    out_color.rgb = mix(in_color.rgb, rgb, fac);
+    out_color.a = in_color.a;
+}
+"""),
+
+    ShaderFunction(code="""
+void node_invert(float fac, vec4 in_color,
+                        out vec4 out_color) {
+    
+    out_color = mix(in_color, vec4(1.0) - in_color, fac);
+    out_color.a = in_color.a;
+}
 """),
 
     ShaderFunction(code="""
@@ -351,7 +386,7 @@ void node_bump(float strength, float dist, float height, vec3 normal,
     ShaderFunction(code="""
 void node_normal_map_tangent(float strength, vec4 color, vec3 normal,
         vec3 tangent, vec3 binormal, out vec3 out_normal) {
-    vec3 signed_color = vec3(2.0, -2.0, 2.0) * (color.xzy - vec3(0.5));
+    vec3 signed_color = vec3(2.0, -2.0, -2.0) * (color.xyz - vec3(0.5));
     vec3 tex_normal = signed_color.x * tangent +
                       signed_color.y * binormal +
                       signed_color.z * normal;