diff --git a/README.md b/README.md index cf77962..4941fe2 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ To start adding volumetric fog to your scene, you need to first add a `Volumetri * `Shadow Atlas Size` :- How much resolution is used to render the shadows of lights. **Does not affect `Volumetric Shadows`**. * `Ambient Light Color` :- The color of the ambient light applied to volumes. * `Ambient Light Energy` :- How much the ambient light is applied to volumes. +* `Cull Mask` :- This determines what lights get processed in the effect. Lights whose layers don't match up with this will not show up in the fog. ### Volume Proxy volume_proxy diff --git a/addons/silicon.vfx.volumetrics/renderer/volumetric_renderer.gd b/addons/silicon.vfx.volumetrics/renderer/volumetric_renderer.gd index ff455ac..79fd633 100644 --- a/addons/silicon.vfx.volumetrics/renderer/volumetric_renderer.gd +++ b/addons/silicon.vfx.volumetrics/renderer/volumetric_renderer.gd @@ -23,6 +23,8 @@ export var volumetric_shadows := false export var ambient_light := Vector3.ONE +export var cull_mask := (1 << 20) - 1 + var tiling := Vector2(8, 16) export var blend := 0.0 diff --git a/addons/silicon.vfx.volumetrics/volumetric_fog.gd b/addons/silicon.vfx.volumetrics/volumetric_fog.gd index c0de6f7..a984043 100644 --- a/addons/silicon.vfx.volumetrics/volumetric_fog.gd +++ b/addons/silicon.vfx.volumetrics/volumetric_fog.gd @@ -17,6 +17,8 @@ var shadow_atlas_size := 1024 setget set_shadow_atlas_size var ambient_light_color := Color.black setget set_ambient_light_color var ambient_light_energy := 1.0 setget set_ambient_light_energy +var cull_mask := (1 << 20) - 1 setget set_cull_mask + func _get_property_list() -> Array: return [ {name="VolumetricFog", type=TYPE_NIL, usage=PROPERTY_USAGE_CATEGORY}, @@ -32,83 +34,123 @@ func _get_property_list() -> Array: {name="Ambient Light", type=TYPE_NIL, usage=PROPERTY_USAGE_GROUP, hint_string="ambient_light_"}, {name="ambient_light_color", type=TYPE_COLOR, hint=PROPERTY_HINT_COLOR_NO_ALPHA}, {name="ambient_light_energy", type=TYPE_REAL, hint=PROPERTY_HINT_RANGE, hint_string="0,16,0.01,or_greater"}, + + {name="Cull Mask", type=TYPE_NIL, usage=PROPERTY_USAGE_GROUP}, + {name="cull_mask", type=TYPE_INT, hint=PROPERTY_HINT_LAYERS_3D_RENDER} ] func _enter_tree() -> void: + if not get_viewport().has_meta("fog_nodes"): + get_viewport().set_meta("fog_nodes", [self]) + elif not get_viewport().get_meta("fog_nodes").has(self): + get_viewport().get_meta("fog_nodes").append(self) + var fog_nodes: Array = get_viewport().get_meta("fog_nodes") + for fog in fog_nodes: + if fog == null or fog.get_parent() == null: + fog_nodes.erase(fog) + print(fog_nodes) + + if fog_nodes.size() > 1: + push_warning("Viewport already has a fog node; the original will stay in effect.") + renderer_id = _get_volumetric_server().add_renderer(get_viewport()) - _get_volumetric_server().renderer_set_start(renderer_id, start) - _get_volumetric_server().renderer_set_end(renderer_id, end) - _get_volumetric_server().renderer_set_tile_size(renderer_id, [2,4,8,16][tile_size]) - _get_volumetric_server().renderer_set_samples(renderer_id, [32,64,128,256][samples]) - _get_volumetric_server().renderer_set_distribution(renderer_id, distribution) - _get_volumetric_server().renderer_set_temporal_blending(renderer_id, temporal_blending) - _get_volumetric_server().renderer_set_volumetric_shadows(renderer_id, volumetric_shadows) - _get_volumetric_server().renderer_set_shadow_atlas_size(renderer_id, shadow_atlas_size) - _get_volumetric_server().renderer_set_ambient_light(renderer_id, Vector3(ambient_light_color.r, ambient_light_color.g, ambient_light_color.b) * ambient_light_energy) + if renderer_id != -1: + _get_volumetric_server().renderer_set_start(renderer_id, start) + _get_volumetric_server().renderer_set_end(renderer_id, end) + _get_volumetric_server().renderer_set_tile_size(renderer_id, [2,4,8,16][tile_size]) + _get_volumetric_server().renderer_set_samples(renderer_id, [32,64,128,256][samples]) + _get_volumetric_server().renderer_set_distribution(renderer_id, distribution) + _get_volumetric_server().renderer_set_temporal_blending(renderer_id, temporal_blending) + _get_volumetric_server().renderer_set_volumetric_shadows(renderer_id, volumetric_shadows) + _get_volumetric_server().renderer_set_shadow_atlas_size(renderer_id, shadow_atlas_size) + _get_volumetric_server().renderer_set_ambient_light(renderer_id, Vector3(ambient_light_color.r, ambient_light_color.g, ambient_light_color.b) * ambient_light_energy) + _get_volumetric_server().renderer_set_cull_mask(renderer_id, cull_mask) + + for fog in fog_nodes: + fog.update_configuration_warning() func _exit_tree() -> void: - _get_volumetric_server().remove_renderer(renderer_id) - renderer_id = -1 + var fog_nodes: Array = get_viewport().get_meta("fog_nodes") + if renderer_id != -1: + _get_volumetric_server().remove_renderer(renderer_id) + fog_nodes.erase(self) + renderer_id = -1 + for fog in fog_nodes: + fog.update_configuration_warning() + if _get_volumetric_server().get_renderer_by_viewport(get_viewport()) == -1 and not fog_nodes.empty(): + fog_nodes[0]._enter_tree() func set_start(value : float) -> void: start = min(value, end - 0.01) if renderer_id == -1: - yield(self, "ready") + return _get_volumetric_server().renderer_set_start(renderer_id, start) func set_end(value : float) -> void: end = max(value, start + 0.01) if renderer_id == -1: - yield(self, "ready") + return _get_volumetric_server().renderer_set_end(renderer_id, end) func set_tile_size(value : int) -> void: tile_size = value if renderer_id == -1: - yield(self, "ready") + return _get_volumetric_server().renderer_set_tile_size(renderer_id, [4,8,16][tile_size]) func set_samples(value : int) -> void: samples = value if renderer_id == -1: - yield(self, "ready") + return _get_volumetric_server().renderer_set_samples(renderer_id, [32,64,128,256][samples]) func set_distribution(value : float) -> void: distribution = value if renderer_id == -1: - yield(self, "ready") + return _get_volumetric_server().renderer_set_distribution(renderer_id, distribution) func set_temporal_blending(value : float) -> void: temporal_blending = value if renderer_id == -1: - yield(self, "ready") + return _get_volumetric_server().renderer_set_temporal_blending(renderer_id, temporal_blending) func set_volumetric_shadows(value : bool) -> void: volumetric_shadows = value if renderer_id == -1: - yield(self, "ready") + return _get_volumetric_server().renderer_set_volumetric_shadows(renderer_id, volumetric_shadows) func set_shadow_atlas_size(value : int) -> void: shadow_atlas_size = clamp(value, 256, 16384) if renderer_id == -1: - yield(self, "ready") + return _get_volumetric_server().renderer_set_shadow_atlas_size(renderer_id, shadow_atlas_size) func set_ambient_light_color(value : Color) -> void: ambient_light_color = value if renderer_id == -1: - yield(self, "ready") + return _get_volumetric_server().renderer_set_ambient_light(renderer_id, Vector3(ambient_light_color.r, ambient_light_color.g, ambient_light_color.b) * ambient_light_energy) func set_ambient_light_energy(value : float) -> void: ambient_light_energy = value if renderer_id == -1: - yield(self, "ready") + return _get_volumetric_server().renderer_set_ambient_light(renderer_id, Vector3(ambient_light_color.r, ambient_light_color.g, ambient_light_color.b) * ambient_light_energy) +func set_cull_mask(value : int) -> void: + cull_mask = value + if renderer_id == -1: + return + _get_volumetric_server().renderer_set_cull_mask(renderer_id, cull_mask) + +func _get_configuration_warning() -> String: + if get_viewport().get_meta("fog_nodes").size() > 1: + return "Only one VolumetricFog is allowed per scene." + return "" + + func _get_volumetric_server() -> Node: return Engine.get_main_loop().root.get_node("/root/VolumetricServer") diff --git a/addons/silicon.vfx.volumetrics/volumetric_server.gd b/addons/silicon.vfx.volumetrics/volumetric_server.gd index e1def86..a5678a2 100644 --- a/addons/silicon.vfx.volumetrics/volumetric_server.gd +++ b/addons/silicon.vfx.volumetrics/volumetric_server.gd @@ -85,6 +85,9 @@ func volume_set_param(id : int, param : String, value) -> void: volume.renderer.set_volume_param(id, param, value) func add_renderer(viewport : Viewport) -> int: + if get_renderer_by_viewport(viewport) != -1: + return -1 + if not can_function: id_counter += 1 return id_counter - 1 @@ -165,6 +168,9 @@ func renderer_set_distribution(id : int, value : float) -> void: func renderer_set_ambient_light(id : int, value : Vector3) -> void: renderers[id].node.ambient_light = value +func renderer_set_cull_mask(id : int, value : int) -> void: + renderers[id].node.cull_mask = value + func renderer_set_temporal_blending(id : int, value : float) -> void: renderers[id].node.blend = value @@ -201,14 +207,16 @@ func update_light(light : Light) -> void: var is_volumetric = light.has_meta("volumetric") is_volumetric = true if not is_volumetric else light.get_meta("volumetric") + var in_cull_mask = (renderer.cull_mask & light.layers) != 0 + if camera and not light is DirectionalLight: var light_aabb : AABB = light.get_transformed_aabb() var frustum_intersection = FrustumAABBIntersection.new(camera) is_volumetric = is_volumetric and frustum_intersection.is_inside_frustum(light_aabb) - if is_volumetric and not light.has_meta("_vol_id"): + if is_volumetric and not light.has_meta("_vol_id") and in_cull_mask: _on_node_added(light) - elif not is_volumetric and light.has_meta("_vol_id"): + elif (not is_volumetric or not in_cull_mask) and light.has_meta("_vol_id"): renderer.remove_light(light.get_meta("_vol_id")) light.remove_meta("_vol_id") diff --git a/addons/silicon.vfx.volumetrics/volumetrics_plugin.gd b/addons/silicon.vfx.volumetrics/volumetrics_plugin.gd index 5a02657..9138475 100644 --- a/addons/silicon.vfx.volumetrics/volumetrics_plugin.gd +++ b/addons/silicon.vfx.volumetrics/volumetrics_plugin.gd @@ -43,8 +43,6 @@ func _ready() -> void: texture_3d_creator.editor_file_system = get_editor_interface().get_resource_filesystem() get_editor_interface().get_base_control().add_child(texture_3d_creator) add_tool_menu_item("Create 3D Texture...", texture_3d_creator, "popup_centered_ratio", 0.0) - - print("Volumetrics plugin enter tree") func _exit_tree() -> void: remove_custom_type("LocalVolume") @@ -54,8 +52,6 @@ func _exit_tree() -> void: remove_spatial_gizmo_plugin(gizmo_plugin) remove_tool_menu_item("Create 3D Texture...") texture_3d_creator.queue_free() - - print("Volumetrics plugin exit tree") func forward_spatial_gui_input(p_camera : Camera, p_event : InputEvent) -> bool: if not editor_camera: diff --git a/demo/volumetrics_demo.tscn b/demo/volumetrics_demo.tscn index f279fa4..d3a8d9f 100644 --- a/demo/volumetrics_demo.tscn +++ b/demo/volumetrics_demo.tscn @@ -144,7 +144,7 @@ material/36 = null material/37 = null __meta__ = { "_edit_lock_": true, -"_vol_id": 4, +"_vol_id": 22, "apply_volumetrics": false } @@ -159,21 +159,18 @@ max_speed = Vector3( 2, 2, 5 ) environment = SubResource( 1 ) [node name="VolumetricFog" type="Node" parent="WorldEnvironment"] -process_priority = 512 script = ExtResource( 7 ) -__meta__ = { -"_editor_description_": "" -} start = 0.1 -end = 60.0 +end = 100.0 tile_size = 2 samples = 1 -distribution = 0.82 -temporal_blending = 0.83 +distribution = 1.0 +temporal_blending = 0.8 volumetric_shadows = true -shadow_atlas_size = 512 -ambient_light_color = Color( 0.0823529, 0.0823529, 0.0823529, 1 ) +shadow_atlas_size = 1024 +ambient_light_color = Color( 0.184314, 0.184314, 0.184314, 1 ) ambient_light_energy = 1.0 +cull_mask = 1048575 [node name="Lights" type="Spatial" parent="."] @@ -184,7 +181,7 @@ shadow_enabled = true omni_range = 18.0 omni_attenuation = 2.73208 __meta__ = { -"_vol_id": 5, +"_vol_id": 23, "volumetric": 4.07 } @@ -195,7 +192,7 @@ shadow_enabled = true omni_range = 18.0 omni_attenuation = 2.73208 __meta__ = { -"_vol_id": 6, +"_vol_id": 24, "volumetric": 4.07 } @@ -204,7 +201,7 @@ transform = Transform( 1, 0, 0, 0, -0.0680631, 0.997681, 0, -0.997681, -0.068063 visible = false shadow_enabled = true __meta__ = { -"_vol_id": 7, +"_vol_id": 25, "volumetric": 2.0 } diff --git a/doc_images/volumetric_fog_inspector.png b/doc_images/volumetric_fog_inspector.png index ca2fc42..c87f769 100644 Binary files a/doc_images/volumetric_fog_inspector.png and b/doc_images/volumetric_fog_inspector.png differ