Browse Source

Merge pull request #658 from Calinou/add-volumetric-fog-demo

Add a volumetric fog demo
Aaron Franke 3 years ago
parent
commit
f47d0909cc

+ 20 - 0
3d/volumetric_fog/README.md

@@ -0,0 +1,20 @@
+# Volumetric Fog
+
+This is an example of Godot's volumetric fog capabilities with the Vulkan renderer.
+
+Showcased features are:
+
+- Positive/negative density volumes that affect albedo (incoming light) and emission.
+- Box/ellipsoid shapes, height falloff, and density modulation using a 3D texture.
+- Temporal reprojection for greater stability and avoiding flickering.
+  - The difference is demonstrated with a moving fog volume.
+- Global density adjustment. With FogVolume nodes that have a positive density,
+  it's possible to apply volumetric fog only in specific areas.
+
+Language: GDScript
+
+Renderer: Vulkan Clustered
+
+## Screenshots
+
+![Screenshot](screenshots/volumetric_fog.png)

+ 69 - 0
3d/volumetric_fog/camera.gd

@@ -0,0 +1,69 @@
+extends Camera3D
+
+const MOUSE_SENSITIVITY = 0.002
+const MOVE_SPEED = 0.6
+
+var rot = Vector3()
+var velocity = Vector3()
+
+@onready var label = $Label
+
+
+func _ready():
+	Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
+	update_label()
+
+
+func _process(delta):
+	var motion = Vector3(
+			Input.get_action_strength("move_right") - Input.get_action_strength("move_left"),
+			0,
+			Input.get_action_strength("move_back") - Input.get_action_strength("move_forward")
+	)
+
+	# Normalize motion to prevent diagonal movement from being
+	# `sqrt(2)` times faster than straight movement.
+	motion = motion.normalized()
+
+	velocity += MOVE_SPEED * delta * (transform.basis * motion)
+	velocity *= 0.85
+	position += velocity
+
+
+func _input(event):
+	# Mouse look (only if the mouse is captured).
+	if event is InputEventMouseMotion and Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
+		# Horizontal mouse look.
+		rot.y -= event.relative.x * MOUSE_SENSITIVITY
+		# Vertical mouse look.
+		rot.x = clamp(rot.x - event.relative.y * MOUSE_SENSITIVITY, -1.57, 1.57)
+		transform.basis = Basis.from_euler(rot)
+
+	if event.is_action_pressed("toggle_mouse_capture"):
+		if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
+			Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
+		else:
+			Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
+
+	if event.is_action_pressed("toggle_temporal_reprojection"):
+		get_world_3d().environment.volumetric_fog_temporal_reprojection_enabled = not get_world_3d().environment.volumetric_fog_temporal_reprojection_enabled
+		update_label()
+	elif event.is_action_pressed("increase_temporal_reprojection"):
+		get_world_3d().environment.volumetric_fog_temporal_reprojection_amount = clamp(get_world_3d().environment.volumetric_fog_temporal_reprojection_amount + 0.01, 0.0, 0.99)
+		update_label()
+	elif event.is_action_pressed("decrease_temporal_reprojection"):
+		get_world_3d().environment.volumetric_fog_temporal_reprojection_amount = clamp(get_world_3d().environment.volumetric_fog_temporal_reprojection_amount - 0.01, 0.0, 0.99)
+		update_label()
+	elif event.is_action_pressed("increase_fog_density"):
+		get_world_3d().environment.volumetric_fog_density = clamp(get_world_3d().environment.volumetric_fog_density + 0.01, 0.0, 1.0)
+		update_label()
+	elif event.is_action_pressed("decrease_fog_density"):
+		get_world_3d().environment.volumetric_fog_density = clamp(get_world_3d().environment.volumetric_fog_density - 0.01, 0.0, 1.0)
+		update_label()
+
+
+func update_label():
+	if get_world_3d().environment.volumetric_fog_temporal_reprojection_enabled:
+		label.text = "Fog density: %.2f\nTemporal reprojection: Enabled\nTemporal reprojection strength: %.3f" % [get_world_3d().environment.volumetric_fog_density, get_world_3d().environment.volumetric_fog_temporal_reprojection_amount]
+	else:
+		label.text = "Fog density: %.2f\nTemporal reprojection: Disabled" % get_world_3d().environment.volumetric_fog_density

BIN
3d/volumetric_fog/icon_outlined.png


+ 26 - 0
3d/volumetric_fog/icon_outlined.png.import

@@ -0,0 +1,26 @@
+[remap]
+
+importer="3d_texture"
+type="CompressedTexture3D"
+uid="uid://bpvy0e34otmhk"
+path="res://.godot/imported/icon_outlined.png-be09dc71a0cb04701900baffec3ab610.ctex3d"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://icon_outlined.png"
+dest_files=["res://.godot/imported/icon_outlined.png-be09dc71a0cb04701900baffec3ab610.ctex3d"]
+
+[params]
+
+compress/mode=0
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/bptc_ldr=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+slices/horizontal=1
+slices/vertical=1

+ 80 - 0
3d/volumetric_fog/project.godot

@@ -0,0 +1,80 @@
+; Engine configuration file.
+; It's best edited using the editor UI and not directly,
+; since the parameters that go here are not all obvious.
+;
+; Format:
+;   [section] ; section goes between []
+;   param=value ; assign values to parameters
+
+config_version=5
+
+[application]
+
+config/name="Volumetric Fog"
+run/main_scene="res://volumetric_fog.tscn"
+config/features=PackedStringArray("4.0")
+
+[display]
+
+window/stretch/mode="canvas_items"
+window/stretch/aspect="expand"
+
+[input]
+
+toggle_temporal_reprojection={
+"deadzone": 0.5,
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"unicode":0,"echo":false,"script":null)
+]
+}
+increase_temporal_reprojection={
+"deadzone": 0.5,
+"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":4,"pressed":false,"double_click":false,"script":null)
+, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":0,"physical_keycode":16777232,"unicode":0,"echo":false,"script":null)
+]
+}
+decrease_temporal_reprojection={
+"deadzone": 0.5,
+"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":5,"pressed":false,"double_click":false,"script":null)
+, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":0,"physical_keycode":16777234,"unicode":0,"echo":false,"script":null)
+]
+}
+increase_fog_density={
+"deadzone": 0.5,
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":0,"physical_keycode":16777233,"unicode":0,"echo":false,"script":null)
+]
+}
+decrease_fog_density={
+"deadzone": 0.5,
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":0,"physical_keycode":16777231,"unicode":0,"echo":false,"script":null)
+]
+}
+move_forward={
+"deadzone": 0.5,
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"unicode":0,"echo":false,"script":null)
+]
+}
+move_back={
+"deadzone": 0.5,
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"unicode":0,"echo":false,"script":null)
+]
+}
+move_right={
+"deadzone": 0.5,
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"unicode":0,"echo":false,"script":null)
+]
+}
+move_left={
+"deadzone": 0.5,
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"unicode":0,"echo":false,"script":null)
+]
+}
+toggle_mouse_capture={
+"deadzone": 0.5,
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":0,"physical_keycode":16777217,"unicode":0,"echo":false,"script":null)
+]
+}
+
+[rendering]
+
+anti_aliasing/quality/screen_space_aa=1
+anti_aliasing/quality/use_debanding=true

+ 0 - 0
3d/volumetric_fog/screenshots/.gdignore


BIN
3d/volumetric_fog/screenshots/volumetric_fog.png


+ 278 - 0
3d/volumetric_fog/volumetric_fog.tscn

@@ -0,0 +1,278 @@
+[gd_scene load_steps=17 format=3 uid="uid://d1d6jy84lcpg7"]
+
+[ext_resource type="Script" path="res://camera.gd" id="1_mfjvp"]
+[ext_resource type="CompressedTexture3D" uid="uid://bpvy0e34otmhk" path="res://icon_outlined.png" id="2_8fjmj"]
+
+[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_fefkn"]
+sky_top_color = Color(0.568627, 0.698039, 0.807843, 1)
+sky_horizon_color = Color(0.672549, 0.704902, 0.734314, 1)
+ground_bottom_color = Color(0.121569, 0.121569, 0.129412, 1)
+ground_horizon_color = Color(0.672549, 0.704902, 0.734314, 1)
+
+[sub_resource type="Sky" id="Sky_5gwha"]
+sky_material = SubResource( "ProceduralSkyMaterial_fefkn" )
+
+[sub_resource type="Environment" id="Environment_gsgar"]
+background_mode = 2
+sky = SubResource( "Sky_5gwha" )
+tonemap_mode = 2
+glow_enabled = true
+volumetric_fog_enabled = true
+volumetric_fog_density = 0.1
+
+[sub_resource type="FogMaterial" id="FogMaterial_sfd8y"]
+density = -1.6842
+
+[sub_resource type="FogMaterial" id="FogMaterial_v1f5u"]
+density = 0.2
+emission = Color(0, 1, 0.501961, 1)
+edge_fade = 2.2779e-05
+
+[sub_resource type="FogMaterial" id="FogMaterial_blauf"]
+density = 0.2
+emission = Color(0, 1, 0.501961, 1)
+height_falloff = 1e+06
+edge_fade = 2.2779e-05
+
+[sub_resource type="FogMaterial" id="FogMaterial_yvnd5"]
+density = 0.3
+emission = Color(1, 0.290196, 0.419608, 1)
+
+[sub_resource type="FogMaterial" id="FogMaterial_gcgmm"]
+density = 0.3
+emission = Color(1, 0.290196, 0.419608, 1)
+height_falloff = 1e+06
+
+[sub_resource type="FogMaterial" id="FogMaterial_8xcc6"]
+density = 0.1
+albedo = Color(1, 15, 10, 1)
+
+[sub_resource type="Animation" id="Animation_jg7qq"]
+length = 0.001
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath("MovingBox:position")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [Vector3(0, 2, 10)]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath("MovingBox:rotation")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [Vector3(0, 0, 0)]
+}
+tracks/2/type = "value"
+tracks/2/imported = false
+tracks/2/enabled = true
+tracks/2/path = NodePath("MovingBox:scale")
+tracks/2/interp = 1
+tracks/2/loop_wrap = true
+tracks/2/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [Vector3(1, 1, 1)]
+}
+
+[sub_resource type="Animation" id="Animation_axnf8"]
+resource_name = "move_fog_volume"
+length = 10.0
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath("MovingBox:position")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0, 3, 6),
+"transitions": PackedFloat32Array(-2, -2, -2),
+"update": 0,
+"values": [Vector3(0, 2, 10), Vector3(-5.20189, 2, 12.7464), Vector3(-0.764091, 6.11944, 20.2665)]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath("MovingBox:rotation")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0, 3, 6),
+"transitions": PackedFloat32Array(-2, -2, -2),
+"update": 0,
+"values": [Vector3(0, 0, 0), Vector3(0, 0.784368, 0), Vector3(-0.33128, 0.307663, 0.797063)]
+}
+tracks/2/type = "value"
+tracks/2/imported = false
+tracks/2/enabled = true
+tracks/2/path = NodePath("MovingBox:scale")
+tracks/2/interp = 1
+tracks/2/loop_wrap = true
+tracks/2/keys = {
+"times": PackedFloat32Array(0, 3, 6),
+"transitions": PackedFloat32Array(-2, -2, -2),
+"update": 0,
+"values": [Vector3(1, 1, 1), Vector3(1, 1, 1), Vector3(3, 3, 3)]
+}
+
+[sub_resource type="BoxMesh" id="BoxMesh_fi43t"]
+
+[sub_resource type="FogMaterial" id="FogMaterial_ktn3i"]
+albedo = Color(0, 0, 4, 1)
+edge_fade = 0.0
+
+[sub_resource type="FogMaterial" id="FogMaterial_yomn8"]
+density = 2.0
+emission = Color(0, 0.501961, 1, 1)
+edge_fade = 0.0
+density_texture = ExtResource( "2_8fjmj" )
+
+[node name="Node3D" type="Node3D"]
+
+[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
+environment = SubResource( "Environment_gsgar" )
+
+[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
+transform = Transform3D(-0.592126, -0.697883, 0.402923, -1.19487e-09, 0.5, 0.866026, -0.805846, 0.512796, -0.296063, 0, 0, 0)
+shadow_enabled = true
+shadow_bias = 0.12
+directional_shadow_max_distance = 250.0
+
+[node name="Camera3D" type="Camera3D" parent="."]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -8, 6, 18)
+script = ExtResource( "1_mfjvp" )
+
+[node name="Label" type="Label" parent="Camera3D"]
+offset_left = 16.0
+offset_top = 16.0
+offset_right = 812.0
+offset_bottom = 299.0
+theme_override_colors/font_shadow_color = Color(0, 0, 0, 0.501961)
+theme_override_constants/shadow_offset_x = 2
+theme_override_constants/shadow_offset_y = 2
+theme_override_constants/shadow_outline_size = 0
+text = "Temporal reprojection: Disabled"
+__meta__ = {
+"_edit_use_anchors_": false
+}
+
+[node name="HelpLabel" type="Label" parent="Camera3D"]
+anchor_top = 1.0
+anchor_bottom = 1.0
+offset_left = 16.0
+offset_top = -369.0
+offset_right = 909.0
+offset_bottom = -16.0
+grow_vertical = 0
+theme_override_colors/font_shadow_color = Color(0, 0, 0, 0.501961)
+theme_override_constants/shadow_offset_x = 2
+theme_override_constants/shadow_offset_y = 2
+theme_override_constants/shadow_outline_size = 0
+text = "W/A/S/D/Mouse: Move
+Left/Right arrows: Adjust global fog density
+Space: Toggle temporal reprojection
+Up/Down arrows or mouse wheel: Adjust temporal reprojection intensity"
+__meta__ = {
+"_edit_use_anchors_": false
+}
+
+[node name="Ground" type="CSGBox3D" parent="."]
+size = Vector3(150, 2, 150)
+
+[node name="Ground2" type="CSGBox3D" parent="Ground"]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.282, 0, 5.62229)
+operation = 2
+size = Vector3(3, 2, 4)
+
+[node name="Ground3" type="CSGBox3D" parent="Ground"]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -7.87312, 0, 2.69763)
+operation = 2
+size = Vector3(3, 2, 4)
+
+[node name="CSGBox3D" type="CSGBox3D" parent="."]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 5, 0)
+size = Vector3(8, 8, 8)
+
+[node name="CSGBox3D" type="CSGBox3D" parent="CSGBox3D"]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.4)
+operation = 2
+size = Vector3(7.5, 7.5, 7.5)
+
+[node name="FogVolumeNegativeDensity" type="FogVolume" parent="."]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 5, 0)
+extents = Vector3(4, 4, 4)
+material = SubResource( "FogMaterial_sfd8y" )
+
+[node name="FogVolumeEllipsoid" type="FogVolume" parent="."]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -13, 6, 6)
+extents = Vector3(2, 2, 2)
+shape = 0
+material = SubResource( "FogMaterial_v1f5u" )
+
+[node name="FogVolumeEllipsoidHeightFalloff" type="FogVolume" parent="."]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -13, 6, 2)
+extents = Vector3(2, 2, 2)
+shape = 0
+material = SubResource( "FogMaterial_blauf" )
+
+[node name="FogVolumeBox" type="FogVolume" parent="."]
+transform = Transform3D(0.707107, 0.5, -0.5, 0, 0.707107, 0.707107, 0.707107, -0.5, 0.5, -7.5189, 4.42465, -2.97368)
+extents = Vector3(2, 2, 2)
+material = SubResource( "FogMaterial_yvnd5" )
+
+[node name="FogVolumeBoxHeightFalloff" type="FogVolume" parent="."]
+transform = Transform3D(0.707107, 0.5, -0.5, 0, 0.707107, 0.707107, 0.707107, -0.5, 0.5, -7.5189, 4.42465, -7.97368)
+extents = Vector3(2, 2, 2)
+material = SubResource( "FogMaterial_gcgmm" )
+
+[node name="OmniLight3D" type="OmniLight3D" parent="."]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.823152, 1.836, 4.31818)
+light_color = Color(1, 0.929412, 0, 1)
+light_energy = 2.0
+omni_range = 6.0
+
+[node name="OmniLight3DShadow" type="OmniLight3D" parent="."]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5.82315, 1.836, 4.31818)
+light_color = Color(1, 0.929412, 0, 1)
+light_energy = 2.0
+shadow_enabled = true
+omni_range = 6.0
+
+[node name="SpotLight3D" type="SpotLight3D" parent="."]
+transform = Transform3D(0.966384, -0.226046, -0.1225, 0, 0.476461, -0.879196, 0.257105, 0.84964, 0.460444, -7.19085, -3.7099, 10.7572)
+light_color = Color(0, 0.439216, 1, 1)
+light_energy = 4.0
+
+[node name="FogVolumeAlbedoTweak" type="FogVolume" parent="."]
+transform = Transform3D(-0.89393, -0.0897075, -0.439138, 0, 0.979766, -0.200148, 0.448207, -0.178918, -0.875842, -15.8913, -15.118, 8.26876)
+extents = Vector3(4, 4, 4)
+material = SubResource( "FogMaterial_8xcc6" )
+
+[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
+autoplay = "move_fog_volume"
+anims/RESET = SubResource( "Animation_jg7qq" )
+anims/move_fog_volume = SubResource( "Animation_axnf8" )
+
+[node name="MovingBox" type="MeshInstance3D" parent="."]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 10)
+mesh = SubResource( "BoxMesh_fi43t" )
+
+[node name="FogVolumeBlue" type="FogVolume" parent="MovingBox"]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0)
+material = SubResource( "FogMaterial_ktn3i" )
+
+[node name="FogVolumeTexture3D" type="FogVolume" parent="."]
+transform = Transform3D(-2.98023e-08, 4.82913e-08, -1, -4.2222e-08, -1, -4.82913e-08, -1, 4.2222e-08, -1.49012e-08, 17, 17, 12)
+extents = Vector3(16, 16, 2)
+material = SubResource( "FogMaterial_yomn8" )