Browse Source

Implement basic cycles light handling. (#164)

Cycles lights are implemented using the node tree, and this patch
doesn't attempt to handle all the possibilities that enables.

However, it does succeed in exporting the basic options you can tweak
in the light settings panel, including:

- RGB Color (no alpha)
- Energy
- Negative Light (for strength < 0)
- Shadows enabled/disabled

This also removes the use_sphere check as cycles lights do not support
limited distance or use_sphere.

Fixes #150.

(cherry picked from commit b57cee82f36c2831efe4e701b122581d2f5a093f)
Lu Jiacheng 6 years ago
parent
commit
dfb78a7599

+ 46 - 9
io_scene_godot/converters/simple_nodes.py

@@ -68,6 +68,24 @@ def export_camera_node(escn_file, export_settings, node, parent_gd_node):
     return cam_node
 
 
+def find_shader_node(node_tree, name):
+    """Find the shader node from the tree with the given name."""
+    for node in node_tree.nodes:
+        if node.bl_idname == name:
+            return node
+    logging.warning("%s node not found", name)
+    return None
+
+
+def node_input(node, name):
+    """Get the named input value from the shader node."""
+    for inp in node.inputs:
+        if inp.name == name:
+            return inp.default_value
+    logging.warning("%s input not found in %s", name, node.bl_idname)
+    return None
+
+
 class LightNode(NodeTemplate):
     """Base class for godot light node"""
     _light_attr_conv = [
@@ -104,14 +122,16 @@ class LightNode(NodeTemplate):
 def export_light_node(escn_file, export_settings, node, parent_gd_node):
     """Exports lights - well, the ones it knows about. Other light types
     just throw a warning"""
-    light = node.data
+    bl_light_to_gd_light = {
+        "POINT": "OmniLight",
+        "SPOT": "SpotLight",
+        "SUN": "DirectionalLight",
+    }
 
-    if light.type == "POINT":
-        light_node = LightNode(node.name, 'OmniLight', parent_gd_node)
-    elif light.type == "SPOT":
-        light_node = LightNode(node.name, 'SpotLight', parent_gd_node)
-    elif light.type == "SUN":
-        light_node = LightNode(node.name, 'DirectionalLight', parent_gd_node)
+    light = node.data
+    if light.type in bl_light_to_gd_light:
+        light_node = LightNode(
+            node.name, bl_light_to_gd_light[light.type], parent_gd_node)
     else:
         light_node = None
         logging.warning(
@@ -123,9 +143,26 @@ def export_light_node(escn_file, export_settings, node, parent_gd_node):
             bl_attr, gd_attr, converter = item
             light_node[gd_attr] = converter(getattr(light, bl_attr))
 
-        # Properties cannot handled by a converter function
+        # Properties common to all lights
+        # These cannot be set via AttributeConvertInfo as it will not handle
+        # animations correctly
         light_node['transform'] = fix_directional_transform(node.matrix_local)
-        light_node['shadow_enabled'] = light.use_shadow
+        if light.use_nodes:
+            emission = find_shader_node(light.node_tree, 'ShaderNodeEmission')
+            if emission:
+                strength = node_input(emission, 'Strength') or 100
+                color = node_input(emission, 'Color') or [1, 1, 1]
+                # we don't have an easy way to get these in cycles
+                # don't set them and let godot use its defaults
+                del light_node['light_specular']
+                del light_node['shadow_color']
+                # strength=100 in cycles is roughly equivalent to energy=1
+                light_node['light_energy'] = abs(strength / 100.0)
+                light_node['light_color'] = gamma_correct(color)
+                light_node['shadow_enabled'] = light.cycles.cast_shadow
+                light_node['light_negative'] = strength < 0
+        else:
+            light_node['shadow_enabled'] = light.use_shadow
 
         escn_file.add_node(light_node)
 

File diff suppressed because it is too large
+ 8 - 0
tests/reference_exports/light/cycles_lights.escn


+ 1 - 2
tests/reference_exports/material_cycle/material_anistropy.escn

@@ -268,12 +268,11 @@ surfaces/0 = {
 
 [node name="Point" type="DirectionalLight" parent="."]
 
-light_specular = 1.0
 light_energy = 1.0
 light_color = Color(1.0, 1.0, 1.0, 1.0)
-shadow_color = Color(0.0, 0.0, 0.0, 1.0)
 transform = Transform(0.701062, -0.562597, -0.438174, 0.452107, -0.124517, 0.88323, -0.551463, -0.8173, 0.16706, -2.09735, 4.28268, -0.137035)
 shadow_enabled = true
+light_negative = false
 
 [node name="object_with_uv" type="MeshInstance" parent="."]
 

+ 2 - 4
tests/reference_exports/material_cycle/material_cycle.escn

@@ -1699,27 +1699,25 @@ material/0 = SubResource(39)
 
 [node name="Spot001" type="SpotLight" parent="."]
 
-light_specular = 1.0
 light_energy = 1.0
 light_color = Color(1.0, 1.0, 1.0, 1.0)
-shadow_color = Color(0.0, 0.0, 0.0, 1.0)
 spot_angle = 17.4
 spot_angle_attenuation = 1.25
 spot_range = 25.0
 transform = Transform(0.629608, 0.0765798, 0.77313, -0.776913, 0.06206, 0.626542, 0.0, -0.99513, 0.0985693, 5.32508, 4.74617, 0.487329)
 shadow_enabled = true
+light_negative = false
 
 [node name="Spot" type="SpotLight" parent="."]
 
-light_specular = 1.0
 light_energy = 1.0
 light_color = Color(1.0, 1.0, 1.0, 1.0)
-shadow_color = Color(0.0, 0.0, 0.0, 1.0)
 spot_angle = 24.3
 spot_angle_attenuation = 1.25
 spot_range = 25.0
 transform = Transform(0.633641, 0.273452, -0.723687, 0.117184, 0.890727, 0.439173, 0.764701, -0.363082, 0.532357, -4.6068, 2.54209, 4.80618)
 shadow_enabled = true
+light_negative = false
 
 [node name="Plane" type="MeshInstance" parent="."]
 

+ 2 - 3
tests/reference_exports/material_cycle/material_normal.escn

@@ -844,12 +844,11 @@ material/0 = SubResource(12)
 
 [node name="Lamp" type="DirectionalLight" parent="."]
 
-light_specular = 1.0
-light_energy = 1.0
+light_energy = 0.04
 light_color = Color(1.0, 1.0, 1.0, 1.0)
-shadow_color = Color(0.0, 0.0, 0.0, 1.0)
 transform = Transform(-0.404791, -0.439839, 0.801677, 0.221124, 0.803611, 0.552553, -0.88727, 0.400938, -0.228035, 4.07625, 1.70784, -1.00545)
 shadow_enabled = true
+light_negative = false
 
 [node name="test_displacement" type="MeshInstance" parent="."]
 

BIN
tests/test_scenes/light/cycles_lights.blend


Some files were not shown because too many files changed in this diff