diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 8ad74f7..0000000 --- a/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Normalize EOL for all files that Git considers text files. -* text=auto eol=lf diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..2bd50bd --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "addons/rokojori_action_library"] + path = addons/rokojori_action_library + url = git@community.rokojori.com:Rokojori/rj-action-library.git diff --git a/Examples/07 VFX/Flash.tscn b/Examples/07 VFX/Flash.tscn new file mode 100644 index 0000000..56db116 --- /dev/null +++ b/Examples/07 VFX/Flash.tscn @@ -0,0 +1,532 @@ +[gd_scene load_steps=69 format=4 uid="uid://dk0p4j4bvakwj"] + +[ext_resource type="Shader" path="res://Packed/Setup/Sky.gdshader" id="1_1r6xr"] +[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Networking/NetworkManager.cs" id="1_cotb1"] +[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Time/TimeLineManager.cs" id="2_nw41q"] +[ext_resource type="Resource" uid="uid://ch5nsa6yafs5l" path="res://addons/rokojori_action_library/Runtime/Time/TimeLines/GameTime.tres" id="3_bdt4g"] +[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/VirtualCameras/VirtualCamera3DManager.cs" id="3_vvibv"] +[ext_resource type="Resource" uid="uid://h6oi6vkj4c2m" path="res://addons/rokojori_action_library/Runtime/Time/TimeLines/RealTime.tres" id="4_ebxbo"] +[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/VirtualCameras/VirtualCamera3DSlot.cs" id="4_kf4jw"] +[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Sensors/SensorManager.cs" id="5_8nqa6"] +[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Time/TimeLineScheduler.cs" id="5_ianp2"] +[ext_resource type="Resource" uid="uid://c5rvf5v86ybks" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/PC/Default-Sensors-PC.tres" id="6_bp8o6"] +[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/VirtualCameras/MouseEditorCamera.cs" id="7_ay8es"] +[ext_resource type="Resource" uid="uid://cbqyav0cnehoq" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/PC/Mouse Button Right.tres" id="8_5j0f3"] +[ext_resource type="Resource" uid="uid://b8u374emi528p" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/PC/Mouse Button Middle.tres" id="9_h22ns"] +[ext_resource type="Resource" uid="uid://b52horrdbgyaa" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/PC/Mouse Wheel Up.tres" id="10_72ia5"] +[ext_resource type="Resource" uid="uid://chwstub7bnlpp" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/PC/Mouse Wheel Down.tres" id="11_guwwl"] +[ext_resource type="Resource" uid="uid://c73afpa00tr65" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/PC/Mouse Editor Camera/Move Forward.tres" id="12_y2v4h"] +[ext_resource type="Resource" uid="uid://cwoisyc1in6ew" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/PC/Mouse Editor Camera/Move Back.tres" id="13_tij1x"] +[ext_resource type="Resource" uid="uid://dfrnedeefk0qk" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/PC/Mouse Editor Camera/Move Left.tres" id="14_dbcdy"] +[ext_resource type="Resource" uid="uid://cbsltqawsp4yy" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/PC/Mouse Editor Camera/Move Right.tres" id="15_f3i0c"] +[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Procedural/Parametric/Cuboid/Cuboid.cs" id="18_6u4rt"] +[ext_resource type="Resource" uid="uid://cslvcweyejh3c" path="res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_camera_movement_component.tres" id="19_e3v8v"] +[ext_resource type="Material" uid="uid://ctut88k70n35x" path="res://Packed/Setup/Dark-Ground.material" id="19_ku7o3"] +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor.gd" id="19_tywpm"] +[ext_resource type="Resource" uid="uid://iru8ynu04i00" path="res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_camera_rotation_component.tres" id="20_vftno"] +[ext_resource type="Resource" uid="uid://rp3mpjmisoyh" path="res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_object_movement_component.tres" id="21_08scy"] +[ext_resource type="Resource" uid="uid://c8ulad7utgrg7" path="res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processing_stage.tres" id="22_a05i4"] +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processor.gd" id="23_l457c"] +[ext_resource type="Resource" uid="uid://ca45noqewsyvp" path="res://addons/SphynxMotionBlurToolkit/Guertin/guertin_experimental_blur_stage.tres" id="24_t7ens"] +[ext_resource type="Resource" uid="uid://cvb65hfs2lrxo" path="res://addons/SphynxMotionBlurToolkit/Guertin/guertin_neighbor_max_stage.tres" id="25_r57r8"] +[ext_resource type="Resource" uid="uid://bidsfymvdyhek" path="res://addons/SphynxMotionBlurToolkit/Guertin/guertin_overlay_stage.tres" id="26_4aidb"] +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/Guertin/new_guertin_motion_blur.gd" id="27_x1n0l"] +[ext_resource type="Resource" uid="uid://dipvwksvqb3dm" path="res://addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_max_x_stage.tres" id="28_0pyew"] +[ext_resource type="Resource" uid="uid://bxfg45ubc2pv7" path="res://addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_max_y_stage.tres" id="29_ae74o"] +[ext_resource type="Resource" uid="uid://bqehecsdgt70s" path="res://addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_variance_stage.tres" id="30_jph5g"] +[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Sensors/OnSensor.cs" id="34_8e6hy"] +[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Interactions/Pointer.cs" id="34_axy5m"] +[ext_resource type="PackedScene" uid="uid://igjwcq828c3x" path="res://Packed/Character/character.glb" id="34_iqgaf"] +[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Actions/OnProcess.cs" id="35_3nues"] +[ext_resource type="Resource" uid="uid://ci42d04kv03yx" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/PC/Mouse Button Left.tres" id="35_gwiry"] +[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Interactions/MultiRayCaster.cs" id="35_m4st3"] +[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Actions/ActionList.cs" id="36_48c1t"] +[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Actions/Node3D/CopyMousePosition.cs" id="36_okrhi"] +[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/Flash/Flash.cs" id="37_jrcib"] +[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Actions/Node3D/LookAt.cs" id="37_ra6bk"] +[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Interactions/Pointable.cs" id="38_iknbl"] +[ext_resource type="Resource" uid="uid://bfxwx0fiejnk3" path="res://addons/rokojori_action_library/Runtime/Animation/Flash/Presets/Blue Shield - Flash.tres" id="39_1edeu"] +[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Interactions/Interactor.cs" id="39_ovot1"] +[ext_resource type="Shader" uid="uid://bmgpmbthlfon3" path="res://addons/rokojori_action_library/Runtime/Shading/Shaders/Effects/Outline/Outline.tres" id="43_vsqdy"] +[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Interactions/Interactable.cs" id="44_4apug"] + +[sub_resource type="Gradient" id="Gradient_lfbf4"] +offsets = PackedFloat32Array(0.390947, 0.44856, 0.469136, 0.534979, 0.711934, 0.851852) +colors = PackedColorArray(0, 0, 0, 1, 0.05252, 0.0556525, 0.253, 1, 0.0875333, 0.277933, 0.421667, 1, 0.0252, 0.0381, 0.18, 1, 0.07, 0, 0.0373333, 1, 0, 0, 0, 1) + +[sub_resource type="GradientTexture2D" id="GradientTexture2D_rim8p"] +gradient = SubResource("Gradient_lfbf4") +fill_from = Vector2(0, 1) +fill_to = Vector2(0, 0) + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_176xm"] +shader = ExtResource("1_1r6xr") +shader_parameter/vertical_sections = 20 +shader_parameter/star_size = 0.02 +shader_parameter/star_falloff = 6.865 +shader_parameter/margin = 0.965 +shader_parameter/starOpacity = 1.0 +shader_parameter/starsNoiseScale = 1.0 +shader_parameter/starsNoiseDivision = 100001.0 +shader_parameter/starsNoiseOffset = Vector2(25.97, 0.01) +shader_parameter/verticalColor = SubResource("GradientTexture2D_rim8p") + +[sub_resource type="Sky" id="Sky_6f3cg"] +sky_material = SubResource("ShaderMaterial_176xm") + +[sub_resource type="Environment" id="Environment_2m3qe"] +background_mode = 2 +background_energy_multiplier = 0.5 +sky = SubResource("Sky_6f3cg") +ambient_light_color = Color(0.226068, 0.225418, 0.308594, 1) +tonemap_mode = 2 +tonemap_exposure = 3.47 +tonemap_white = 5.47 +ssao_enabled = true +ssao_intensity = 3.0 +ssao_light_affect = 1.0 +ssao_ao_channel_affect = 1.0 +fog_enabled = true +fog_light_color = Color(0.0313726, 0.121569, 0.258824, 1) +fog_density = 0.003 +fog_sky_affect = 0.0 + +[sub_resource type="CameraAttributesPractical" id="CameraAttributesPractical_0tow3"] +dof_blur_near_enabled = true + +[sub_resource type="CompositorEffect" id="CompositorEffect_4lfo8"] +resource_local_to_scene = false +resource_name = "" +enabled = true +effect_callback_type = 4 +needs_motion_vectors = false +needs_normal_roughness = false +script = ExtResource("23_l457c") +pre_blur_processor_stage = ExtResource("22_a05i4") +camera_rotation_component = ExtResource("20_vftno") +camera_movement_component = ExtResource("19_e3v8v") +object_movement_component = ExtResource("21_08scy") +debug = false + +[sub_resource type="CompositorEffect" id="CompositorEffect_2sxnw"] +resource_local_to_scene = false +resource_name = "" +enabled = true +effect_callback_type = 4 +needs_motion_vectors = false +needs_normal_roughness = false +script = ExtResource("27_x1n0l") +blur_stage = ExtResource("24_t7ens") +overlay_stage = ExtResource("26_4aidb") +tile_max_x_stage = ExtResource("28_0pyew") +tile_max_y_stage = ExtResource("29_ae74o") +neighbor_max_stage = ExtResource("25_r57r8") +tile_variance_stage = ExtResource("30_jph5g") +tile_size = 40 +linear_falloff_slope = 1.0 +importance_bias = 40.0 +maximum_jitter_value = 0.95 +minimum_user_threshold = 1.5 +debug = false + +[sub_resource type="Compositor" id="Compositor_osc1s"] +compositor_effects = Array[CompositorEffect]([SubResource("CompositorEffect_4lfo8"), SubResource("CompositorEffect_2sxnw")]) +script = ExtResource("19_tywpm") +samples = 32 +intensity = 0.5 +center_fade = 0.445 +framerate_independent = true +uncapped_independence = false +target_constant_framerate = 30.0 + +[sub_resource type="ArrayMesh" id="ArrayMesh_5gsj3"] +_surfaces = [{ +"aabb": AABB(-0.5, -0.5, -0.5, 1, 1, 1), +"attribute_data": PackedByteArray("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), +"format": 34359742487, +"index_count": 132, +"index_data": PackedByteArray("AgABAAAAAQACAAMADgAFAAYABQAOAA0AEwAHAAsABwATAA8ADAAIAAQACAAMABAAEQAKAAkACgARABIADwAGAAcABgAPAA4AEgALAAoACwASABMAEAAJAAgACQAQABEADQAEAAUABAANAAwAAAAFAAQADAANABQAAQAHAAYADgAPABUAAgAIAAkAEQAQABYAAwAKAAsAEwASABcABgAAAAEAAAAGAAUADQAVABQAFQANAA4ACwABAAMAAQALAAcADwAXABUAFwAPABMACQADAAIAAwAJAAoAEgAWABcAFgASABEABAACAAAAAgAEAAgAEAAUABYAFAAQAAwAFwAUABUAFAAXABYA"), +"primitive": 3, +"uv_scale": Vector4(0, 0, 0, 0), +"vertex_count": 24, +"vertex_data": PackedByteArray("ZmbmvgAAAD9mZuY+ZmbmPgAAAD9mZuY+ZmbmvgAAAD9mZua+ZmbmPgAAAD9mZua+AAAAv2Zm5j5mZuY+ZmbmvmZm5j4AAAA/ZmbmPmZm5j4AAAA/AAAAP2Zm5j5mZuY+AAAAv2Zm5j5mZua+ZmbmvmZm5j4AAAC/ZmbmPmZm5j4AAAC/AAAAP2Zm5j5mZua+AAAAv2Zm5r5mZuY+ZmbmvmZm5r4AAAA/ZmbmPmZm5r4AAAA/AAAAP2Zm5r5mZuY+AAAAv2Zm5r5mZua+ZmbmvmZm5r4AAAC/ZmbmPmZm5r4AAAC/AAAAP2Zm5r5mZua+ZmbmvgAAAL9mZuY+ZmbmPgAAAL9mZuY+ZmbmvgAAAL9mZua+ZmbmPgAAAL9mZua+/3///wAA/7//f///AAD/v/9///8AAP+//3///wAA/78AAP9//3//v/9//3//fwCA/3//f/9/AID///9//3//vwAA/3//f/+///////9/AID//////38AgP///3//f/+/AAD/f/9//7//f/9//38AgP9//3//fwCA////f/9//78AAP9//3//v///////fwCA//////9/AID///9//3//v/9/AAAAAP+//38AAAAA/7//fwAAAAD/v/9/AAAAAP+/") +}] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_ak8yx"] +render_priority = 0 +shader = ExtResource("43_vsqdy") +shader_parameter/albedo = Color(1, 1, 1, 1) +shader_parameter/sizeClose = 1.0 +shader_parameter/sizeFar = 0.0 +shader_parameter/closeDistance = 5.0 +shader_parameter/farDistance = 50.0 + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_evgdl"] +frequency = 0.0054 +fractal_lacunarity = 2.555 + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_7uutl"] +width = 2048 +height = 2048 +seamless = true +as_normal_map = true +noise = SubResource("FastNoiseLite_evgdl") + +[sub_resource type="Gradient" id="Gradient_e5v7b"] + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_8pji8"] +frequency = 0.0073 + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_rbhss"] +seamless = true +color_ramp = SubResource("Gradient_e5v7b") +noise = SubResource("FastNoiseLite_8pji8") + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_kc4hg"] +next_pass = SubResource("ShaderMaterial_ak8yx") +albedo_color = Color(0.15625, 0.0756836, 0.0756836, 1) +metallic = 0.47 +metallic_specular = 0.25 +roughness_texture = SubResource("NoiseTexture2D_rbhss") +normal_enabled = true +normal_texture = SubResource("NoiseTexture2D_7uutl") +uv1_triplanar = true + +[sub_resource type="BoxShape3D" id="BoxShape3D_tgb73"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_mmiv8"] +albedo_color = Color(0.15625, 0.0756836, 0.0756836, 1) +metallic = 0.47 +metallic_specular = 0.25 +roughness_texture = SubResource("NoiseTexture2D_rbhss") +normal_enabled = true +normal_texture = SubResource("NoiseTexture2D_7uutl") +uv1_triplanar = true + +[node name="Flash" type="Node3D"] + +[node name="App Setup" type="Node3D" parent="."] + +[node name="NetworkManager" type="Node" parent="App Setup"] +script = ExtResource("1_cotb1") + +[node name="TimeLineManager" type="Node" parent="App Setup"] +script = ExtResource("2_nw41q") +timeLines = [ExtResource("3_bdt4g"), ExtResource("4_ebxbo")] +gameTimeTimeLine = ExtResource("3_bdt4g") +realTimeTimeLine = ExtResource("4_ebxbo") + +[node name="TimeLineScheduler" type="Node" parent="App Setup/TimeLineManager"] +script = ExtResource("5_ianp2") + +[node name="SensorManager" type="Node" parent="App Setup"] +script = ExtResource("5_8nqa6") +sensors = [] +sensorGroups = [ExtResource("6_bp8o6")] +processSensors = true + +[node name="VirtualCamera3DManager" type="Node" parent="App Setup" node_paths=PackedStringArray("camera")] +script = ExtResource("3_vvibv") +camera = NodePath("../Main Camera") +active = true + +[node name="Slot 1" type="Node" parent="App Setup/VirtualCamera3DManager" node_paths=PackedStringArray("camera")] +script = ExtResource("4_kf4jw") +camera = NodePath("../../Mouse Editor Camera") +priority = 1.0 + +[node name="Main Camera" type="Camera3D" parent="App Setup"] +transform = Transform3D(-1, 3.23243e-08, -8.12273e-08, 0, 0.929133, 0.369747, 8.74228e-08, 0.369747, -0.929133, 0, 3.69746, -9.2913) +fov = 60.0 + +[node name="Mouse Editor Camera" type="Node3D" parent="App Setup"] +transform = Transform3D(1, 0, 0, 0, 0.92913, -0.369746, 0, 0.369746, 0.92913, 0, 3.69746, -9.2913) +script = ExtResource("7_ay8es") +pitch = 21.7 +yawSpeed = -1.0 +orbitButton = ExtResource("8_5j0f3") +orbitModifierButtons = [] +panSpeedX = 0.005 +panSpeedY = 0.005 +panButton = ExtResource("9_h22ns") +panModifierButtons = [] +zoomInButton = ExtResource("11_guwwl") +zoomInModifierButtons = [] +zoomOutButton = ExtResource("10_72ia5") +zoomOutModifierButtons = [] +forwardButton = ExtResource("12_y2v4h") +backwardsButton = ExtResource("13_tij1x") +leftButton = ExtResource("14_dbcdy") +rightButton = ExtResource("15_f3i0c") + +[node name="Dark Scene" type="Node3D" parent="App Setup"] + +[node name="Dark World Environment" type="WorldEnvironment" parent="App Setup/Dark Scene"] +environment = SubResource("Environment_2m3qe") +camera_attributes = SubResource("CameraAttributesPractical_0tow3") +compositor = SubResource("Compositor_osc1s") + +[node name="Dark Ground" type="CSGBox3D" parent="App Setup/Dark Scene"] +transform = Transform3D(0.991132, 0, -0.132879, 0, 1, 0, 0.132879, 0, 0.991132, 0, -0.5, 0) +size = Vector3(4000, 1, 4000) +material = ExtResource("19_ku7o3") + +[node name="OmniLight3D" type="OmniLight3D" parent="App Setup/Dark Scene"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 6.322, 0) +light_color = Color(0.980469, 0.344696, 0, 1) +light_energy = 16.0 +shadow_enabled = true +omni_range = 40.101 +omni_attenuation = 0.5 + +[node name="OmniLight3D2" type="OmniLight3D" parent="App Setup/Dark Scene"] +transform = Transform3D(-0.443768, 0.0327227, 0.895544, 0.0719348, 0.997409, -0.000798984, -0.89325, 0.0640662, -0.444972, 0, 3.482, 0) +light_color = Color(0.929688, 0.73239, 0.265106, 1) +light_energy = 16.0 +light_indirect_energy = 3.56 +light_volumetric_fog_energy = 1.465 +shadow_enabled = true +omni_range = 7.851 +omni_attenuation = 0.5 + +[node name="OmniLight3D3" type="OmniLight3D" parent="App Setup/Dark Scene"] +transform = Transform3D(-0.443768, 0.0327227, 0.895544, 0.0719348, 0.997409, -0.000798984, -0.89325, 0.0640662, -0.444972, 0, 3.482, 0) +light_color = Color(0.941406, 0.939854, 0.842117, 1) +light_energy = 16.0 +light_indirect_energy = 3.56 +light_volumetric_fog_energy = 1.465 +shadow_enabled = true +omni_range = 5.461 +omni_attenuation = 0.5 + +[node name="OmniLight3D5" type="OmniLight3D" parent="App Setup/Dark Scene"] +transform = Transform3D(-0.443768, 0.0327227, 0.895544, 0.0719348, 0.997409, -0.000799021, -0.89325, 0.0640662, -0.444972, 5.789, 3.482, -3.48577) +light_color = Color(0.733017, 0.891285, 0.933594, 1) +light_indirect_energy = 3.56 +light_volumetric_fog_energy = 1.465 +shadow_enabled = true +omni_range = 12.358 +omni_attenuation = 0.5 + +[node name="OmniLight3D6" type="OmniLight3D" parent="App Setup/Dark Scene"] +transform = Transform3D(-0.443768, 0.0327227, 0.895544, 0.0719348, 0.997409, -0.000799021, -0.89325, 0.0640662, -0.444972, 6.2227, 3.482, 4.10247) +light_color = Color(0.911762, 0.957031, 0.770111, 1) +light_indirect_energy = 3.56 +light_volumetric_fog_energy = 1.465 +shadow_enabled = true +omni_range = 14.376 +omni_attenuation = 0.0 + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="App Setup/Dark Scene"] +transform = Transform3D(-0.442868, 0, 0.896587, 0, 1, 0, -0.896587, 0, -0.442868, 0, 0, 0) +light_color = Color(0.0835571, 0.114468, 0.578125, 1) +light_energy = 3.665 +shadow_enabled = true + +[node name="OmniLight3D4" type="OmniLight3D" parent="App Setup/Dark Scene"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5.4893, -0.364594, 0.850517) + +[node name="Interactions" type="Node" parent="App Setup"] + +[node name="Pointer" type="Node3D" parent="App Setup/Interactions" node_paths=PackedStringArray("caster")] +script = ExtResource("34_axy5m") +caster = NodePath("../RayCaster/MultiRayCaster") + +[node name="RayCaster" type="Node" parent="App Setup/Interactions"] + +[node name="MultiRayCaster" type="Node3D" parent="App Setup/Interactions/RayCaster"] +transform = Transform3D(0.99992, 0, -0.012627, 0, 1, 0, 0.012627, 0, 0.99992, 0, 0, 14.254) +script = ExtResource("35_m4st3") +rayLength = 1000.0 + +[node name="Look At Target" type="Node3D" parent="App Setup/Interactions/RayCaster"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.18, 0, 0) + +[node name="Update RayCaster" type="Node" parent="App Setup/Interactions/RayCaster" node_paths=PackedStringArray("actions")] +script = ExtResource("35_3nues") +actions = [] +executeInEditor = true + +[node name="Set RayCaster Position" type="Node" parent="App Setup/Interactions/RayCaster/Update RayCaster" node_paths=PackedStringArray("camera", "target")] +script = ExtResource("36_okrhi") +camera = NodePath("../../../../Main Camera") +target = NodePath("../../MultiRayCaster") + +[node name="Set RayCaster Look Target" type="Node" parent="App Setup/Interactions/RayCaster/Update RayCaster" node_paths=PackedStringArray("camera", "target")] +script = ExtResource("36_okrhi") +camera = NodePath("../../../../Main Camera") +depth = 1000.0 +target = NodePath("../../Look At Target") + +[node name="RayCaster Look At Target" type="Node" parent="App Setup/Interactions/RayCaster/Update RayCaster" node_paths=PackedStringArray("lookFrom", "lookTarget")] +script = ExtResource("37_ra6bk") +lookFrom = NodePath("../../MultiRayCaster") +lookTarget = NodePath("../../Look At Target") + +[node name="Interactor" type="Node3D" parent="App Setup/Interactions" node_paths=PackedStringArray("pointer")] +script = ExtResource("39_ovot1") +pointer = NodePath("../Pointer") +button = ExtResource("35_gwiry") + +[node name="Node3D" type="Node3D" parent="."] + +[node name="character" parent="Node3D" instance=ExtResource("34_iqgaf")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4.18049, 0, 3.50792) + +[node name="Cuboid4" type="Node3D" parent="Node3D" node_paths=PackedStringArray("output")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.91883, 4.76837e-07, 1.61163) +script = ExtResource("18_6u4rt") +borderSize = 0.05 +output = NodePath("MeshInstance3D") +metadata/_edit_group_ = true + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Node3D/Cuboid4"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) +mesh = SubResource("ArrayMesh_5gsj3") +surface_material_override/0 = SubResource("StandardMaterial3D_kc4hg") + +[node name="StaticBody3D" type="StaticBody3D" parent="Node3D/Cuboid4"] + +[node name="CollisionShape3D" type="CollisionShape3D" parent="Node3D/Cuboid4/StaticBody3D"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.518866, 0) +shape = SubResource("BoxShape3D_tgb73") + +[node name="Pointable" type="Node3D" parent="Node3D/Cuboid4/StaticBody3D"] +script = ExtResource("38_iknbl") + +[node name="Interactable" type="Node3D" parent="Node3D/Cuboid4/StaticBody3D" node_paths=PackedStringArray("onInteraction")] +script = ExtResource("44_4apug") +onInteraction = NodePath("../../../OnSensor/ActionList") + +[node name="OnSensor" type="Node" parent="Node3D" node_paths=PackedStringArray("onStart")] +script = ExtResource("34_8e6hy") +sensor = ExtResource("35_gwiry") +onStart = NodePath("ActionList") + +[node name="ActionList" type="Node" parent="Node3D/OnSensor" node_paths=PackedStringArray("actions")] +script = ExtResource("36_48c1t") +actions = [] + +[node name="Flash" type="Node" parent="Node3D/OnSensor/ActionList" node_paths=PackedStringArray("targets")] +script = ExtResource("37_jrcib") +flashEffect = ExtResource("39_1edeu") +targets = [NodePath("../../../character/Armature/Skeleton3D/Beta_Joints"), NodePath("../../../character/Armature/Skeleton3D/Beta_Surface")] + +[node name="Cubes" type="Node3D" parent="Node3D"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.24594, -4.76837e-07, -3.11724) + +[node name="Cuboid" type="Node3D" parent="Node3D/Cubes" node_paths=PackedStringArray("output")] +transform = Transform3D(0.972018, 0, -0.234905, 0, 1, 0, 0.234905, 0, 0.972018, -0.61298, 4.76837e-07, -0.0393667) +script = ExtResource("18_6u4rt") +borderSize = 0.05 +output = NodePath("MeshInstance3D") +metadata/_edit_group_ = true + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Node3D/Cubes/Cuboid"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) +mesh = SubResource("ArrayMesh_5gsj3") +surface_material_override/0 = SubResource("StandardMaterial3D_mmiv8") + +[node name="Cuboid3" type="Node3D" parent="Node3D/Cubes" node_paths=PackedStringArray("output")] +transform = Transform3D(0.972018, 0, -0.234905, 0, 1, 0, 0.234905, 0, 0.972018, 0.095506, 1, 0.0459044) +script = ExtResource("18_6u4rt") +borderSize = 0.05 +output = NodePath("MeshInstance3D") +metadata/_edit_group_ = true + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Node3D/Cubes/Cuboid3"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) +mesh = SubResource("ArrayMesh_5gsj3") +surface_material_override/0 = SubResource("StandardMaterial3D_mmiv8") + +[node name="Cuboid2" type="Node3D" parent="Node3D/Cubes" node_paths=PackedStringArray("output")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.66897, 4.76837e-07, 0.252781) +script = ExtResource("18_6u4rt") +borderSize = 0.05 +output = NodePath("MeshInstance3D") +metadata/_edit_group_ = true + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Node3D/Cubes/Cuboid2"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) +mesh = SubResource("ArrayMesh_5gsj3") +surface_material_override/0 = SubResource("StandardMaterial3D_mmiv8") + +[node name="Cubes2" type="Node3D" parent="Node3D"] +transform = Transform3D(0.497398, 0, -0.867522, 0, 1, 0, 0.867522, 0, 0.497398, 8.95531, 0, -1.18651) + +[node name="Cuboid" type="Node3D" parent="Node3D/Cubes2" node_paths=PackedStringArray("output")] +transform = Transform3D(0.972018, 0, -0.234905, 0, 1, 0, 0.234905, 0, 0.972018, -0.61298, 4.76837e-07, -0.0393667) +script = ExtResource("18_6u4rt") +borderSize = 0.05 +output = NodePath("MeshInstance3D") +metadata/_edit_group_ = true + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Node3D/Cubes2/Cuboid"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) +mesh = SubResource("ArrayMesh_5gsj3") +surface_material_override/0 = SubResource("StandardMaterial3D_mmiv8") + +[node name="Cuboid3" type="Node3D" parent="Node3D/Cubes2" node_paths=PackedStringArray("output")] +transform = Transform3D(0.972018, 0, -0.234905, 0, 1, 0, 0.234905, 0, 0.972018, 0.095506, 1, 0.0459044) +script = ExtResource("18_6u4rt") +borderSize = 0.05 +output = NodePath("MeshInstance3D") +metadata/_edit_group_ = true + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Node3D/Cubes2/Cuboid3"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) +mesh = SubResource("ArrayMesh_5gsj3") +surface_material_override/0 = SubResource("StandardMaterial3D_mmiv8") + +[node name="Cuboid2" type="Node3D" parent="Node3D/Cubes2" node_paths=PackedStringArray("output")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.66897, 4.76837e-07, 0.252781) +script = ExtResource("18_6u4rt") +borderSize = 0.05 +output = NodePath("MeshInstance3D") +metadata/_edit_group_ = true + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Node3D/Cubes2/Cuboid2"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) +mesh = SubResource("ArrayMesh_5gsj3") +surface_material_override/0 = SubResource("StandardMaterial3D_mmiv8") + +[node name="Cubes3" type="Node3D" parent="Node3D"] +transform = Transform3D(0.497398, 0, -0.867522, 0, 1, 0, 0.867522, 0, 0.497398, 12.234, -4.76837e-07, 4.21264) + +[node name="Cuboid" type="Node3D" parent="Node3D/Cubes3" node_paths=PackedStringArray("output")] +transform = Transform3D(0.972018, 0, -0.234905, 0, 1, 0, 0.234905, 0, 0.972018, -0.61298, 4.76837e-07, -0.0393667) +script = ExtResource("18_6u4rt") +borderSize = 0.05 +output = NodePath("MeshInstance3D") +metadata/_edit_group_ = true + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Node3D/Cubes3/Cuboid"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) +mesh = SubResource("ArrayMesh_5gsj3") +surface_material_override/0 = SubResource("StandardMaterial3D_mmiv8") + +[node name="Cuboid3" type="Node3D" parent="Node3D/Cubes3" node_paths=PackedStringArray("output")] +transform = Transform3D(0.972018, 0, -0.234905, 0, 1, 0, 0.234905, 0, 0.972018, 0.095506, 1, 0.0459044) +script = ExtResource("18_6u4rt") +borderSize = 0.05 +output = NodePath("MeshInstance3D") +metadata/_edit_group_ = true + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Node3D/Cubes3/Cuboid3"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) +mesh = SubResource("ArrayMesh_5gsj3") +surface_material_override/0 = SubResource("StandardMaterial3D_mmiv8") + +[node name="Cuboid2" type="Node3D" parent="Node3D/Cubes3" node_paths=PackedStringArray("output")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.66897, 4.76837e-07, 0.252781) +script = ExtResource("18_6u4rt") +borderSize = 0.05 +output = NodePath("MeshInstance3D") +metadata/_edit_group_ = true + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Node3D/Cubes3/Cuboid2"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) +mesh = SubResource("ArrayMesh_5gsj3") +surface_material_override/0 = SubResource("StandardMaterial3D_mmiv8") + +[editable path="Node3D/character"] diff --git a/Packed/Character/character.glb b/Packed/Character/character.glb new file mode 100644 index 0000000..06fc0f1 Binary files /dev/null and b/Packed/Character/character.glb differ diff --git a/Packed/Character/character.glb.import b/Packed/Character/character.glb.import new file mode 100644 index 0000000..227f74c --- /dev/null +++ b/Packed/Character/character.glb.import @@ -0,0 +1,36 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://igjwcq828c3x" +path="res://.godot/imported/character.glb-190f43fac2eac45ced86d26ad400c4a7.scn" + +[deps] + +source_file="res://Packed/Character/character.glb" +dest_files=["res://.godot/imported/character.glb-190f43fac2eac45ced86d26ad400c4a7.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +_subresources={} +gltf/naming_version=1 +gltf/embedded_image_handling=1 diff --git a/Packed/Setup/Dark-Ground.material b/Packed/Setup/Dark-Ground.material new file mode 100644 index 0000000..6eb4f33 Binary files /dev/null and b/Packed/Setup/Dark-Ground.material differ diff --git a/Packed/Setup/Sky.gdshader b/Packed/Setup/Sky.gdshader new file mode 100644 index 0000000..6018ec4 --- /dev/null +++ b/Packed/Setup/Sky.gdshader @@ -0,0 +1,53 @@ +shader_type sky; + +#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Math.gdshaderinc" +#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Transform.gdshaderinc" +#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Noise.gdshaderinc" + +uniform int vertical_sections = 21; +uniform float star_size = 0.02; +uniform float star_falloff = 4.; +uniform float margin = 0.05; // How far the star is from the edge of it's section. Avoids artifacts at the edge of sections. + +uniform sampler2D verticalColor: source_color; +uniform float starOpacity = 0; +uniform float starsNoiseScale = 1; +uniform float starsNoiseDivision = 1; +uniform vec2 starsNoiseOffset =vec2(0,0); + +vec2 get_partition( vec2 sky_coords ) +{ + // Separate the sphere into sections of roughly equal width and height. + float y = sky_coords.y * 2. - 1.; + float section_y = ceil(abs(y) * float(vertical_sections)) / float(vertical_sections); + float horizontal_sections = max(4., ceil(float(vertical_sections) * 4. * cos(section_y * PI / 2.))); + horizontal_sections = horizontal_sections > 0. ? horizontal_sections : 1.; + return vec2(sky_coords.x * horizontal_sections, y * float(vertical_sections)); +} + +vec2 rand_vec2(vec2 xy) +{ + float rand1 = fract(sin(dot(xy, vec2(11.9131, 81.2317))) * 57183.77193); + float rand2 = fract(sin(dot(xy, vec2(16.8131, 91.2327))) * 37113.66193); + return vec2(rand1, rand2) * ( 1. - margin * 2.) + margin; +} + +float star_brightness(vec2 sky_coords) +{ + vec2 partitions = get_partition(sky_coords); + vec2 partition_index = floor(partitions); + vec2 inner_coord = fract(partitions); + vec2 star_coord = rand_vec2(partition_index); + float dist = length(inner_coord - star_coord); + + return pow(star_size / dist, star_falloff); + +} + +void sky() +{ + vec3 stars= clamp( vec3( star_brightness( SKY_COORDS ) ), vec3(0,0,0), vec3(1,1,1) ); + float starsLight = random( ( starsNoiseOffset+ SKY_COORDS ) * starsNoiseScale / starsNoiseDivision ); + COLOR = stars* starOpacity * starsLight + texture( verticalColor, SKY_COORDS ).rgb ; + // vec3( star_brightness( SKY_COORDS ) ); +} diff --git a/Packed/Setup/box.bin b/Packed/Setup/box.bin new file mode 100644 index 0000000..0713f79 Binary files /dev/null and b/Packed/Setup/box.bin differ diff --git a/Packed/Setup/box.gltf b/Packed/Setup/box.gltf new file mode 100644 index 0000000..3503336 --- /dev/null +++ b/Packed/Setup/box.gltf @@ -0,0 +1,104 @@ +{ + "asset":{ + "generator":"Khronos glTF Blender I/O v4.0.44", + "version":"2.0" + }, + "scene":0, + "scenes":[ + { + "name":"Scene", + "nodes":[ + 0 + ] + } + ], + "nodes":[ + { + "mesh":0, + "name":"Cube" + } + ], + "meshes":[ + { + "name":"Cube", + "primitives":[ + { + "attributes":{ + "POSITION":0, + "NORMAL":1, + "TEXCOORD_0":2 + }, + "indices":3 + } + ] + } + ], + "accessors":[ + { + "bufferView":0, + "componentType":5126, + "count":24, + "max":[ + 2000, + 0.5, + 2000 + ], + "min":[ + -2000, + -0.5, + -2000 + ], + "type":"VEC3" + }, + { + "bufferView":1, + "componentType":5126, + "count":24, + "type":"VEC3" + }, + { + "bufferView":2, + "componentType":5126, + "count":24, + "type":"VEC2" + }, + { + "bufferView":3, + "componentType":5123, + "count":36, + "type":"SCALAR" + } + ], + "bufferViews":[ + { + "buffer":0, + "byteLength":288, + "byteOffset":0, + "target":34962 + }, + { + "buffer":0, + "byteLength":288, + "byteOffset":288, + "target":34962 + }, + { + "buffer":0, + "byteLength":192, + "byteOffset":576, + "target":34962 + }, + { + "buffer":0, + "byteLength":72, + "byteOffset":768, + "target":34963 + } + ], + "buffers":[ + { + "byteLength":840, + "uri":"box.bin" + } + ] +} diff --git a/Packed/Setup/box.gltf.import b/Packed/Setup/box.gltf.import new file mode 100644 index 0000000..7d467bd --- /dev/null +++ b/Packed/Setup/box.gltf.import @@ -0,0 +1,36 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://cj1isgoxsyx8m" +path="res://.godot/imported/box.gltf-2f15594fb0b34e673a96dd96d6a969f3.scn" + +[deps] + +source_file="res://Packed/Setup/box.gltf" +dest_files=["res://.godot/imported/box.gltf-2f15594fb0b34e673a96dd96d6a969f3.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +_subresources={} +gltf/naming_version=1 +gltf/embedded_image_handling=1 diff --git a/Packed/Setup/kloofendal_48d_partly_cloudy_puresky_4k.jpg b/Packed/Setup/kloofendal_48d_partly_cloudy_puresky_4k.jpg new file mode 100644 index 0000000..4e7a615 Binary files /dev/null and b/Packed/Setup/kloofendal_48d_partly_cloudy_puresky_4k.jpg differ diff --git a/Packed/Setup/kloofendal_48d_partly_cloudy_puresky_4k.jpg.import b/Packed/Setup/kloofendal_48d_partly_cloudy_puresky_4k.jpg.import new file mode 100644 index 0000000..c7a4387 --- /dev/null +++ b/Packed/Setup/kloofendal_48d_partly_cloudy_puresky_4k.jpg.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bsgmsgnxypkci" +path.s3tc="res://.godot/imported/kloofendal_48d_partly_cloudy_puresky_4k.jpg-66104c2a7833e79677860eadb6596748.s3tc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} + +[deps] + +source_file="res://Packed/Setup/kloofendal_48d_partly_cloudy_puresky_4k.jpg" +dest_files=["res://.godot/imported/kloofendal_48d_partly_cloudy_puresky_4k.jpg-66104c2a7833e79677860eadb6596748.s3tc.ctex"] + +[params] + +compress/mode=2 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=0 diff --git a/Packed/Setup/kloofendal_48d_partly_cloudy_puresky_4k.jpg~ b/Packed/Setup/kloofendal_48d_partly_cloudy_puresky_4k.jpg~ new file mode 100644 index 0000000..edb71c2 Binary files /dev/null and b/Packed/Setup/kloofendal_48d_partly_cloudy_puresky_4k.jpg~ differ diff --git a/Rokojori Action Library Examples.csproj b/Rokojori Action Library Examples.csproj new file mode 100644 index 0000000..aaa67a5 --- /dev/null +++ b/Rokojori Action Library Examples.csproj @@ -0,0 +1,9 @@ + + + net6.0 + net7.0 + net8.0 + true + RokojoriActionLibraryExamples + + \ No newline at end of file diff --git a/Rokojori Action Library Examples.sln b/Rokojori Action Library Examples.sln new file mode 100644 index 0000000..70f3912 --- /dev/null +++ b/Rokojori Action Library Examples.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rokojori Action Library Examples", "Rokojori Action Library Examples.csproj", "{8445BB6D-F6E9-4689-8FA3-F3B7C4A98278}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + ExportDebug|Any CPU = ExportDebug|Any CPU + ExportRelease|Any CPU = ExportRelease|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8445BB6D-F6E9-4689-8FA3-F3B7C4A98278}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8445BB6D-F6E9-4689-8FA3-F3B7C4A98278}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8445BB6D-F6E9-4689-8FA3-F3B7C4A98278}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU + {8445BB6D-F6E9-4689-8FA3-F3B7C4A98278}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU + {8445BB6D-F6E9-4689-8FA3-F3B7C4A98278}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU + {8445BB6D-F6E9-4689-8FA3-F3B7C4A98278}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU + EndGlobalSection +EndGlobal diff --git a/addons/SphynxMotionBlurToolkit/BaseClasses/enhanced_compositor_effect.gd b/addons/SphynxMotionBlurToolkit/BaseClasses/enhanced_compositor_effect.gd new file mode 100644 index 0000000..0306df3 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/BaseClasses/enhanced_compositor_effect.gd @@ -0,0 +1,227 @@ +extends CompositorEffect + +var rd: RenderingDevice + +var linear_sampler: RID + +var nearest_sampler : RID + +var context: StringName = "PostProcess" + +var all_shader_stages : Dictionary + +@export var debug : bool = false: + set(value): + if(debug == value): + return + + debug = value + free_shaders.call_deferred() + generate_shaders.call_deferred() + +var debug_1 : String = "debug_1" +var debug_2 : String = "debug_2" +var debug_3 : String = "debug_3" +var debug_4 : String = "debug_4" +var debug_5 : String = "debug_5" +var debug_6 : String = "debug_6" +var debug_7 : String = "debug_7" +var debug_8 : String = "debug_8" + +var all_debug_images : Array[RID] + +func _init(): + RenderingServer.call_on_render_thread(_initialize_compute) + +func _notification(what): + if what == NOTIFICATION_PREDELETE: + if !rd: + return + if linear_sampler.is_valid(): + rd.free_rid(linear_sampler) + if nearest_sampler.is_valid(): + rd.free_rid(nearest_sampler) + for shader_stage in all_shader_stages.keys(): + if shader_stage.pipeline.is_valid(): + rd.free_rid(shader_stage.pipeline) + if shader_stage.shader.is_valid(): + rd.free_rid(shader_stage.shader) + +func free_shaders(): + for shader_stage in all_shader_stages.keys(): + if shader_stage.pipeline.is_valid(): + rd.free_rid(shader_stage.pipeline) + if shader_stage.shader.is_valid(): + rd.free_rid(shader_stage.shader) + +func generate_shaders(): + for shader_stage in all_shader_stages.keys(): + generate_shader_stage(shader_stage) + + +func subscirbe_shader_stage(shader_stage : ShaderStageResource): + if all_shader_stages.has(shader_stage): + return + + all_shader_stages[shader_stage] = 1 + + if rd: + generate_shader_stage(shader_stage) + +func unsubscribe_shader_stage(shader_stage : ShaderStageResource): + if all_shader_stages.has(shader_stage): + all_shader_stages.erase(shader_stage) + if !rd: + return + + if shader_stage.shader.is_valid(): + rd.free_rid(shader_stage.shader) + if shader_stage.pipeline.is_valid(): + rd.free_rid(shader_stage.pipeline) + +func _initialize_compute(): + rd = RenderingServer.get_rendering_device() + + if !rd: + return + + var sampler_state := RDSamplerState.new() + + sampler_state.min_filter = RenderingDevice.SAMPLER_FILTER_LINEAR + sampler_state.mag_filter = RenderingDevice.SAMPLER_FILTER_LINEAR + sampler_state.repeat_u = RenderingDevice.SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE + sampler_state.repeat_v = RenderingDevice.SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE + + linear_sampler = rd.sampler_create(sampler_state) + + sampler_state.min_filter = RenderingDevice.SAMPLER_FILTER_NEAREST + sampler_state.mag_filter = RenderingDevice.SAMPLER_FILTER_NEAREST + sampler_state.repeat_u = RenderingDevice.SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE + sampler_state.repeat_v = RenderingDevice.SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE + + nearest_sampler = rd.sampler_create(sampler_state) + + generate_shaders() + + +func generate_shader_stage(shader_stage : ShaderStageResource): + var shader_spirv : RDShaderSPIRV + if debug: + var file = FileAccess.open(shader_stage.shader_file.resource_path, FileAccess.READ) + var split_shader : PackedStringArray = file.get_as_text().split("#[compute]", true, 1) + var content : String = split_shader[min(1, split_shader.size() - 1)] + var all_split_parts : PackedStringArray = content.split("#version 450", true, 1) + content = str(all_split_parts[0], + "#version 450 +#define DEBUG +layout(rgba16f, set = 0, binding = 10) uniform image2D debug_1_image; +layout(rgba16f, set = 0, binding = 11) uniform image2D debug_2_image; +layout(rgba16f, set = 0, binding = 12) uniform image2D debug_3_image; +layout(rgba16f, set = 0, binding = 13) uniform image2D debug_4_image; +layout(rgba16f, set = 0, binding = 14) uniform image2D debug_5_image; +layout(rgba16f, set = 0, binding = 15) uniform image2D debug_6_image; +layout(rgba16f, set = 0, binding = 16) uniform image2D debug_7_image; +layout(rgba16f, set = 0, binding = 17) uniform image2D debug_8_image;", + all_split_parts[1]) + var shader_source : RDShaderSource = RDShaderSource.new() + shader_source.set_stage_source(RenderingDevice.SHADER_STAGE_COMPUTE, content) + shader_spirv = rd.shader_compile_spirv_from_source(shader_source, false) + print(content) + else: + shader_spirv = shader_stage.shader_file.get_spirv() + + shader_stage.shader = rd.shader_create_from_spirv(shader_spirv) + shader_stage.pipeline = rd.compute_pipeline_create(shader_stage.shader) + +func _render_callback(p_effect_callback_type, p_render_data): + if !rd: + return + + var render_scene_buffers: RenderSceneBuffersRD = p_render_data.get_render_scene_buffers() + var render_scene_data: RenderSceneDataRD = p_render_data.get_render_scene_data() + if !render_scene_buffers or !render_scene_data: + return + + var render_size: Vector2i = render_scene_buffers.get_internal_size() + + if render_size.x == 0 or render_size.y == 0: + return + + if debug: + ensure_texture(debug_1, render_scene_buffers) + ensure_texture(debug_2, render_scene_buffers) + ensure_texture(debug_3, render_scene_buffers) + ensure_texture(debug_4, render_scene_buffers) + ensure_texture(debug_5, render_scene_buffers) + ensure_texture(debug_6, render_scene_buffers) + ensure_texture(debug_7, render_scene_buffers) + ensure_texture(debug_8, render_scene_buffers) + + var view_count = render_scene_buffers.get_view_count() + + for view in range(view_count): + all_debug_images.append(render_scene_buffers.get_texture_slice(context, debug_1, view, 0, 1, 1)) + all_debug_images.append(render_scene_buffers.get_texture_slice(context, debug_2, view, 0, 1, 1)) + all_debug_images.append(render_scene_buffers.get_texture_slice(context, debug_3, view, 0, 1, 1)) + all_debug_images.append(render_scene_buffers.get_texture_slice(context, debug_4, view, 0, 1, 1)) + all_debug_images.append(render_scene_buffers.get_texture_slice(context, debug_5, view, 0, 1, 1)) + all_debug_images.append(render_scene_buffers.get_texture_slice(context, debug_6, view, 0, 1, 1)) + all_debug_images.append(render_scene_buffers.get_texture_slice(context, debug_7, view, 0, 1, 1)) + all_debug_images.append(render_scene_buffers.get_texture_slice(context, debug_8, view, 0, 1, 1)) + + _render_callback_2(render_size, render_scene_buffers, render_scene_data) + + all_debug_images.clear() + +func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSceneBuffersRD, render_scene_data : RenderSceneDataRD): + pass + +func ensure_texture(texture_name : StringName, render_scene_buffers : RenderSceneBuffersRD, texture_format : RenderingDevice.DataFormat = RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, render_size_multiplier : Vector2 = Vector2(1, 1)): + var render_size : Vector2i = Vector2(render_scene_buffers.get_internal_size()) * render_size_multiplier + + if render_scene_buffers.has_texture(context, texture_name): + var tf: RDTextureFormat = render_scene_buffers.get_texture_format(context, texture_name) + if tf.width != render_size.x or tf.height != render_size.y: + render_scene_buffers.clear_context(context) + + if !render_scene_buffers.has_texture(context, texture_name): + var usage_bits: int = RenderingDevice.TEXTURE_USAGE_SAMPLING_BIT | RenderingDevice.TEXTURE_USAGE_STORAGE_BIT + render_scene_buffers.create_texture(context, texture_name, texture_format, usage_bits, RenderingDevice.TEXTURE_SAMPLES_1, render_size, 1, 1, true) + +func get_image_uniform(image: RID, binding: int) -> RDUniform: + var uniform: RDUniform = RDUniform.new() + uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_IMAGE + uniform.binding = binding + uniform.add_id(image) + return uniform + +func get_sampler_uniform(image: RID, binding: int, linear : bool = true) -> RDUniform: + var uniform: RDUniform = RDUniform.new() + uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_SAMPLER_WITH_TEXTURE + uniform.binding = binding + uniform.add_id(linear_sampler if linear else nearest_sampler) + uniform.add_id(image) + return uniform + +func dispatch_stage(stage : ShaderStageResource, uniforms : Array[RDUniform], push_constants : PackedByteArray, dispatch_size : Vector3i, label : String = "DefaultLabel", view : int = 0, color : Color = Color(1, 1, 1, 1)): + rd.draw_command_begin_label(label + " " + str(view), color) + + if debug: + for i in 8: + var debug_image_index = i + view * 8; + uniforms.append(get_image_uniform(all_debug_images[debug_image_index], 10 + i)) + + var tex_uniform_set = UniformSetCacheRD.get_cache(stage.shader, 0, uniforms) + + var compute_list = rd.compute_list_begin() + rd.compute_list_bind_compute_pipeline(compute_list, stage.pipeline) + rd.compute_list_bind_uniform_set(compute_list, tex_uniform_set, 0) + + if !push_constants.is_empty(): + rd.compute_list_set_push_constant(compute_list, push_constants, push_constants.size()) + + rd.compute_list_dispatch(compute_list, dispatch_size.x, dispatch_size.y, dispatch_size.z) + + rd.compute_list_end() + + rd.draw_command_end_label() diff --git a/addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor.gd b/addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor.gd new file mode 100644 index 0000000..21b64a0 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor.gd @@ -0,0 +1,49 @@ +extends Compositor +class_name MotionBlurCompositor + +@export_group("Motion Blur") +# diminishing returns over 16 +@export_range(4, 64) var samples: int = 16 : + set(value): + for effect in compositor_effects: + effect.set("samples", value) + samples = value +# you really don't want this over 0.5, but you can if you want to try +@export_range(0, 0.5, 0.001, "or_greater") var intensity: float = 1 : + set(value): + for effect in compositor_effects: + effect.set("intensity", value) + intensity = value +@export_range(0, 1) var center_fade: float = 0.0 : + set(value): + for effect in compositor_effects: + effect.set("center_fade", value) + center_fade = value + +## wether this motion blur stays the same intensity below +## target_constant_framerate +@export var framerate_independent : bool = true : + set(value): + for effect in compositor_effects: + effect.set("framerate_independent", value) + framerate_independent = value + +## Description: Removes clamping on motion blur scale to allow framerate independent motion +## blur to scale longer than realistically possible when render framerate is higher +## than target framerate.[br][br] +## [color=yellow]Warning:[/color] Turning this on would allow over-blurring of pixels, which +## produces inaccurate results, and would likely cause nausea in players over +## long exposure durations, use with caution and out of artistic intent +@export var uncapped_independence : bool = false : + set(value): + for effect in compositor_effects: + effect.set("uncapped_independence", value) + uncapped_independence = value + +## if framerate_independent is enabled, the blur would simulate +## sutter speeds at that framerate, and up. +@export var target_constant_framerate : float = 30 : + set(value): + for effect in compositor_effects: + effect.set("target_constant_framerate", value) + target_constant_framerate = value diff --git a/addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor_effect.gd b/addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor_effect.gd new file mode 100644 index 0000000..a049ebb --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor_effect.gd @@ -0,0 +1,28 @@ +extends "res://addons/SphynxMotionBlurToolkit/BaseClasses/enhanced_compositor_effect.gd" + +# diminishing returns over 16 +var samples: int = 16 +# you really don't want this over 0.5, but you can if you want to try +var intensity: float = 1 +var center_fade: float = 0.0 + +## wether this motion blur stays the same intensity below +## target_constant_framerate +var framerate_independent : bool = true + +## Description: Removes clamping on motion blur scale to allow framerate independent motion +## blur to scale longer than realistically possible when render framerate is higher +## than target framerate.[br][br] +## [color=yellow]Warning:[/color] Turning this on would allow over-blurring of pixels, which +## produces inaccurate results, and would likely cause nausea in players over +## long exposure durations, use with caution and out of artistic intent +var uncapped_independence : bool = false + +## if framerate_independent is enabled, the blur would simulate +## sutter speeds at that framerate, and up. +var target_constant_framerate : float = 30 + +func _init(): + needs_motion_vectors = true + set_deferred("context", "MotionBlur") + super() diff --git a/addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd b/addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd new file mode 100644 index 0000000..7d86dfe --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd @@ -0,0 +1,7 @@ +extends Resource +class_name ShaderStageResource + +@export var shader_file : RDShaderFile + +var shader : RID +var pipeline : RID diff --git a/addons/SphynxMotionBlurToolkit/Debug/ShaderFiles/debug_overlay.glsl b/addons/SphynxMotionBlurToolkit/Debug/ShaderFiles/debug_overlay.glsl new file mode 100644 index 0000000..196953e --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Debug/ShaderFiles/debug_overlay.glsl @@ -0,0 +1,87 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 +#define DBL_MAX 1.7976931348623158e+308 +#define DBL_MIN 2.2250738585072014e-308 + +layout(rgba16f, set = 0, binding = 0) uniform image2D past_color_image; +layout(rgba16f, set = 0, binding = 1) uniform image2D output_color_image; +layout(set = 0, binding = 2) uniform sampler2D color_sampler; + +layout(push_constant, std430) uniform Params +{ + float nan_fl_1; + float nan_fl_2; + float nan_fl_3; + float nan_fl_4; + int freeze; + int draw_debug; + int debug_page; + int nan3; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + + +void main() +{ + ivec2 render_size = ivec2(textureSize(color_sampler, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + // show past image for freeze frame + if(params.freeze > 0) + { + imageStore(output_color_image, uvi, imageLoad(past_color_image, uvi)); + return; + } + // must be on pixel center for whole values (tested) + vec2 uvn = vec2(uvi + vec2(0.5)) / render_size; + + vec4 source = textureLod(color_sampler, uvn, 0.0); + + if (params.draw_debug == 0) + { + imageStore(output_color_image, uvi, source); + imageStore(past_color_image, uvi, source); + return; + } + + vec4 tl_col; + + vec4 tr_col; + + vec4 bl_col; + + vec4 br_col; + +#ifdef DEBUG + if(params.debug_page == 0) + { + tl_col = imageLoad(debug_1_image, uvi); + tr_col = imageLoad(debug_2_image, uvi); + bl_col = imageLoad(debug_3_image, uvi); + br_col = imageLoad(debug_4_image, uvi); + } + if(params.debug_page == 1) + { + tl_col = imageLoad(debug_5_image, uvi); + tr_col = imageLoad(debug_6_image, uvi); + bl_col = imageLoad(debug_7_image, uvi); + br_col = imageLoad(debug_8_image, uvi); + } +#endif + + imageStore(output_color_image, uvi / 2, tl_col); + imageStore(output_color_image, uvi / 2 + ivec2(vec2(0.5, 0.5) * render_size), br_col); + imageStore(output_color_image, uvi / 2 + ivec2(vec2(0.0, 0.5) * render_size), bl_col); + imageStore(output_color_image, uvi / 2 + ivec2(vec2(0.5, 0.0) * render_size), tr_col); + imageStore(past_color_image, uvi / 2, tl_col); + imageStore(past_color_image, uvi / 2 + ivec2(vec2(0.5, 0.5) * render_size), br_col); + imageStore(past_color_image, uvi / 2 + ivec2(vec2(0.0, 0.5) * render_size), bl_col); + imageStore(past_color_image, uvi / 2 + ivec2(vec2(0.5, 0.0) * render_size), tr_col); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/Debug/ShaderFiles/debug_overlay.glsl.import b/addons/SphynxMotionBlurToolkit/Debug/ShaderFiles/debug_overlay.glsl.import new file mode 100644 index 0000000..af416c2 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Debug/ShaderFiles/debug_overlay.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://dyxn6g5gvoge7" +path="res://.godot/imported/debug_overlay.glsl-5ad15477a64c7f484bc494103ad163b6.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/Debug/ShaderFiles/debug_overlay.glsl" +dest_files=["res://.godot/imported/debug_overlay.glsl-5ad15477a64c7f484bc494103ad163b6.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/Debug/debug_overlay_shader_stage.tres b/addons/SphynxMotionBlurToolkit/Debug/debug_overlay_shader_stage.tres new file mode 100644 index 0000000..58735f3 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Debug/debug_overlay_shader_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://o2bivm33b0v4"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_rqnmr"] +[ext_resource type="RDShaderFile" uid="uid://dyxn6g5gvoge7" path="res://addons/SphynxMotionBlurToolkit/Debug/ShaderFiles/debug_overlay.glsl" id="2_qgd1y"] + +[resource] +script = ExtResource("1_rqnmr") +shader_file = ExtResource("2_qgd1y") diff --git a/addons/SphynxMotionBlurToolkit/Debug/post_process_debug.gd b/addons/SphynxMotionBlurToolkit/Debug/post_process_debug.gd new file mode 100644 index 0000000..455fd9f --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Debug/post_process_debug.gd @@ -0,0 +1,99 @@ +extends "res://addons/SphynxMotionBlurToolkit/BaseClasses/enhanced_compositor_effect.gd" +class_name DebugCompositorEffect + +@export var overlay_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Debug/debug_overlay_shader_stage.tres"): + set(value): + unsubscribe_shader_stage(overlay_stage) + overlay_stage = value + subscirbe_shader_stage(value) + +## wether to display debug views for velocity and depth +## buffers +@export var draw_debug : bool = false + +## currently 0 - 1, flip between velocity buffers +## and depth buffers debug views +@export var debug_page : int = 0 + +var past_color : StringName = "past_color" + +var freeze : bool = false + +func _init(): + set_deferred("context", "MotionBlur") + set_deferred("debug", true) + super() + +func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSceneBuffersRD, render_scene_data : RenderSceneDataRD): + ensure_texture(past_color, render_scene_buffers) + ensure_texture(debug_1, render_scene_buffers) + ensure_texture(debug_2, render_scene_buffers) + ensure_texture(debug_3, render_scene_buffers) + ensure_texture(debug_4, render_scene_buffers) + ensure_texture(debug_5, render_scene_buffers) + ensure_texture(debug_6, render_scene_buffers) + ensure_texture(debug_7, render_scene_buffers) + ensure_texture(debug_8, render_scene_buffers) + + rd.draw_command_begin_label("Debug", Color(1.0, 1.0, 1.0, 1.0)) + + if Input.is_action_just_pressed("freeze"): + freeze = !freeze + + if Input.is_action_just_pressed("Z"): + draw_debug = !draw_debug + + if Input.is_action_just_pressed("C"): + debug_page = 1 if debug_page == 0 else 0 + + var push_constant: PackedFloat32Array = [ + 0, + 0, + 0, + 0, + ] + var int_push_constant : PackedInt32Array = [ + freeze, + draw_debug, + debug_page, + 0 + ] + var byte_array = push_constant.to_byte_array() + byte_array.append_array(int_push_constant.to_byte_array()) + + var view_count = render_scene_buffers.get_view_count() + for view in range(view_count): + var color_image := render_scene_buffers.get_color_layer(view) + var past_color_image := render_scene_buffers.get_texture_slice(context, past_color, view, 0, 1, 1) + var debug_1_image := render_scene_buffers.get_texture_slice(context, debug_1, view, 0, 1, 1) + var debug_2_image := render_scene_buffers.get_texture_slice(context, debug_2, view, 0, 1, 1) + var debug_3_image := render_scene_buffers.get_texture_slice(context, debug_3, view, 0, 1, 1) + var debug_4_image := render_scene_buffers.get_texture_slice(context, debug_4, view, 0, 1, 1) + var debug_5_image := render_scene_buffers.get_texture_slice(context, debug_5, view, 0, 1, 1) + var debug_6_image := render_scene_buffers.get_texture_slice(context, debug_6, view, 0, 1, 1) + var debug_7_image := render_scene_buffers.get_texture_slice(context, debug_7, view, 0, 1, 1) + var debug_8_image := render_scene_buffers.get_texture_slice(context, debug_8, view, 0, 1, 1) + + var x_groups := floori((render_size.x - 1) / 16 + 1) + var y_groups := floori((render_size.y - 1) / 16 + 1) + + dispatch_stage(overlay_stage, + [ + get_image_uniform(past_color_image, 0), + get_image_uniform(color_image, 1), + get_sampler_uniform(color_image, 2), + get_sampler_uniform(debug_1_image, 3), + get_sampler_uniform(debug_2_image, 4), + get_sampler_uniform(debug_3_image, 5), + get_sampler_uniform(debug_4_image, 6), + get_sampler_uniform(debug_5_image, 7), + get_sampler_uniform(debug_6_image, 8), + get_sampler_uniform(debug_7_image, 9), + get_sampler_uniform(debug_8_image, 10), + ], + byte_array, + Vector3i(x_groups, y_groups, 1), + "Debug Overlay", + view) + + rd.draw_command_end_label() diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_blur.glsl b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_blur.glsl new file mode 100644 index 0000000..9efecd9 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_blur.glsl @@ -0,0 +1,156 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D color_sampler; +layout(set = 0, binding = 1) uniform sampler2D depth_sampler; +layout(set = 0, binding = 2) uniform sampler2D velocity_sampler; +layout(set = 0, binding = 3) uniform sampler2D neighbor_max; +layout(set = 0, binding = 4) uniform sampler2D tile_variance; +layout(rgba16f, set = 0, binding = 5) uniform writeonly image2D output_color; +layout(rgba16f, set = 0, binding = 6) uniform image2D debug_1_image; +layout(rgba16f, set = 0, binding = 7) uniform image2D debug_2_image; + +layout(push_constant, std430) uniform Params +{ + float minimum_user_threshold; + float importance_bias; + float maximum_jitter_value; + float nan8; + int tile_size; + int sample_count; + int frame; + int nan4; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +// McGuire's functions https://docs.google.com/document/d/1IIlAKTj-O01hcXEdGxTErQbCHO9iBmRx6oFUy_Jm0fI/edit +// ---------------------------------------------------------- +float soft_depth_compare(float depth_X, float depth_Y, float sze) +{ + return clamp(1 - (depth_X - depth_Y) / sze, 0, 1); +} + +float cone(float T, float v) +{ + return clamp(1 - abs(T) / v, 0, 1); +} + +float cylinder(float T, float v) +{ + return 1.0 - smoothstep(0.95 * v, 1.05 * v, abs(T)); +} +// ---------------------------------------------------------- + +// Guertin's functions https://research.nvidia.com/sites/default/files/pubs/2013-11_A-Fast-and/Guertin2013MotionBlur-small.pdf +// ---------------------------------------------------------- +float z_compare(float a, float b) +{ + return clamp(1. - (a - b) / min(a, b), 0, 1); +} +// ---------------------------------------------------------- + +// from https://www.shadertoy.com/view/ftKfzc +// ---------------------------------------------------------- +float interleaved_gradient_noise(vec2 uv, int FrameId){ + uv += float(FrameId) * (vec2(47, 17) * 0.695); + + vec3 magic = vec3( 0.06711056, 0.00583715, 52.9829189 ); + + return fract(magic.z * fract(dot(uv, magic.xy))); +} +// ---------------------------------------------------------- + +vec2 sample_random_offset(vec2 uv, float j) +{ + return vec2(0); +} + +void main() +{ + ivec2 render_size = ivec2(textureSize(color_sampler, 0)); + ivec2 tile_render_size = ivec2(textureSize(neighbor_max, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + + vec2 x = (vec2(uvi) + vec2(0.5)) / vec2(render_size); + + float j = interleaved_gradient_noise(uvi, params.frame) * 2. - 1.; + + vec2 vn = textureLod(neighbor_max, x, 0.0).xy * render_size / 2; + + float vn_length = max(0.5, length(vn)); + + vec4 base_color = textureLod(color_sampler, x, 0.0); + + if(vn_length <= 0.5) + { + imageStore(output_color, uvi, base_color); + imageStore(debug_1_image, uvi, base_color); + imageStore(debug_2_image, uvi, vec4(vn / render_size * 2, 0, 1)); + return; + } + + vec2 wn = normalize(vn); + + vec2 vx = textureLod(velocity_sampler, x, 0.0).xy * render_size / 2; + + float vx_length = max(0.5, length(vx)); + + vec2 wp = vec2(-wn.y, wn.x); + + if(dot(wp, vx) < 0) + { + wp = -wp; + } + + vec2 wc = normalize(mix(wp, normalize(vx), (vx_length - 0.5) / params.minimum_user_threshold)); + + float zx = -0.05 / textureLod(depth_sampler, x, 0.0).x; + + float weight = params.sample_count / (params.importance_bias * vx_length); + + vec4 sum = base_color * weight; + + for(int i = 0; i < params.sample_count; i++) + { + float t = mix(-1.0, 1.0, (i + j * params.maximum_jitter_value + 1.0) / (params.sample_count + 1.0)); + + vec2 d = ((i % 2) > 0) ? vx : vn; + + float T = t * vn_length; + + vec2 y = x + t * d / render_size; + + vec2 vy = textureLod(velocity_sampler, y, 0.0).xy * render_size / 2; + + float vy_length = max(0.5, length(vy)); + + float zy = -0.05 / textureLod(depth_sampler, y, 0.0).x; + + float f = z_compare(zx, zy); + float b = z_compare(zy, zx); + + float wa = dot(wc, d); + float wb = dot(normalize(vy), d); + + float ay = f * cone(T, 1. / vy_length) * max(FLT_MIN, abs(wb)) + + b * cone(T, 1. / vx_length) * max(FLT_MIN, abs(wa)) + + cylinder(T, min(vx_length, vy_length)) * 2 * max(FLT_MIN, max(abs(wa), abs(wb))); + + weight += abs(ay); + sum += ay * textureLod(color_sampler, y, 0.0); + } + + sum /= weight; + + imageStore(output_color, uvi, sum); + imageStore(debug_1_image, uvi, sum); + imageStore(debug_2_image, uvi, vec4(vn / render_size * 2, 0, 1)); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_blur.glsl.import b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_blur.glsl.import new file mode 100644 index 0000000..2b497ce --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_blur.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://cbdyfuhewqag8" +path="res://.godot/imported/guertin_blur.glsl-bc647b2d965e982b702f0e036903e801.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_blur.glsl" +dest_files=["res://.godot/imported/guertin_blur.glsl-bc647b2d965e982b702f0e036903e801.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_experimental_blur.glsl b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_experimental_blur.glsl new file mode 100644 index 0000000..9426c3f --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_experimental_blur.glsl @@ -0,0 +1,200 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 +#define M_PI 3.1415926535897932384626433832795 + +layout(set = 0, binding = 0) uniform sampler2D color_sampler; +layout(set = 0, binding = 1) uniform sampler2D velocity_sampler; +layout(set = 0, binding = 2) uniform sampler2D neighbor_max; +layout(set = 0, binding = 3) uniform sampler2D tile_variance; +layout(rgba16f, set = 0, binding = 4) uniform writeonly image2D output_color; + + +layout(push_constant, std430) uniform Params +{ + float minimum_user_threshold; + float importance_bias; + float maximum_jitter_value; + float motion_blur_intensity; + int tile_size; + int sample_count; + int frame; + int nan4; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +// McGuire's functions https://docs.google.com/document/d/1IIlAKTj-O01hcXEdGxTErQbCHO9iBmRx6oFUy_Jm0fI/edit +// ---------------------------------------------------------- +float soft_depth_compare(float depth_X, float depth_Y, float sze) +{ + return clamp(1 - (depth_X - depth_Y) / sze, 0, 1); +} + +float cone(float T, float v) +{ + return clamp(1 - T / v, 0, 1); +} + +float cylinder(float T, float v) +{ + return 1.0 - smoothstep(0.95 * v, 1.05 * v, T); +} +// ---------------------------------------------------------- + +// Guertin's functions https://research.nvidia.com/sites/default/files/pubs/2013-11_A-Fast-and/Guertin2013MotionBlur-small.pdf +// ---------------------------------------------------------- +float z_compare(float a, float b, float sze) +{ + return clamp(1. - sze * (a - b), 0, 1); +} +// ---------------------------------------------------------- + +// from https://www.shadertoy.com/view/ftKfzc +// ---------------------------------------------------------- +float interleaved_gradient_noise(vec2 uv){ + uv += float(params.frame) * (vec2(47, 17) * 0.695); + + vec3 magic = vec3( 0.06711056, 0.00583715, 52.9829189 ); + + return fract(magic.z * fract(dot(uv, magic.xy))); +} +// ---------------------------------------------------------- + +// from https://github.com/bradparks/KinoMotion__unity_motion_blur/tree/master +// ---------------------------------------------------------- +vec2 safenorm(vec2 v) +{ + float l = max(length(v), 1e-6); + return v / l * int(l >= 0.5); +} + +vec2 jitter_tile(vec2 uvi) +{ + float rx, ry; + float angle = interleaved_gradient_noise(uvi + vec2(2, 0)) * M_PI * 2; + rx = cos(angle); + ry = sin(angle); + return vec2(rx, ry) / textureSize(neighbor_max, 0) / 4; +} +// ---------------------------------------------------------- + +void main() +{ + ivec2 render_size = ivec2(textureSize(color_sampler, 0)); + ivec2 tile_render_size = ivec2(textureSize(neighbor_max, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + + vec2 x = (vec2(uvi) + vec2(0.5)) / vec2(render_size); + + vec4 vnzw = textureLod(neighbor_max, x + vec2(params.tile_size / 2) / vec2(render_size) + jitter_tile(uvi), 0.0) * vec4(render_size / 2., 1, 1) * params.motion_blur_intensity; + + vec2 vn = vnzw.xy; + + float vn_length = length(vn); + + vec4 base_color = textureLod(color_sampler, x, 0.0); + + vec4 vxzw = textureLod(velocity_sampler, x, 0.0) * vec4(render_size / 2., 1, 1) * params.motion_blur_intensity; + + if(vn_length < 0.5) + { + imageStore(output_color, uvi, base_color); +#ifdef DEBUG + imageStore(debug_1_image, uvi, base_color); + imageStore(debug_2_image, uvi, vec4(vn / render_size * 2, 0, 1)); + imageStore(debug_3_image, uvi, vec4(vxzw.xy / render_size * 2, 0, 1)); + imageStore(debug_4_image, uvi, vec4(0)); +#endif + return; + } + + vec2 wn = safenorm(vn); + + vec2 vx = vxzw.xy; + + float vx_length = max(0.5, length(vx)); + + vec2 wx = safenorm(vx); + + float j = interleaved_gradient_noise(uvi) * 2. - 1.; + + float zx = vxzw.w; + + float weight = 1e-6; + + vec4 sum = base_color * weight; + + float nai_weight = 1e-6; + + vec4 nai_sum = base_color * nai_weight; + + for(int i = 0; i < params.sample_count; i++) + { + float t = mix(-1.0, 1.0, (i + j * params.maximum_jitter_value + 1.0) / (params.sample_count + 1.0)); + + bool use_vn = ((i % 2) == 0); + + vec2 d = use_vn ? vn : vx; + + float dz = use_vn ? vnzw.z : vxzw.z; + + vec2 wd = use_vn ? wn : wx; + + float T = abs(t * vn_length); + + vec2 y = x + t * d / render_size; + + float wa = abs(dot(wx, wd)); + + vec4 vyzw = textureLod(velocity_sampler, y, 0.0) * vec4(render_size / 2, 1, 1) * params.motion_blur_intensity; + + vec2 vy = vyzw.xy - dz * t; + + float vy_length = max(0.5, length(vy)); + + float zy = vyzw.w; + + float f = z_compare(-zy, -zx, 20000); + float b = z_compare(-zx, -zy, 20000); + + float wb = abs(dot(vy / vy_length, wd)); + + if(use_vn) + { + float ay = f * step(T, vy_length * wb); + + weight += ay; + + sum += textureLod(color_sampler, y, 0.0) * ay; + } + + float nai_ay = b * step(T, vx_length * wa) * 2; + + nai_weight += nai_ay; + + nai_sum += textureLod(color_sampler, y, 0.0) * nai_ay; + } + + sum /= weight; + + weight /= params.sample_count / 2; + + nai_sum /= nai_weight; + + sum = mix(nai_sum, sum, weight); + + imageStore(output_color, uvi, sum); +#ifdef DEBUG + imageStore(debug_1_image, uvi, base_color); + imageStore(debug_2_image, uvi, vec4(vn / render_size * 2, 0, 1)); + imageStore(debug_3_image, uvi, vec4(vx / render_size * 2, 0, 1)); + imageStore(debug_4_image, uvi, vxzw); +#endif +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_experimental_blur.glsl.import b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_experimental_blur.glsl.import new file mode 100644 index 0000000..420c36b --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_experimental_blur.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://br71y0l0rxt8h" +path="res://.godot/imported/guertin_experimental_blur.glsl-196a1037ea9a4eb1095033202fe161a7.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_experimental_blur.glsl" +dest_files=["res://.godot/imported/guertin_experimental_blur.glsl-196a1037ea9a4eb1095033202fe161a7.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_kino_blur.glsl b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_kino_blur.glsl new file mode 100644 index 0000000..b3cf422 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_kino_blur.glsl @@ -0,0 +1,191 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 +#define M_PI 3.1415926535897932384626433832795 + +layout(set = 0, binding = 0) uniform sampler2D color_sampler; +layout(set = 0, binding = 1) uniform sampler2D velocity_sampler; +layout(set = 0, binding = 2) uniform sampler2D neighbor_max; +layout(set = 0, binding = 3) uniform sampler2D tile_variance; +layout(rgba16f, set = 0, binding = 4) uniform writeonly image2D output_color; + + +layout(push_constant, std430) uniform Params +{ + float minimum_user_threshold; + float importance_bias; + float maximum_jitter_value; + float motion_blur_intensity; + int tile_size; + int sample_count; + int frame; + int nan4; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +// McGuire's functions https://docs.google.com/document/d/1IIlAKTj-O01hcXEdGxTErQbCHO9iBmRx6oFUy_Jm0fI/edit +// ---------------------------------------------------------- +float soft_depth_compare(float depth_X, float depth_Y, float sze) +{ + return clamp(1 - (depth_X - depth_Y) / sze, 0, 1); +} + +float cone(float T, float v) +{ + return clamp(1 - T / v, 0, 1); +} + +float cylinder(float T, float v) +{ + return 1.0 - smoothstep(0.95 * v, 1.05 * v, T); +} +// ---------------------------------------------------------- + +// Guertin's functions https://research.nvidia.com/sites/default/files/pubs/2013-11_A-Fast-and/Guertin2013MotionBlur-small.pdf +// ---------------------------------------------------------- +float z_compare(float a, float b, float sze) +{ + return clamp(1. - sze * (a - b), 0, 1); +} +// ---------------------------------------------------------- + +// from https://www.shadertoy.com/view/ftKfzc +// ---------------------------------------------------------- +float interleaved_gradient_noise(vec2 uv){ + uv += float(params.frame) * (vec2(47, 17) * 0.695); + + vec3 magic = vec3( 0.06711056, 0.00583715, 52.9829189 ); + + return fract(magic.z * fract(dot(uv, magic.xy))); +} +// ---------------------------------------------------------- + +// from https://github.com/bradparks/KinoMotion__unity_motion_blur/tree/master +// ---------------------------------------------------------- +vec2 safenorm(vec2 v) +{ + float l = max(length(v), 1e-6); + return v / l * int(l >= 0.5); +} + +vec2 jitter_tile(vec2 uvi) +{ + float rx, ry; + float angle = interleaved_gradient_noise(uvi + vec2(2, 0)) * M_PI * 2; + rx = cos(angle); + ry = sin(angle); + return vec2(rx, ry) / textureSize(neighbor_max, 0) / 4; +} +// ---------------------------------------------------------- + +void main() +{ + ivec2 render_size = ivec2(textureSize(color_sampler, 0)); + ivec2 tile_render_size = ivec2(textureSize(neighbor_max, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + + vec2 x = (vec2(uvi) + vec2(0.5)) / vec2(render_size); + + float j = interleaved_gradient_noise(uvi) * 2. - 1.; + + vec4 vnzw = textureLod(neighbor_max, x + vec2(params.tile_size / 2) / vec2(render_size) + jitter_tile(uvi), 0.0) * vec4(render_size / 2., 1, 1) * params.motion_blur_intensity; + + vec2 vn = vnzw.xy; + + float vn_length = length(vn); + + vec4 base_color = textureLod(color_sampler, x, 0.0); + + if(vn_length < 0.5) + { + imageStore(output_color, uvi, base_color); +#ifdef DEBUG + imageStore(debug_1_image, uvi, base_color); + imageStore(debug_2_image, uvi, vec4(vn / render_size * 2, 0, 1)); + imageStore(debug_3_image, uvi, vec4(0)); + imageStore(debug_4_image, uvi, vec4(0)); +#endif + return; + } + + vec2 wn = safenorm(vn); + + vec4 vxzw = textureLod(velocity_sampler, x, 0.0) * vec4(render_size / 2., 1, 1) * params.motion_blur_intensity; + + vec2 vx = vxzw.xy; + + float vx_length = max(0.5, length(vx)); + + vec2 wx = safenorm(vx); + + vec2 wp = vec2(-wn.y, wn.x); + + if(dot(wp, vx) < 0) + { + wp = -wp; + } + + vec2 wc = safenorm(mix(wp, wx, clamp((vx_length - 0.5) / params.minimum_user_threshold, 0, 1))); + + float zx = vxzw.w; + + float total_weight = params.sample_count / (params.importance_bias * vx_length); + + vec4 sum = base_color * total_weight; + + for(int i = 0; i < params.sample_count; i++) + { + float t = mix(-1.0, 1.0, (i + j * params.maximum_jitter_value + 1.0) / (params.sample_count + 1.0)); + + vec2 d = ((i % 2) > 0) ? vx : vn; + + float dz = ((i % 2) > 0) ? vxzw.z : vnzw.z; + + vec2 wd = safenorm(d); + + float T = abs(t * vn_length); + + vec2 y = x + t * d / render_size; + + float wa = dot(wc, wd); + + vec4 vyzw = textureLod(velocity_sampler, y, 0.0) * vec4(render_size / 2, 1, 1) * params.motion_blur_intensity; + + vec2 vy = vyzw.xy - dz * t; + + float vy_length = max(0.5, length(vy)); + + float zy = vyzw.w; + + float f = z_compare(-zy, -zx, 20000); + float b = z_compare(-zx, -zy, 20000); + + float wb = abs(dot(vy / vy_length, wd)); + + float weight = 0.0; + weight += f * cone(T, vy_length) * wb; + weight += b * cone(T, vx_length) * wa; + weight += cylinder(T, min(vy_length, vx_length)) * 2. * max(wa, wb); + + total_weight += weight; + + sum += weight * textureLod(color_sampler, y, 0.0); + } + + sum /= total_weight; + + imageStore(output_color, uvi, sum); +#ifdef DEBUG + imageStore(debug_1_image, uvi, sum); + imageStore(debug_2_image, uvi, vec4(vn / render_size * 2, 0, 1)); + imageStore(debug_3_image, uvi, vnzw); + imageStore(debug_4_image, uvi, vxzw); +#endif +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_kino_blur.glsl.import b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_kino_blur.glsl.import new file mode 100644 index 0000000..a13c0d0 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_kino_blur.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://m6rlgfu6i0b3" +path="res://.godot/imported/guertin_kino_blur.glsl-71e9932045a7522115793d60f179d67e.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_kino_blur.glsl" +dest_files=["res://.godot/imported/guertin_kino_blur.glsl-71e9932045a7522115793d60f179d67e.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_neighbor_max.glsl b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_neighbor_max.glsl new file mode 100644 index 0000000..ccd3b7f --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_neighbor_max.glsl @@ -0,0 +1,72 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D tile_max; +layout(rgba16f, set = 0, binding = 1) uniform writeonly image2D neighbor_max; + +layout(push_constant, std430) uniform Params +{ + float nan5; + float nan6; + float nan7; + float nan8; + int nan1; + int nan2; + int nan3; + int nan4; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + + +void main() +{ + ivec2 render_size = ivec2(textureSize(tile_max, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + + vec2 uvn = (vec2(uvi) + vec2(0.5)) / render_size; + + vec2 max_neighbor_velocity = vec2(0); + + float max_neighbor_velocity_length = 0; + + for(int i = -1; i < 2; i++) + { + for(int j = -1; j < 2; j++) + { + vec2 current_offset = vec2(1) / vec2(render_size) * vec2(i, j); + vec2 current_uv = uvn + current_offset; + if(current_uv.x < 0 || current_uv.x > 1 || current_uv.y < 0 || current_uv.y > 1) + { + continue; + } + + bool is_diagonal = (abs(i) + abs(j) == 2); + + vec2 current_neighbor_velocity = textureLod(tile_max, current_uv, 0.0).xy; + + bool facing_center = dot(current_neighbor_velocity, current_offset) > 0; + + if(is_diagonal && !facing_center) + { + continue; + } + + float current_neighbor_velocity_length = dot(current_neighbor_velocity, current_neighbor_velocity); + if(current_neighbor_velocity_length > max_neighbor_velocity_length) + { + max_neighbor_velocity_length = current_neighbor_velocity_length; + max_neighbor_velocity = current_neighbor_velocity; + } + } + } + + imageStore(neighbor_max, uvi, vec4(max_neighbor_velocity, 0, 1)); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_neighbor_max.glsl.import b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_neighbor_max.glsl.import new file mode 100644 index 0000000..edb48e0 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_neighbor_max.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://bn88jkvr17x4j" +path="res://.godot/imported/guertin_neighbor_max.glsl-91e836516679e0c51b67df5b480ef0af.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_neighbor_max.glsl" +dest_files=["res://.godot/imported/guertin_neighbor_max.glsl-91e836516679e0c51b67df5b480ef0af.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_overlay.glsl b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_overlay.glsl new file mode 100644 index 0000000..c85ac5b --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_overlay.glsl @@ -0,0 +1,18 @@ +#[compute] +#version 450 + +layout(set = 0, binding = 0) uniform sampler2D blur_sampler; +layout(rgba16f, set = 0, binding = 1) uniform image2D color_image; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; +void main() +{ + ivec2 render_size = ivec2(textureSize(blur_sampler, 0)); + ivec2 output_size = imageSize(color_image); + ivec2 uv = ivec2(gl_GlobalInvocationID.xy); + if ((uv.x >= output_size.x) || (uv.y >= output_size.y)) + { + return; + } + imageStore(color_image, uv, textureLod(blur_sampler, (vec2(uv) + 0.5) / output_size, 0.0)); +} diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_overlay.glsl.import b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_overlay.glsl.import new file mode 100644 index 0000000..5b57c2b --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_overlay.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://i6rnwhmss334" +path="res://.godot/imported/guertin_overlay.glsl-506c18362b63cb0a2477b4a4fbfea046.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_overlay.glsl" +dest_files=["res://.godot/imported/guertin_overlay.glsl-506c18362b63cb0a2477b4a4fbfea046.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_x.glsl b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_x.glsl new file mode 100644 index 0000000..007548d --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_x.glsl @@ -0,0 +1,55 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D velocity_sampler; +layout(set = 0, binding = 1) uniform sampler2D depth_sampler; +layout(rgba16f, set = 0, binding = 2) uniform writeonly image2D tile_max_x; + +layout(push_constant, std430) uniform Params +{ + float nan5; + float nan6; + float nan7; + float nan8; + int tile_size; + int nan2; + int nan3; + int nan4; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + + +void main() +{ + ivec2 render_size = ivec2(textureSize(velocity_sampler, 0)); + ivec2 output_size = imageSize(tile_max_x); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + ivec2 global_uvi = uvi * ivec2(params.tile_size, 1); + if ((uvi.x >= output_size.x) || (uvi.y >= output_size.y) || (global_uvi.x >= render_size.x) || (global_uvi.y >= render_size.y)) + { + return; + } + + vec2 uvn = (vec2(global_uvi) + vec2(0.5)) / render_size; + + vec4 max_velocity = vec4(0); + + float max_velocity_length = -1; + + for(int i = 0; i < params.tile_size; i++) + { + vec2 current_uv = uvn + vec2(float(i) / render_size.x, 0); + vec3 velocity_sample = textureLod(velocity_sampler, current_uv, 0.0).xyz; + float current_velocity_length = dot(velocity_sample.xy, velocity_sample.xy); + if(current_velocity_length > max_velocity_length) + { + max_velocity_length = current_velocity_length; + max_velocity = vec4(velocity_sample, textureLod(depth_sampler, current_uv, 0.0).x); + } + } + imageStore(tile_max_x, uvi, max_velocity); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_x.glsl.import b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_x.glsl.import new file mode 100644 index 0000000..19144a3 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_x.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://d0s5upcgm7r6l" +path="res://.godot/imported/guertin_tile_max_x.glsl-7ca561425618287b0f2821fd8c232f09.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_x.glsl" +dest_files=["res://.godot/imported/guertin_tile_max_x.glsl-7ca561425618287b0f2821fd8c232f09.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_y.glsl b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_y.glsl new file mode 100644 index 0000000..1fc1328 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_y.glsl @@ -0,0 +1,54 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D tile_max_x; +layout(rgba16f, set = 0, binding = 1) uniform writeonly image2D tile_max; + +layout(push_constant, std430) uniform Params +{ + float nan5; + float nan6; + float nan7; + float nan8; + int tile_size; + int nan2; + int nan3; + int nan4; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + + +void main() +{ + ivec2 render_size = ivec2(textureSize(tile_max_x, 0)); + ivec2 output_size = imageSize(tile_max); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + ivec2 global_uvi = uvi * ivec2(1, params.tile_size); + if ((uvi.x >= output_size.x) || (uvi.y >= output_size.y) || (global_uvi.x >= render_size.x) || (global_uvi.y >= render_size.y)) + { + return; + } + + vec2 uvn = (vec2(global_uvi) + vec2(0.5)) / render_size; + + vec4 max_velocity = vec4(0); + + float max_velocity_length = -1; + + for(int i = 0; i < params.tile_size; i++) + { + vec2 current_uv = uvn + vec2(0, float(i) / render_size.y); + vec4 velocity_sample = textureLod(tile_max_x, current_uv, 0.0); + float current_velocity_length = dot(velocity_sample.xy, velocity_sample.xy); + if(current_velocity_length > max_velocity_length) + { + max_velocity_length = current_velocity_length; + max_velocity = velocity_sample; + } + } + imageStore(tile_max, uvi, max_velocity); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_y.glsl.import b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_y.glsl.import new file mode 100644 index 0000000..e241248 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_y.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://ceetvitdbio4l" +path="res://.godot/imported/guertin_tile_max_y.glsl-60f045725ff6917c4bd911cf3710a444.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_y.glsl" +dest_files=["res://.godot/imported/guertin_tile_max_y.glsl-60f045725ff6917c4bd911cf3710a444.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_variance.glsl b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_variance.glsl new file mode 100644 index 0000000..24ec95c --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_variance.glsl @@ -0,0 +1,68 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D tile_max; +layout(rgba16f, set = 0, binding = 1) uniform writeonly image2D tile_variance; + +layout(push_constant, std430) uniform Params +{ + float nan5; + float nan6; + float nan7; + float nan8; + int nan1; + int nan2; + int nan3; + int nan4; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + + +void main() +{ + ivec2 render_size = ivec2(textureSize(tile_max, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + + vec2 uvn = (vec2(uvi) + vec2(0.5)) / render_size; + + float variance = 0; + + vec2 current_velocity = abs(normalize(textureLod(tile_max, uvn, 0.0).xy)); + + float tile_count = 0; + + for(int i = -1; i < 2; i++) + { + for(int j = -1; j < 2; j++) + { + vec2 current_offset = vec2(1) / vec2(render_size) * vec2(i, j); + vec2 current_uv = uvn + current_offset; + if(current_uv.x < 0 || current_uv.x > 1 || current_uv.y < 0 || current_uv.y > 1) + { + continue; + } + if(i == j && i == 0) + { + continue; + } + + tile_count += 1; + + vec2 current_neighbor_velocity = abs(normalize(textureLod(tile_max, current_uv, 0.0).xy)); + + variance += dot(current_velocity, current_neighbor_velocity); + } + } + + variance /= tile_count; + + imageStore(tile_variance, uvi, vec4(1 - variance)); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_variance.glsl.import b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_variance.glsl.import new file mode 100644 index 0000000..61e2a82 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_variance.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://by6mslkv0palh" +path="res://.godot/imported/guertin_tile_variance.glsl-2fb44423dc25efae19822b8cfbe32a55.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_variance.glsl" +dest_files=["res://.godot/imported/guertin_tile_variance.glsl-2fb44423dc25efae19822b8cfbe32a55.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/Guertin/base_guertin_motion_blur.gd b/addons/SphynxMotionBlurToolkit/Guertin/base_guertin_motion_blur.gd new file mode 100644 index 0000000..58c32e6 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/base_guertin_motion_blur.gd @@ -0,0 +1,12 @@ +extends "res://addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor_effect.gd" + +@export_group("Shader Parameters") +@export var tile_size : int = 40 + +@export var linear_falloff_slope : float = 1 + +@export var importance_bias : float = 40 + +@export var maximum_jitter_value : float = 0.95 + +@export var minimum_user_threshold : float = 1.5 diff --git a/addons/SphynxMotionBlurToolkit/Guertin/guertin_blur_stage.tres b/addons/SphynxMotionBlurToolkit/Guertin/guertin_blur_stage.tres new file mode 100644 index 0000000..32072c4 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/guertin_blur_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://dre56ajymywpr"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_loemu"] +[ext_resource type="RDShaderFile" uid="uid://m6rlgfu6i0b3" path="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_kino_blur.glsl" id="2_uo41r"] + +[resource] +script = ExtResource("1_loemu") +shader_file = ExtResource("2_uo41r") diff --git a/addons/SphynxMotionBlurToolkit/Guertin/guertin_experimental_blur_stage.tres b/addons/SphynxMotionBlurToolkit/Guertin/guertin_experimental_blur_stage.tres new file mode 100644 index 0000000..fae83c2 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/guertin_experimental_blur_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://ca45noqewsyvp"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_kvtxq"] +[ext_resource type="RDShaderFile" uid="uid://br71y0l0rxt8h" path="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_experimental_blur.glsl" id="2_ykr12"] + +[resource] +script = ExtResource("1_kvtxq") +shader_file = ExtResource("2_ykr12") diff --git a/addons/SphynxMotionBlurToolkit/Guertin/guertin_motion_blur.gd b/addons/SphynxMotionBlurToolkit/Guertin/guertin_motion_blur.gd new file mode 100644 index 0000000..2f43539 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/guertin_motion_blur.gd @@ -0,0 +1,245 @@ +extends "res://addons/SphynxMotionBlurToolkit/Guertin/base_guertin_motion_blur.gd" +class_name OldGuertinMotionBlur + +@export_group("Shader Stages") +@export var blur_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Guertin/guertin_blur_stage.tres"): + set(value): + unsubscribe_shader_stage(blur_stage) + blur_stage = value + subscirbe_shader_stage(value) + +@export var overlay_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Guertin/guertin_overlay_stage.tres"): + set(value): + unsubscribe_shader_stage(overlay_stage) + overlay_stage = value + subscirbe_shader_stage(value) + +@export var tile_max_x_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_max_x_stage.tres"): + set(value): + unsubscribe_shader_stage(tile_max_x_stage) + tile_max_x_stage = value + subscirbe_shader_stage(value) + +@export var tile_max_y_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_max_y_stage.tres"): + set(value): + unsubscribe_shader_stage(tile_max_y_stage) + tile_max_y_stage = value + subscirbe_shader_stage(value) + +@export var neighbor_max_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Guertin/guertin_neighbor_max_stage.tres"): + set(value): + unsubscribe_shader_stage(neighbor_max_stage) + neighbor_max_stage = value + subscirbe_shader_stage(value) + +@export var tile_variance_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_variance_stage.tres"): + set(value): + unsubscribe_shader_stage(tile_variance_stage) + tile_variance_stage = value + subscirbe_shader_stage(value) + +var output_color: StringName = "output_color" + +var tile_max_x : StringName = "tile_max_x" + +var tile_max : StringName = "tile_max" + +var neighbor_max : StringName = "neighbor_max" + +var tile_variance : StringName = "tile_variance" + +var custom_velocity : StringName = "custom_velocity" + +var freeze : bool = false + +var temp_intensity : float + +var previous_time : float = 0 + +func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSceneBuffersRD, render_scene_data : RenderSceneDataRD): + var time : float = float(Time.get_ticks_msec()) / 1000 + + var delta_time : float = time - previous_time + + previous_time = time + + temp_intensity = intensity + + if framerate_independent: + var capped_frame_time : float = 1 / target_constant_framerate + + if !uncapped_independence: + capped_frame_time = min(capped_frame_time, delta_time) + + temp_intensity = intensity * capped_frame_time / delta_time + + ensure_texture(tile_max_x, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1.)) + ensure_texture(tile_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1. / tile_size)) + ensure_texture(neighbor_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1. / tile_size)) + ensure_texture(tile_variance, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1. / tile_size)) + ensure_texture(custom_velocity, render_scene_buffers) + ensure_texture(output_color, render_scene_buffers) + + rd.draw_command_begin_label("Motion Blur", Color(1.0, 1.0, 1.0, 1.0)) + + var tile_max_x_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_tile_max_x_push_constants : PackedInt32Array = [ + tile_size, + 0, + 0, + 0 + ] + var tile_max_x_push_constants_byte_array = tile_max_x_push_constants.to_byte_array() + tile_max_x_push_constants_byte_array.append_array(int_tile_max_x_push_constants.to_byte_array()) + + var tile_max_y_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_tile_max_y_push_constants : PackedInt32Array = [ + tile_size, + 0, + 0, + 0 + ] + var tile_max_y_push_constants_byte_array = tile_max_y_push_constants.to_byte_array() + tile_max_y_push_constants_byte_array.append_array(int_tile_max_y_push_constants.to_byte_array()) + + var neighbor_max_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_neighbor_max_push_constants : PackedInt32Array = [ + 0, + 0, + 0, + 0 + ] + var neighbor_max_push_constants_byte_array = neighbor_max_push_constants.to_byte_array() + neighbor_max_push_constants_byte_array.append_array(int_neighbor_max_push_constants.to_byte_array()) + + var tile_variance_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_tile_variance_push_constants : PackedInt32Array = [ + 0, + 0, + 0, + 0 + ] + var tile_variance_push_constants_byte_array = tile_variance_push_constants.to_byte_array() + tile_variance_push_constants_byte_array.append_array(int_tile_variance_push_constants.to_byte_array()) + + var blur_push_constants: PackedFloat32Array = [ + minimum_user_threshold, + importance_bias, + maximum_jitter_value, + temp_intensity, + ] + var int_blur_push_constants : PackedInt32Array = [ + tile_size, + samples, + Engine.get_frames_drawn() % 8, + 0 + ] + var blur_push_constants_byte_array = blur_push_constants.to_byte_array() + blur_push_constants_byte_array.append_array(int_blur_push_constants.to_byte_array()) + + var view_count = render_scene_buffers.get_view_count() + + for view in range(view_count): + var color_image := render_scene_buffers.get_color_layer(view) + var depth_image := render_scene_buffers.get_depth_layer(view) + var output_color_image := render_scene_buffers.get_texture_slice(context, output_color, view, 0, 1, 1) + var tile_max_x_image := render_scene_buffers.get_texture_slice(context, tile_max_x, view, 0, 1, 1) + var tile_max_image := render_scene_buffers.get_texture_slice(context, tile_max, view, 0, 1, 1) + var neighbor_max_image := render_scene_buffers.get_texture_slice(context, neighbor_max, view, 0, 1, 1) + var tile_variance_image := render_scene_buffers.get_texture_slice(context, tile_variance, view, 0, 1, 1) + var custom_velocity_image := render_scene_buffers.get_texture_slice(context, custom_velocity, view, 0, 1, 1) + + var x_groups := floori((render_size.x / tile_size - 1) / 16 + 1) + var y_groups := floori((render_size.y - 1) / 16 + 1) + + dispatch_stage(tile_max_x_stage, + [ + get_sampler_uniform(custom_velocity_image, 0, false), + get_sampler_uniform(depth_image, 1, false), + get_image_uniform(tile_max_x_image, 2) + ], + tile_max_x_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "TileMaxX", + view) + + x_groups = floori((render_size.x / tile_size - 1) / 16 + 1) + y_groups = floori((render_size.y / tile_size - 1) / 16 + 1) + + dispatch_stage(tile_max_y_stage, + [ + get_sampler_uniform(tile_max_x_image, 0, false), + get_image_uniform(tile_max_image, 1) + ], + tile_max_y_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "TileMaxY", + view) + + dispatch_stage(neighbor_max_stage, + [ + get_sampler_uniform(tile_max_image, 0, false), + get_image_uniform(neighbor_max_image, 1) + ], + neighbor_max_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "NeighborMax", + view) + + dispatch_stage(tile_variance_stage, + [ + get_sampler_uniform(tile_max_image, 0, false), + get_image_uniform(tile_variance_image, 1) + ], + tile_variance_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "TileVariance", + view) + + x_groups = floori((render_size.x - 1) / 16 + 1) + y_groups = floori((render_size.y - 1) / 16 + 1) + + dispatch_stage(blur_stage, + [ + get_sampler_uniform(color_image, 0, false), + get_sampler_uniform(custom_velocity_image, 1, false), + get_sampler_uniform(neighbor_max_image, 2, false), + get_sampler_uniform(tile_variance_image, 3, true), + get_image_uniform(output_color_image, 4), + ], + blur_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "Blur", + view) + + dispatch_stage(overlay_stage, + [ + get_sampler_uniform(output_color_image, 0, false), + get_image_uniform(color_image, 1) + ], + [], + Vector3i(x_groups, y_groups, 1), + "Overlay result", + view) + + rd.draw_command_end_label() diff --git a/addons/SphynxMotionBlurToolkit/Guertin/guertin_neighbor_max_stage.tres b/addons/SphynxMotionBlurToolkit/Guertin/guertin_neighbor_max_stage.tres new file mode 100644 index 0000000..a742592 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/guertin_neighbor_max_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://cvb65hfs2lrxo"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_i1bu0"] +[ext_resource type="RDShaderFile" uid="uid://bn88jkvr17x4j" path="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_neighbor_max.glsl" id="2_jp4do"] + +[resource] +script = ExtResource("1_i1bu0") +shader_file = ExtResource("2_jp4do") diff --git a/addons/SphynxMotionBlurToolkit/Guertin/guertin_overlay_stage.tres b/addons/SphynxMotionBlurToolkit/Guertin/guertin_overlay_stage.tres new file mode 100644 index 0000000..fed9f06 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/guertin_overlay_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://bidsfymvdyhek"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_2uett"] +[ext_resource type="RDShaderFile" uid="uid://i6rnwhmss334" path="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_overlay.glsl" id="2_evkw4"] + +[resource] +script = ExtResource("1_2uett") +shader_file = ExtResource("2_evkw4") diff --git a/addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_max_x_stage.tres b/addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_max_x_stage.tres new file mode 100644 index 0000000..53cffa5 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_max_x_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://dipvwksvqb3dm"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_bxcqf"] +[ext_resource type="RDShaderFile" uid="uid://d0s5upcgm7r6l" path="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_x.glsl" id="2_q6kae"] + +[resource] +script = ExtResource("1_bxcqf") +shader_file = ExtResource("2_q6kae") diff --git a/addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_max_y_stage.tres b/addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_max_y_stage.tres new file mode 100644 index 0000000..6dde404 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_max_y_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://bxfg45ubc2pv7"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_gy5dj"] +[ext_resource type="RDShaderFile" uid="uid://ceetvitdbio4l" path="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_y.glsl" id="2_grpec"] + +[resource] +script = ExtResource("1_gy5dj") +shader_file = ExtResource("2_grpec") diff --git a/addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_variance_stage.tres b/addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_variance_stage.tres new file mode 100644 index 0000000..1565004 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_variance_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://bqehecsdgt70s"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_kkpwt"] +[ext_resource type="RDShaderFile" uid="uid://by6mslkv0palh" path="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_variance.glsl" id="2_r5u5d"] + +[resource] +script = ExtResource("1_kkpwt") +shader_file = ExtResource("2_r5u5d") diff --git a/addons/SphynxMotionBlurToolkit/Guertin/new_guertin_motion_blur.gd b/addons/SphynxMotionBlurToolkit/Guertin/new_guertin_motion_blur.gd new file mode 100644 index 0000000..ea42e23 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/new_guertin_motion_blur.gd @@ -0,0 +1,245 @@ +extends "res://addons/SphynxMotionBlurToolkit/Guertin/base_guertin_motion_blur.gd" +class_name GuertinMotionBlur + +@export_group("Shader Stages") +@export var blur_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Guertin/guertin_experimental_blur_stage.tres"): + set(value): + unsubscribe_shader_stage(blur_stage) + blur_stage = value + subscirbe_shader_stage(value) + +@export var overlay_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Guertin/guertin_overlay_stage.tres"): + set(value): + unsubscribe_shader_stage(overlay_stage) + overlay_stage = value + subscirbe_shader_stage(value) + +@export var tile_max_x_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_max_x_stage.tres"): + set(value): + unsubscribe_shader_stage(tile_max_x_stage) + tile_max_x_stage = value + subscirbe_shader_stage(value) + +@export var tile_max_y_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_max_y_stage.tres"): + set(value): + unsubscribe_shader_stage(tile_max_y_stage) + tile_max_y_stage = value + subscirbe_shader_stage(value) + +@export var neighbor_max_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Guertin/guertin_neighbor_max_stage.tres"): + set(value): + unsubscribe_shader_stage(neighbor_max_stage) + neighbor_max_stage = value + subscirbe_shader_stage(value) + +@export var tile_variance_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_variance_stage.tres"): + set(value): + unsubscribe_shader_stage(tile_variance_stage) + tile_variance_stage = value + subscirbe_shader_stage(value) + +var output_color: StringName = "output_color" + +var tile_max_x : StringName = "tile_max_x" + +var tile_max : StringName = "tile_max" + +var neighbor_max : StringName = "neighbor_max" + +var tile_variance : StringName = "tile_variance" + +var custom_velocity : StringName = "custom_velocity" + +var freeze : bool = false + +var temp_intensity : float + +var previous_time : float = 0 + +func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSceneBuffersRD, render_scene_data : RenderSceneDataRD): + var time : float = float(Time.get_ticks_msec()) / 1000 + + var delta_time : float = time - previous_time + + previous_time = time + + temp_intensity = intensity + + if framerate_independent: + var capped_frame_time : float = 1 / target_constant_framerate + + if !uncapped_independence: + capped_frame_time = min(capped_frame_time, delta_time) + + temp_intensity = intensity * capped_frame_time / delta_time + + ensure_texture(tile_max_x, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1.)) + ensure_texture(tile_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1. / tile_size)) + ensure_texture(neighbor_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1. / tile_size)) + ensure_texture(tile_variance, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1. / tile_size)) + ensure_texture(custom_velocity, render_scene_buffers) + ensure_texture(output_color, render_scene_buffers) + + rd.draw_command_begin_label("Motion Blur", Color(1.0, 1.0, 1.0, 1.0)) + + var tile_max_x_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_tile_max_x_push_constants : PackedInt32Array = [ + tile_size, + 0, + 0, + 0 + ] + var tile_max_x_push_constants_byte_array = tile_max_x_push_constants.to_byte_array() + tile_max_x_push_constants_byte_array.append_array(int_tile_max_x_push_constants.to_byte_array()) + + var tile_max_y_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_tile_max_y_push_constants : PackedInt32Array = [ + tile_size, + 0, + 0, + 0 + ] + var tile_max_y_push_constants_byte_array = tile_max_y_push_constants.to_byte_array() + tile_max_y_push_constants_byte_array.append_array(int_tile_max_y_push_constants.to_byte_array()) + + var neighbor_max_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_neighbor_max_push_constants : PackedInt32Array = [ + 0, + 0, + 0, + 0 + ] + var neighbor_max_push_constants_byte_array = neighbor_max_push_constants.to_byte_array() + neighbor_max_push_constants_byte_array.append_array(int_neighbor_max_push_constants.to_byte_array()) + + var tile_variance_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_tile_variance_push_constants : PackedInt32Array = [ + 0, + 0, + 0, + 0 + ] + var tile_variance_push_constants_byte_array = tile_variance_push_constants.to_byte_array() + tile_variance_push_constants_byte_array.append_array(int_tile_variance_push_constants.to_byte_array()) + + var blur_push_constants: PackedFloat32Array = [ + minimum_user_threshold, + importance_bias, + maximum_jitter_value, + temp_intensity, + ] + var int_blur_push_constants : PackedInt32Array = [ + tile_size, + samples, + Engine.get_frames_drawn() % 8, + 0 + ] + var blur_push_constants_byte_array = blur_push_constants.to_byte_array() + blur_push_constants_byte_array.append_array(int_blur_push_constants.to_byte_array()) + + var view_count = render_scene_buffers.get_view_count() + + for view in range(view_count): + var color_image := render_scene_buffers.get_color_layer(view) + var depth_image := render_scene_buffers.get_depth_layer(view) + var output_color_image := render_scene_buffers.get_texture_slice(context, output_color, view, 0, 1, 1) + var tile_max_x_image := render_scene_buffers.get_texture_slice(context, tile_max_x, view, 0, 1, 1) + var tile_max_image := render_scene_buffers.get_texture_slice(context, tile_max, view, 0, 1, 1) + var neighbor_max_image := render_scene_buffers.get_texture_slice(context, neighbor_max, view, 0, 1, 1) + var tile_variance_image := render_scene_buffers.get_texture_slice(context, tile_variance, view, 0, 1, 1) + var custom_velocity_image := render_scene_buffers.get_texture_slice(context, custom_velocity, view, 0, 1, 1) + + var x_groups := floori((render_size.x / tile_size - 1) / 16 + 1) + var y_groups := floori((render_size.y - 1) / 16 + 1) + + dispatch_stage(tile_max_x_stage, + [ + get_sampler_uniform(custom_velocity_image, 0, false), + get_sampler_uniform(depth_image, 1, false), + get_image_uniform(tile_max_x_image, 2) + ], + tile_max_x_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "TileMaxX", + view) + + x_groups = floori((render_size.x / tile_size - 1) / 16 + 1) + y_groups = floori((render_size.y / tile_size - 1) / 16 + 1) + + dispatch_stage(tile_max_y_stage, + [ + get_sampler_uniform(tile_max_x_image, 0, false), + get_image_uniform(tile_max_image, 1) + ], + tile_max_y_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "TileMaxY", + view) + + dispatch_stage(neighbor_max_stage, + [ + get_sampler_uniform(tile_max_image, 0, false), + get_image_uniform(neighbor_max_image, 1) + ], + neighbor_max_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "NeighborMax", + view) + + dispatch_stage(tile_variance_stage, + [ + get_sampler_uniform(tile_max_image, 0, false), + get_image_uniform(tile_variance_image, 1) + ], + tile_variance_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "TileVariance", + view) + + x_groups = floori((render_size.x - 1) / 16 + 1) + y_groups = floori((render_size.y - 1) / 16 + 1) + + dispatch_stage(blur_stage, + [ + get_sampler_uniform(color_image, 0, false), + get_sampler_uniform(custom_velocity_image, 1, false), + get_sampler_uniform(neighbor_max_image, 2, false), + get_sampler_uniform(tile_variance_image, 3, true), + get_image_uniform(output_color_image, 4), + ], + blur_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "Blur", + view) + + dispatch_stage(overlay_stage, + [ + get_sampler_uniform(output_color_image, 0, false), + get_image_uniform(color_image, 1) + ], + [], + Vector3i(x_groups, y_groups, 1), + "Overlay result", + view) + + rd.draw_command_end_label() diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jf_neighbor_depth_max.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jf_neighbor_depth_max.glsl new file mode 100644 index 0000000..146851a --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jf_neighbor_depth_max.glsl @@ -0,0 +1,63 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D tile_max; +layout(set = 0, binding = 1) uniform sampler2D tile_max_map; +layout(rgba16f, set = 0, binding = 2) uniform writeonly image2D neighbor_max; + +layout(push_constant, std430) uniform Params +{ + float nan5; + float nan6; + float nan7; + float nan8; + int nan1; + int nan2; + int nan3; + int nan4; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + + +void main() +{ + ivec2 render_size = ivec2(textureSize(tile_max, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + + vec2 uvn = (vec2(uvi) + vec2(0.5)) / render_size; + + vec2 max_neighbor_velocity = vec2(0); + + float max_neighbor_depth = -1; + + for(int i = -1; i < 2; i++) + { + for(int j = -1; j < 2; j++) + { + vec2 current_offset = vec2(1) / vec2(render_size) * vec2(i, j); + vec2 current_uv = uvn + current_offset; + if(current_uv.x < 0 || current_uv.x > 1 || current_uv.y < 0 || current_uv.y > 1) + { + continue; + } + + vec3 current_neighbor_sample = textureLod(tile_max_map, current_uv, 0.0).xyz; + + if(current_neighbor_sample.z > max_neighbor_depth) + { + max_neighbor_depth = current_neighbor_sample.z; + max_neighbor_velocity = current_neighbor_sample.xy; + } + } + } + + imageStore(neighbor_max, uvi, vec4(max_neighbor_velocity, 0, 1)); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jf_neighbor_depth_max.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jf_neighbor_depth_max.glsl.import new file mode 100644 index 0000000..4cd9936 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jf_neighbor_depth_max.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://bcivntgn7ipwo" +path="res://.godot/imported/jf_neighbor_depth_max.glsl-d20bc4da7a00b27ca7e046fc2a191610.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jf_neighbor_depth_max.glsl" +dest_files=["res://.godot/imported/jf_neighbor_depth_max.glsl-d20bc4da7a00b27ca7e046fc2a191610.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jf_simple_archive_17_8_24.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jf_simple_archive_17_8_24.glsl new file mode 100644 index 0000000..41ad0aa --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jf_simple_archive_17_8_24.glsl @@ -0,0 +1,201 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D tile_max_sampler; +layout(rgba16f, set = 0, binding = 1) uniform writeonly image2D buffer_a; +layout(rgba16f, set = 0, binding = 2) uniform writeonly image2D buffer_b; +layout(set = 0, binding = 3) uniform sampler2D buffer_a_sampler; +layout(set = 0, binding = 4) uniform sampler2D buffer_b_sampler; + +layout(set = 0, binding = 5, std430) restrict buffer MyDataBuffer { + int iteration_index; +} +iteration_data; + +layout(push_constant, std430) uniform Params +{ + int nan0;//iteration_index; + int last_iteration_index; + int nan1; + int nan2; + float perpen_error_thresh; + float sample_step_multiplier; + float motion_blur_intensity; + float nan_fl_5; + float nan_fl_4; + float nan_fl_3; + float nan_fl_6; + float step_exponent_modifier; + float nan_fl_0;//step_size; + float max_dilation_radius; + float nan_fl_1; + float nan_fl_2; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +const int kernel_size = 8; + +const vec2 check_step_kernel[kernel_size] = { + vec2(-1, 0), + vec2(1, 0), + vec2(0, -1), + vec2(0, 1), + vec2(-1, 1), + vec2(1, -1), + vec2(1, 1), + vec2(-1, -1), +}; + +vec2 get_value(bool a, vec2 uv) +{ + if(a) + { + return textureLod(buffer_a_sampler, uv, 0.0).xy; + } + else + { + return textureLod(buffer_b_sampler, uv, 0.0).xy; + } +} + +void set_value(bool a, ivec2 uvi, vec4 value) +{ + if(a) + { + imageStore(buffer_a, uvi, value); + } + else + { + imageStore(buffer_b, uvi, value); + } +} + +void sample_fitness(vec2 uv_offset, vec4 uv_sample, vec2 render_size, inout vec4 current_sample_fitness) +{ + vec2 sample_velocity = -uv_sample.xy; + +// if (dot(sample_velocity, sample_velocity) <= FLT_MIN || uv_sample.w == 0) +// { +// current_sample_fitness = vec4(10, 10, 0, 0); +// return; +// } + + float velocity_space_distance = dot(sample_velocity, uv_offset) / dot(sample_velocity, sample_velocity); + + float mid_point = params.motion_blur_intensity / 2 + 1e-5; + + float absolute_velocity_space_distance = abs(velocity_space_distance - mid_point); + + float within_velocity_range = step(absolute_velocity_space_distance, mid_point); + + float side_offset = abs(dot(vec2(uv_offset.y, -uv_offset.x), sample_velocity)) / dot(sample_velocity, sample_velocity); + + float within_perpen_error_range = step(side_offset, params.perpen_error_thresh * params.motion_blur_intensity); + + current_sample_fitness = vec4(/*max(absolute_velocity_space_distance, side_offset)*/absolute_velocity_space_distance, velocity_space_distance, uv_sample.w + uv_sample.z * velocity_space_distance, within_velocity_range * within_perpen_error_range); +} + +//float is_sample_better(vec4 a, vec4 b) +//{ +// return 1. - step(b.x * a.w, a.x * b.w);//mix(1. - step(b.x * a.w, a.x * b.w), step(b.z, a.z), step(0.5, b.w) * step(0.5, a.w)); +//} + +//vec4 backtrack_sample(vec2 chosen_uv, vec4 best_sample_fitness) +//{ +// vec4 velocity = textureLod(tile_max_sampler, chosen_uv, 0.0); +// +// vec2 uv_candidate = chosen_uv + velocity.xy; +// +// vec4 velocity_candidate = textureLod(tile_max_sampler, uv_candidate, 0.0); +// +// if((dot(velocity, velocity_candidate) / dot(velocity, velocity)) > 0.5 && velocity_candidate.w > 0) +// { +// return vec4(uv_candidate, 0, 0); +// } +// else +// { +// return vec4(chosen_uv, 0, 0); +// } +//} + +void main() +{ + ivec2 render_size = ivec2(textureSize(tile_max_sampler, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + + vec2 uvn = (vec2(uvi) + vec2(0.5)) / render_size; + + vec2 step_size = vec2(round(pow(2 + params.step_exponent_modifier, params.last_iteration_index - iteration_data.iteration_index))); + + vec2 uv_step = vec2(round(step_size)) / render_size; + + vec4 best_sample_fitness = vec4(10, 10, 0, 0); + + vec2 chosen_uv = uvn; + + bool set_a = !bool(step(0.5, float(iteration_data.iteration_index % 2))); + + iteration_data.iteration_index += 1; + + vec2 step_offset; + + vec2 check_uv; + + vec4 uv_sample; + + vec4 current_sample_fitness; + + for(int i = 0; i < kernel_size; i++) + { + step_offset = check_step_kernel[i] * uv_step; + check_uv = uvn + step_offset; + + if(any(notEqual(check_uv, clamp(check_uv, vec2(0.0), vec2(1.0))))) + { + continue; + } + +// if(iteration_data.iteration_index > 0) +// { + check_uv = get_value(!set_a, check_uv).xy; + + step_offset = check_uv - uvn; +// } + + uv_sample = textureLod(tile_max_sampler, check_uv, 0.0); + + sample_fitness(step_offset, uv_sample, render_size, current_sample_fitness); + + float sample_better = 1. - step(current_sample_fitness.z * current_sample_fitness.w, best_sample_fitness.z * best_sample_fitness.w); + best_sample_fitness = mix(best_sample_fitness, current_sample_fitness, sample_better); + chosen_uv = mix(chosen_uv, check_uv, sample_better); + } + +// if(params.iteration_index < params.last_iteration_index) +// { +// set_value(set_a, uvi, vec4(chosen_uv, 0, 0)); +// return; +// } +// +// float depth = textureLod(tile_max_sampler, uvn, 0.0).w; +// +// if(params.iteration_index == params.last_iteration_index && (best_sample_fitness.w < 0.5 || depth > best_sample_fitness.z)) +// { +// set_value(set_a, uvi, vec4(uvn, 0, 0)); +// return; +// } + + set_value(set_a, uvi, vec4(chosen_uv, 0, 0)); + +// vec4 backtracked_sample = backtrack_sample(chosen_uv, best_sample_fitness); +// +// set_value(set_a, uvi, backtracked_sample); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jf_simple_archive_17_8_24.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jf_simple_archive_17_8_24.glsl.import new file mode 100644 index 0000000..7e8a887 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jf_simple_archive_17_8_24.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://brlr85tfh5tv2" +path="res://.godot/imported/jf_simple_archive_17_8_24.glsl-e91ee2bf9d7e74579e89e443fc0e02d3.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jf_simple_archive_17_8_24.glsl" +dest_files=["res://.godot/imported/jf_simple_archive_17_8_24.glsl-e91ee2bf9d7e74579e89e443fc0e02d3.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jfp_simple_push_based_archive.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jfp_simple_push_based_archive.glsl new file mode 100644 index 0000000..3b5e671 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jfp_simple_push_based_archive.glsl @@ -0,0 +1,192 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D tile_max_sampler; +layout(rgba16f, set = 0, binding = 1) uniform writeonly image2D buffer_a; +layout(rgba16f, set = 0, binding = 2) uniform writeonly image2D buffer_b; +layout(set = 0, binding = 3) uniform sampler2D buffer_a_sampler; +layout(set = 0, binding = 4) uniform sampler2D buffer_b_sampler; + +layout(push_constant, std430) uniform Params +{ + int iteration_index; + int last_iteration_index; + int nan1; + int nan2; + float perpen_error_thresh; + float sample_step_multiplier; + float motion_blur_intensity; + float nan_fl_5; + float nan_fl_4; + float nan_fl_3; + float nan_fl_6; + float step_exponent_modifier; + float step_size; + float max_dilation_radius; + float nan_fl_1; + float nan_fl_2; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +const int kernel_size = 8; + +const vec2 check_step_kernel[kernel_size] = { + vec2(-1, 0), + vec2(1, 0), + vec2(0, -1), + vec2(0, 1), + vec2(-1, 1), + vec2(1, -1), + vec2(1, 1), + vec2(-1, -1), +}; + +vec2 get_value(bool a, vec2 uv) +{ + if(a) + { + return textureLod(buffer_a_sampler, uv, 0.0).xy; + } + else + { + return textureLod(buffer_b_sampler, uv, 0.0).xy; + } +} + +void set_value(bool a, ivec2 uvi, vec4 value) +{ + if(a) + { + imageStore(buffer_a, uvi, value); + } + else + { + imageStore(buffer_b, uvi, value); + } +} + +void sample_fitness(vec2 uv_offset, vec4 uv_sample, vec2 render_size, inout vec4 current_sample_fitness) +{ + vec2 sample_velocity = -uv_sample.xy; + +// if (dot(sample_velocity, sample_velocity) <= FLT_MIN || uv_sample.w == 0) +// { +// current_sample_fitness = vec4(10, 10, 0, 0); +// return; +// } + + float velocity_space_distance = dot(sample_velocity, uv_offset) / dot(sample_velocity, sample_velocity); + + float mid_point = params.motion_blur_intensity / 2 + 1e-5; + + float absolute_velocity_space_distance = abs(velocity_space_distance - mid_point); + + float within_velocity_range = step(absolute_velocity_space_distance, mid_point); + + float side_offset = abs(dot(vec2(uv_offset.y, -uv_offset.x), sample_velocity)) / dot(sample_velocity, sample_velocity); + + float within_perpen_error_range = step(side_offset, params.perpen_error_thresh * params.motion_blur_intensity); + + current_sample_fitness = vec4(/*max(absolute_velocity_space_distance, side_offset)*/absolute_velocity_space_distance, velocity_space_distance, uv_sample.w + uv_sample.z * velocity_space_distance, within_velocity_range * within_perpen_error_range); +} + +//float is_sample_better(vec4 a, vec4 b) +//{ +// return 1. - step(b.x * a.w, a.x * b.w);//mix(1. - step(b.x * a.w, a.x * b.w), step(b.z, a.z), step(0.5, b.w) * step(0.5, a.w)); +//} + +//vec4 backtrack_sample(vec2 chosen_uv, vec4 best_sample_fitness) +//{ +// vec4 velocity = textureLod(tile_max_sampler, chosen_uv, 0.0); +// +// vec2 uv_candidate = chosen_uv + velocity.xy; +// +// vec4 velocity_candidate = textureLod(tile_max_sampler, uv_candidate, 0.0); +// +// if((dot(velocity, velocity_candidate) / dot(velocity, velocity)) > 0.5 && velocity_candidate.w > 0) +// { +// return vec4(uv_candidate, 0, 0); +// } +// else +// { +// return vec4(chosen_uv, 0, 0); +// } +//} + +void main() +{ + ivec2 render_size = ivec2(textureSize(tile_max_sampler, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + + vec2 uvn = (vec2(uvi) + vec2(0.5)) / render_size; + + vec2 uv_step = vec2(round(params.step_size)) / render_size; + + vec4 best_sample_fitness = vec4(10, 10, 0, 0); + + vec2 chosen_uv = uvn; + + bool set_a = !bool(step(0.5, float(params.iteration_index % 2))); + + vec2 step_offset; + + vec2 check_uv; + + vec4 uv_sample; + + vec4 current_sample_fitness; + + for(int i = 0; i < kernel_size; i++) + { + step_offset = check_step_kernel[i] * uv_step; + check_uv = uvn + step_offset; + + if(any(notEqual(check_uv, clamp(check_uv, vec2(0.0), vec2(1.0))))) + { + continue; + } + + if(params.iteration_index > 0) + { + check_uv = get_value(!set_a, check_uv).xy; + + step_offset = check_uv - uvn; + } + + uv_sample = textureLod(tile_max_sampler, check_uv, 0.0); + + sample_fitness(step_offset, uv_sample, render_size, current_sample_fitness); + + float sample_better = 1. - step(current_sample_fitness.z * current_sample_fitness.w, best_sample_fitness.z * best_sample_fitness.w); + best_sample_fitness = mix(best_sample_fitness, current_sample_fitness, sample_better); + chosen_uv = mix(chosen_uv, check_uv, sample_better); + } + +// if(params.iteration_index < params.last_iteration_index) +// { +// set_value(set_a, uvi, vec4(chosen_uv, 0, 0)); +// return; +// } +// +// float depth = textureLod(tile_max_sampler, uvn, 0.0).w; +// +// if(params.iteration_index == params.last_iteration_index && (best_sample_fitness.w < 0.5 || depth > best_sample_fitness.z)) +// { +// set_value(set_a, uvi, vec4(uvn, 0, 0)); +// return; +// } + + set_value(set_a, uvi, vec4(chosen_uv, 0, 0)); + +// vec4 backtracked_sample = backtrack_sample(chosen_uv, best_sample_fitness); +// +// set_value(set_a, uvi, backtracked_sample); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jfp_simple_push_based_archive.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jfp_simple_push_based_archive.glsl.import new file mode 100644 index 0000000..ace608e --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jfp_simple_push_based_archive.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://c7q41dxu78i8o" +path="res://.godot/imported/jfp_simple_push_based_archive.glsl-a99001e07de7540b5869f83d2e3643a4.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jfp_simple_push_based_archive.glsl" +dest_files=["res://.godot/imported/jfp_simple_push_based_archive.glsl-a99001e07de7540b5869f83d2e3643a4.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jump_flood_mcguire_blur.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jump_flood_mcguire_blur.glsl new file mode 100644 index 0000000..af39e6a --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jump_flood_mcguire_blur.glsl @@ -0,0 +1,235 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 +#define M_PI 3.1415926535897932384626433832795 + +layout(set = 0, binding = 0) uniform sampler2D color_sampler; +layout(set = 0, binding = 1) uniform sampler2D depth_sampler; +layout(set = 0, binding = 2) uniform sampler2D vector_sampler; +layout(set = 0, binding = 3) uniform sampler2D velocity_map; +layout(rgba16f, set = 0, binding = 4) uniform writeonly image2D output_image; +layout(rgba16f, set = 0, binding = 5) uniform writeonly image2D debug_1_image; +layout(rgba16f, set = 0, binding = 6) uniform writeonly image2D debug_2_image; +layout(rgba16f, set = 0, binding = 7) uniform writeonly image2D debug_3_image; +layout(rgba16f, set = 0, binding = 8) uniform writeonly image2D debug_4_image; +layout(rgba16f, set = 0, binding = 9) uniform writeonly image2D debug_5_image; +layout(rgba16f, set = 0, binding = 10) uniform writeonly image2D debug_6_image; +layout(rgba16f, set = 0, binding = 11) uniform writeonly image2D debug_7_image; +layout(rgba16f, set = 0, binding = 12) uniform writeonly image2D debug_8_image; +layout(set = 0, binding = 13) uniform sampler2D tile_max; + +layout(push_constant, std430) uniform Params +{ + float motion_blur_samples; + float motion_blur_intensity; + float motion_blur_center_fade; + float frame; + float last_iteration_index; + float sample_step_multiplier; + float step_exponent_modifier; + float max_dilation_radius; + int nan0; + int nan1; + int nan2; + int nan3; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +// McGuire's functions https://docs.google.com/document/d/1IIlAKTj-O01hcXEdGxTErQbCHO9iBmRx6oFUy_Jm0fI/edit +// ---------------------------------------------------------- +float soft_depth_compare(float depth_X, float depth_Y, float sze) +{ + return clamp(1 - (depth_X - depth_Y) / sze, 0, 1); +} + +float cone(float T, float v) +{ + return clamp(1 - T / v, 0, 1); +} + +float cylinder(float T, float v) +{ + return 1.0 - smoothstep(0.95 * v, 1.05 * v, T); +} +// ---------------------------------------------------------- + +// Guertin's functions https://research.nvidia.com/sites/default/files/pubs/2013-11_A-Fast-and/Guertin2013MotionBlur-small.pdf +// ---------------------------------------------------------- +float z_compare(float a, float b, float sze) +{ + return clamp(1. - sze * (a - b) / min(a, b), 0, 1); +} +// ---------------------------------------------------------- + +// from https://www.shadertoy.com/view/ftKfzc +// ---------------------------------------------------------- +float interleaved_gradient_noise(vec2 uv){ + uv += float(params.frame) * (vec2(47, 17) * 0.695); + + vec3 magic = vec3( 0.06711056, 0.00583715, 52.9829189 ); + + return fract(magic.z * fract(dot(uv, magic.xy))); +} +// ---------------------------------------------------------- + +// from https://github.com/bradparks/KinoMotion__unity_motion_blur/tree/master +// ---------------------------------------------------------- +vec2 safenorm(vec2 v) +{ + float l = max(length(v), 1e-6); + return v / l * int(1 >= 0.5); +} + +vec2 jitter_tile(vec2 uvi) +{ + float rx, ry; + float angle = interleaved_gradient_noise(uvi + vec2(2, 0)) * M_PI * 2; + rx = cos(angle); + ry = sin(angle); + return vec2(rx, ry) / textureSize(tile_max, 0) / 4; +} +// ---------------------------------------------------------- + +float get_motion_difference(vec2 V, vec2 V2, float power) +{ + vec2 VO = V - V2; + float difference = dot(VO, V) / max(FLT_MIN, dot(V, V)); + return pow(clamp(difference, 0, 1), power); +} + +vec2 sample_random_offset(vec2 uv, float j) +{ + return vec2(0); +} + +void main() +{ + ivec2 render_size = ivec2(textureSize(color_sampler, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + + vec2 x = (vec2(uvi) + vec2(0.5)) / vec2(render_size); + + vec2 velocity_map_sample = textureLod(velocity_map, x + jitter_tile(uvi), 0.0).xy; + + vec3 vnz = textureLod(tile_max, velocity_map_sample, 0.0).xyz * vec3(render_size, 1);// * 2; + + vec2 vn = vnz.xy; + + float vn_length = max(0.5, length(vn)); + + vec2 wn = safenorm(vn); + + vec4 col_x = textureLod(color_sampler, x, 0.0); + + vec3 vxz = textureLod(vector_sampler, x, 0.0).xyz * vec3(render_size, 1);// * 2; + + vec2 vx = vxz.xy; + + if(vn_length <= 0.5) + { + imageStore(output_image, uvi, col_x); + imageStore(debug_1_image, uvi, col_x); + imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1))); + imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1))); + imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1))); + imageStore(debug_5_image, uvi, 10 * abs(textureLod(tile_max, x, 0.0))); + imageStore(debug_6_image, uvi, 10 * abs(textureLod(tile_max, textureLod(velocity_map, x, 0.0).xy, 0.0))); + imageStore(debug_7_image, uvi, 10 * abs(textureLod(velocity_map, x, 0.0))); + imageStore(debug_8_image, uvi, abs(textureLod(velocity_map, x, 0.0) / 10)); + return; + } + + float zx = -0.05 / max(FLT_MIN, textureLod(depth_sampler, x, 0.0).x); + + float vx_length = max(0.5, length(vx)); + + vec2 wx = safenorm(vx); + + vec2 wp = vec2(-wn.y, wn.x); + + if(dot(wp, vx) < 0) + { + wp = -wp; + } + + vec2 wc = safenorm(mix(wp, wx, clamp((vx_length - 0.5) / 1.5, 0, 1))); + + float weight = 1;//params.motion_blur_samples / (100 * vx_length); + + vec4 sum = col_x * weight; + + float j = interleaved_gradient_noise(uvi) - 0.5; + + int vnvx = 2;//int(vn_length / (10 + vx_length)) + 2; + + for(int i = 0; i < params.motion_blur_samples; i++) + { + if(i == (params.motion_blur_samples - 1) / 2) + { + continue; + } + float t = mix(-1., 0.0, (i + j + 1.0) / (params.motion_blur_samples + 1.0)); + + float T = abs(t * vn_length); + + float Tx = abs((t + 0.5) * vn_length); + + bool sample_main_v = !(((i - 1) % vnvx) == 0); + + vec2 d = vn;//sample_main_v ? vn : vx; + + float dz = vnz.z;//sample_main_v ? vnz.z : vxz.z; + + vec2 wd = safenorm(d); + + vec2 y = x + (d / render_size) * t; + + vec2 vy = textureLod(vector_sampler, y, 0.0).xy * render_size;// * 2; + + float vy_length = max(0.5, length(vy)); + + float zy = -0.05 / max(FLT_MIN, textureLod(depth_sampler, y, 0.0).x - dz * t); + + float f = z_compare(zy, zx, 15); + float b = z_compare(zx, zy, 15); + + float wa = abs(max(0, dot(vy / vy_length, wd))); + + float wb = abs((dot(wc, wd))); + + float cone_x = cone(T, vx_length); // how much of the velocity reaches the current position + + float cone_y = cone(T, vy_length); // how much of the velocity reaches the current position + + float ay = clamp(max(step(FLT_MIN, f * wa * cone_y), step(FLT_MIN, b * wb * cone_x)), 0, 1);// * wb;// + cylinder(T, vy_length) * cylinder(T, vx_length) * 2;//cylinder(T, min(vy_length, vx_length)) * 2. * max(wa, wb);// + + vec4 col_y = textureLod(color_sampler, y, 0.0); + + vec4 final_color = mix(col_x, col_y, ay); + + float final_weight = mix(1, 1, ay); + + weight += final_weight;//ay; + sum += final_color * final_weight;// * ay; + } + + sum /= weight; + + imageStore(output_image, uvi, sum); + + imageStore(debug_1_image, uvi, sum); + imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1))); + imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1))); + imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1))); + imageStore(debug_5_image, uvi, 10 * abs(textureLod(tile_max, x, 0.0))); + imageStore(debug_6_image, uvi, 10 * abs(textureLod(tile_max, textureLod(velocity_map, x, 0.0).xy, 0.0))); + imageStore(debug_7_image, uvi, 10 * abs(textureLod(velocity_map, x, 0.0))); + imageStore(debug_8_image, uvi, abs(textureLod(velocity_map, x, 0.0) / 10)); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jump_flood_mcguire_blur.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jump_flood_mcguire_blur.glsl.import new file mode 100644 index 0000000..c4aceb1 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jump_flood_mcguire_blur.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://dc6r26wwdjceq" +path="res://.godot/imported/jump_flood_mcguire_blur.glsl-db182d03471f2a14ff66b8fcdafe8dc6.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jump_flood_mcguire_blur.glsl" +dest_files=["res://.godot/imported/jump_flood_mcguire_blur.glsl-db182d03471f2a14ff66b8fcdafe8dc6.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jump_flood_past_experimental_blur.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jump_flood_past_experimental_blur.glsl new file mode 100644 index 0000000..08acb52 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jump_flood_past_experimental_blur.glsl @@ -0,0 +1,452 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 +#define M_PI 3.1415926535897932384626433832795 + +layout(set = 0, binding = 0) uniform sampler2D color_sampler; +layout(set = 0, binding = 1) uniform sampler2D depth_sampler; +layout(set = 0, binding = 2) uniform sampler2D velocity_sampler; +layout(set = 0, binding = 3) uniform sampler2D velocity_map; +layout(rgba16f, set = 0, binding = 4) uniform writeonly image2D output_image; +layout(set = 0, binding = 5) uniform sampler2D tile_max; +layout(set = 0, binding = 6) uniform sampler2D past_color_sampler; +layout(set = 0, binding = 7) uniform sampler2D past_velocity_sampler; + +layout(push_constant, std430) uniform Params +{ + float motion_blur_samples; + float motion_blur_intensity; + float motion_blur_center_fade; + float frame; + float last_iteration_index; + float sample_step_multiplier; + float step_exponent_modifier; + float max_dilation_radius; + int nan0; + int nan1; + int nan2; + int nan3; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +// McGuire's functions https://docs.google.com/document/d/1IIlAKTj-O01hcXEdGxTErQbCHO9iBmRx6oFUy_Jm0fI/edit +// ---------------------------------------------------------- +float soft_depth_compare(float depth_X, float depth_Y, float sze) +{ + return clamp(1 - (depth_X - depth_Y) / sze, 0, 1); +} + +float cone(float T, float v) +{ + return clamp(1 - T / v, 0, 1); +} + +float cylinder(float T, float v) +{ + return 1.0 - smoothstep(0.95 * v, 1.05 * v, T); +} +// ---------------------------------------------------------- + +// Guertin's functions https://research.nvidia.com/sites/default/files/pubs/2013-11_A-Fast-and/Guertin2013MotionBlur-small.pdf +// ---------------------------------------------------------- +float z_compare(float a, float b, float sze) +{ + return clamp(1. - sze * (a - b), 0, 1); +} +// ---------------------------------------------------------- + +// from https://www.shadertoy.com/view/ftKfzc +// ---------------------------------------------------------- +float interleaved_gradient_noise(vec2 uv){ + uv += float(params.frame) * (vec2(47, 17) * 0.695); + + vec3 magic = vec3( 0.06711056, 0.00583715, 52.9829189 ); + + return fract(magic.z * fract(dot(uv, magic.xy))); +} +// ---------------------------------------------------------- + +// from https://github.com/bradparks/KinoMotion__unity_motion_blur/tree/master +// ---------------------------------------------------------- +vec2 safenorm(vec2 v) +{ + float l = max(length(v), 1e-6); + return v / l * int(l >= 0.5); +} + +vec2 jitter_tile(vec2 uvi) +{ + float rx, ry; + float angle = interleaved_gradient_noise(uvi + vec2(2, 0)) * M_PI * 2; + rx = cos(angle); + ry = sin(angle); + return vec2(rx, ry) / textureSize(tile_max, 0) / 4; +} +// ---------------------------------------------------------- + +void main() +{ + ivec2 render_size = ivec2(textureSize(color_sampler, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + + vec2 x = (vec2(uvi) + vec2(0.5)) / vec2(render_size); + + vec2 velocity_map_sample = textureLod(velocity_map, x + jitter_tile(uvi), 0.0).xy; + + vec3 vnz = textureLod(tile_max, velocity_map_sample, 0.0).xyz * vec3(render_size, 1); + + float vn_length = max(0.5, length(vnz.xy)); + + float multiplier = clamp(vn_length, 0, min(params.max_dilation_radius, vn_length * params.motion_blur_intensity)) / max(FLT_MIN, vn_length); + + vnz.xyz *= multiplier; + + vn_length *= multiplier; + + vec2 vn = vnz.xy; + + vec4 col_x = textureLod(color_sampler, x, 0.0); + + vec2 wn = safenorm(vn); + + vec4 vxz = textureLod(velocity_sampler, x, 0.0) * vec4(render_size, 1, 1); + + float vx_length = max(0.5, length(vxz.xy)); + + multiplier = clamp(vx_length, 0, min(params.max_dilation_radius, vn_length * params.motion_blur_intensity)) / max(FLT_MIN, vx_length); + + vxz.xyz *= multiplier; + + vx_length *= multiplier; + + vec2 vx = vxz.xy; + + if(vn_length <= 0.5) + { + imageStore(output_image, uvi, col_x); + +#ifdef DEBUG + imageStore(debug_1_image, uvi, col_x); + imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1))); + imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1))); + imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1))); + imageStore(debug_5_image, uvi, col_x); +#endif + + return; + } + + float velocity_match = pow(clamp(dot(vx, vn) / dot(vn, vn), 0, 1), 0.25); + + vn = mix(vn, vx, velocity_match); + + vnz = mix(vnz, vxz.xyz, velocity_match); + + float zx = vxz.w; + + vec2 wx = safenorm(vx); + + float weight = 0; + + vec4 sum = col_x * weight; + + float total_back_weight = 1e-10; + + vec4 back_sum = col_x * total_back_weight; + + float j = interleaved_gradient_noise(uvi) - 0.5; + + vec4 past_vxz = textureLod(past_velocity_sampler, x, 0.0) * vec4(render_size, 1, 1); + + vec2 past_vx = past_vxz.xy; + + vec4 past_col_x = textureLod(past_color_sampler, x, 0.0); + + for(int i = 0; i < params.motion_blur_samples; i++) + { + float nai_t = mix(0., -1., (i + j + 1.0) / (params.motion_blur_samples + 1.0)); + + float nai_T = abs(nai_t * vx_length); + + vec2 nai_y = x + (vx / render_size) * nai_t; + + if(nai_y.x < 0 || nai_y.x > 1 || nai_y.y < 0 || nai_y.y > 1) + { + continue; + } + + vec4 nai_vy = textureLod(velocity_sampler, nai_y, 0.0) * vec4(render_size, 1, 1); + + float nai_zy = nai_vy.w - vxz.z * nai_t; + + float nai_b = z_compare(-zx, -nai_zy, 20000); + + float nai_f = z_compare(-nai_zy, -zx, 20000); + + float nai_ay = nai_b + (1 - nai_f); + + float past_t = mix(0., -1., (i + j + 1.0) / (params.motion_blur_samples + 1.0)); + + vec2 past_y = x + (past_vx / render_size) * past_t; + + float alpha = z_compare(-past_vxz.w, -vxz.w, 20000); // may need to be a step + + vec4 past_vy = mix(textureLod(past_velocity_sampler, past_y, 0.0) * vec4(render_size, 1, 1), textureLod(velocity_sampler, past_y, 0.0) * vec4(render_size, 1, 1), alpha); + + float past_zy = past_vy.w - past_vxz.z * past_t; + + float past_b = z_compare(-past_vxz.w, -past_zy, 20000); + + vec4 nai_col_y = mix(textureLod(color_sampler, nai_y, 0.0), mix(textureLod(past_color_sampler, x, 0.0), mix(textureLod(past_color_sampler, past_y, 0.0), textureLod(color_sampler, past_y, 0.0), alpha), past_b), (1 - nai_f)); + + total_back_weight += nai_ay; + + back_sum += nai_col_y * nai_ay; + + float t = mix(0., -1., (i + j + 1.0) / (params.motion_blur_samples + 1.0)); + + float T = abs(t * vn_length); + + vec2 y = x + (vn / render_size) * t; + + if(y.x < 0 || y.x > 1 || y.y < 0 || y.y > 1) + { + continue; + } + + vec4 vy = textureLod(velocity_sampler, y, 0.0) * vec4(render_size, 1, 1); + + float vy_length = max(0.5, length(vy.xy)); + + float zy = vy.w - vnz.z * t; + + float f = z_compare(-zy, -zx, 20000); + + float wa = abs(max(0, dot(vy.xy / vy_length, wn))); + + float ay_trail = f * step(T, vy_length * wa); + + vec4 col_y = textureLod(color_sampler, y, 0.0); + + weight += ay_trail; + + sum += col_y * ay_trail; + } + + back_sum *= (params.motion_blur_samples - weight) / total_back_weight; + + sum /= params.motion_blur_samples; + + back_sum /= params.motion_blur_samples; + + imageStore(output_image, uvi, sum + back_sum); + +#ifdef DEBUG + imageStore(debug_1_image, uvi, sum + back_sum); + imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1))); + imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1))); + imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1))); + imageStore(debug_5_image, uvi, col_x); + imageStore(debug_6_image, uvi, past_col_x); + imageStore(debug_7_image, uvi, past_col_x); + imageStore(debug_8_image, uvi, back_sum); +#endif +} + +//void main() +//{ +// ivec2 render_size = ivec2(textureSize(color_sampler, 0)); +// ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); +// if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) +// { +// return; +// } +// +// vec2 x = (vec2(uvi) + vec2(0.5)) / vec2(render_size); +// +// vec2 velocity_map_sample = textureLod(velocity_map, x + jitter_tile(uvi), 0.0).xy; +// +// vec3 vnz = textureLod(tile_max, velocity_map_sample, 0.0).xyz * vec3(render_size, 1);// * 2; +// +// vec2 vn = vnz.xy; +// +// float vn_length = max(0.5, length(vn)); +// +// vec2 wn = safenorm(vn); +// +// vec4 col_x = textureLod(color_sampler, x, 0.0); +// +// vec3 vxz = textureLod(vector_sampler, x, 0.0).xyz * vec3(render_size, 1);// * 2; +// +// vec2 vx = vxz.xy; +// +// vec3 past_vxz = textureLod(past_velocity_sampler, x, 0.0).xyz * vec3(render_size, 1); +// +// vec2 past_vx = past_vxz.xy; +// +// vec4 past_col_x = textureLod(past_color_sampler, x, 0.0); +// +// float velocity_match = pow(clamp(dot(vx, vn) / dot(vn, vn), 0, 1), 0.5); +// +// vn = mix(vn, vx, velocity_match); +// +// vnz = mix(vnz, vxz, velocity_match); +// +// if(vn_length <= 0.5) +// { +// imageStore(output_image, uvi, col_x); +// +//#ifdef DEBUG +// imageStore(debug_1_image, uvi, col_x); +// imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1))); +// imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1))); +// imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1))); +// imageStore(debug_5_image, uvi, col_x); +// imageStore(debug_6_image, uvi, past_col_x); +// imageStore(debug_7_image, uvi, past_col_x); +// imageStore(debug_8_image, uvi, abs(vec4(past_vx / render_size * 10, past_vxz.z * 100, 1))); +//#endif +// return; +// } +// +// float zx = -0.05 / max(FLT_MIN, textureLod(depth_sampler, x, 0.0).x); +// +// float vx_length = max(0.5, length(vx)); +// +// vec2 wx = safenorm(vx); +// +// vec2 wp = vec2(-wn.y, wn.x); +// +// if(dot(wp, vx) < 0) +// { +// wp = -wp; +// } +// +// vec2 wc = safenorm(mix(wp, wx, clamp((vx_length - 0.5) / 1.5, 0, 1))); +// +// float weight = 0;// params.motion_blur_samples / (40 * vx_length); +// +// vec4 sum = col_x * weight; +// +// float j = interleaved_gradient_noise(uvi) - 0.5; +// +// int vnvx = 2;//int(vn_length / (10 + vx_length)) + 2; +// +// float total_back_weight = 1e-10; +// +// vec4 back_sum = col_x * total_back_weight; +// +// for(int i = 0; i < params.motion_blur_samples; i++) +// { +// float t = mix(-1., 0.0, (i + j + 1.0) / (params.motion_blur_samples + 1.0)); +// +// float T = abs(t * vn_length); +// +// float Tx = abs((t + 0.5) * vn_length); +// +// bool sample_main_v = !(((i - 1) % vnvx) == 0); +// +// vec2 d = vn;//sample_main_v ? vn : vx; +// +// vec2 nai_d = vx; +// +// vec2 nai_wd = safenorm(nai_d); +// +// float nai_dz = vxz.z; +// +// vec2 past_nai_d = past_vx; +// +// float dz = vnz.z;//sample_main_v ? vnz.z : vxz.z; +// +// vec2 wd = safenorm(d); +// +// vec2 y = x + (d / render_size) * t; +// +// vec2 nai_y = x + (nai_d / render_size) * t; +// +// vec2 past_nai_y = x + (past_nai_d / render_size) * t; +// +// float nai_y_length = max(0.5, length(nai_y)); +// +// vec2 vy = textureLod(vector_sampler, y, 0.0).xy * render_size;// * 2; +// +// float vy_length = max(0.5, length(vy)); +// +// vec2 nai_vy = textureLod(vector_sampler, nai_y, 0.0).xy * render_size; +// +// float nai_vy_length = max(0.5, length(nai_vy)); +// +// float zy = -0.05 / max(FLT_MIN, textureLod(depth_sampler, y, 0.0).x - dz * t); +// +// float nai_zy = -0.05 / max(FLT_MIN, textureLod(depth_sampler, nai_y, 0.0).x - nai_dz * t); +// +// float f = z_compare(zy, zx, 15); +// float b = z_compare(zx, zy, 15); +// +// float wa = abs(max(0, dot(vy / vy_length, wd))); +// +// float wb = abs((dot(wc, wd))); +// +// float cone_x = cone(T, vx_length); +// +// float cone_y = cone(T, vy_length); +// +// float nai_f = z_compare(nai_zy, zx, 15); +// +// float nai_b = z_compare(zx, nai_zy, 15); +// +// float nai_wa = abs(max(0, dot(nai_vy / nai_vy_length, nai_wd))); +// +// float nai_wb = abs((dot(wc, nai_wd))); +// +// float nai_cone_y = cone(T, nai_vy_length); +// +// float ay_trail = f * wa * step(FLT_MIN, cone_y); +// +// float ay_lead = (1 - f) * wb * step(FLT_MIN, cone_x); +// +// float nai_ay = nai_b;//max(nai_b, nai_f * nai_wa * step(FLT_MIN, nai_cone_y)); +// +// vec4 col_y = textureLod(color_sampler, y, 0.0); +// +// vec4 past_col_y = textureLod(past_color_sampler, past_nai_y, 0.0); +// +// vec4 nai_col_y = textureLod(color_sampler, nai_y, 0.0); +// +// vec4 col_back = nai_col_y; +// +// total_back_weight += nai_ay; +// +// back_sum += col_back * nai_ay; +// +// weight += ay_trail + ay_lead; +// +// sum += col_y * ay_trail + past_col_y * ay_lead; +// } +// +// back_sum *= (params.motion_blur_samples - weight) / total_back_weight; +// +// sum /= params.motion_blur_samples; +// +// back_sum /= params.motion_blur_samples; +// +// imageStore(output_image, uvi, sum + back_sum); +// +//#ifdef DEBUG +// imageStore(debug_1_image, uvi, sum + back_sum); +// imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1))); +// imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1))); +// imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1))); +// imageStore(debug_5_image, uvi, col_x);//sum + back_sum); +// imageStore(debug_6_image, uvi, past_col_x); +// imageStore(debug_7_image, uvi, past_col_x); +// imageStore(debug_8_image, uvi, abs(vec4(past_vx / render_size * 10, past_vxz.z * 100, 1))); +//#endif +//} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jump_flood_past_experimental_blur.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jump_flood_past_experimental_blur.glsl.import new file mode 100644 index 0000000..36407b0 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jump_flood_past_experimental_blur.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://4vnw7nqk2lmb" +path="res://.godot/imported/jump_flood_past_experimental_blur.glsl-75b0138dd1cf1e624e753e1e20d4e672.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/Archive/jump_flood_past_experimental_blur.glsl" +dest_files=["res://.godot/imported/jump_flood_past_experimental_blur.glsl-75b0138dd1cf1e624e753e1e20d4e672.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_x.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_x.glsl new file mode 100644 index 0000000..fc6c26c --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_x.glsl @@ -0,0 +1,61 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D velocity_sampler; +layout(rgba16f, set = 0, binding = 1) uniform writeonly image2D tile_max_x; + +layout(push_constant, std430) uniform Params +{ + float nan5; + float nan6; + float nan7; + float nan8; + int tile_size; + int nan2; + int nan3; + int nan4; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + + +void main() +{ + ivec2 render_size = ivec2(textureSize(velocity_sampler, 0)); + ivec2 output_size = imageSize(tile_max_x); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + int tile_size = render_size.x / output_size.x; + ivec2 global_uvi = uvi * ivec2(tile_size, 1); + if ((uvi.x >= output_size.x) || (uvi.y >= output_size.y) || (global_uvi.x >= render_size.x) || (global_uvi.y >= render_size.y)) + { + return; + } + + vec2 uvn = (vec2(global_uvi) + vec2(0.5)) / render_size; + + vec4 max_velocity = vec4(0); + + float max_velocity_length = -1; + + //bool foreground = false; + + for(int i = 0; i < tile_size; i++) + { + vec2 current_uv = uvn + vec2(float(i) / render_size.x, 0); + vec4 velocity_sample = textureLod(velocity_sampler, current_uv, 0.0); + float current_velocity_length = dot(velocity_sample.xy, velocity_sample.xy); + if(current_velocity_length > max_velocity_length)// || (velocity_sample.w > 0 && !foreground)) + { + max_velocity_length = current_velocity_length; + max_velocity = vec4(velocity_sample); +// if(velocity_sample.w > 0) +// { +// foreground = true; +// } + } + } + imageStore(tile_max_x, uvi, max_velocity); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_x.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_x.glsl.import new file mode 100644 index 0000000..6b1a9ee --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_x.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://djp3da364fk2l" +path="res://.godot/imported/jf_guertin_tile_max_x.glsl-acb187dfb7304d498ecdfb75a54c725d.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_x.glsl" +dest_files=["res://.godot/imported/jf_guertin_tile_max_x.glsl-acb187dfb7304d498ecdfb75a54c725d.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_y.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_y.glsl new file mode 100644 index 0000000..7ba3975 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_y.glsl @@ -0,0 +1,61 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D tile_max_x; +layout(rgba16f, set = 0, binding = 1) uniform writeonly image2D tile_max; + +layout(push_constant, std430) uniform Params +{ + float nan5; + float nan6; + float nan7; + float nan8; + int tile_size; + int nan2; + int nan3; + int nan4; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + + +void main() +{ + ivec2 render_size = ivec2(textureSize(tile_max_x, 0)); + ivec2 output_size = imageSize(tile_max); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + int tile_size = render_size.y / output_size.y; + ivec2 global_uvi = uvi * ivec2(1, tile_size); + if ((uvi.x >= output_size.x) || (uvi.y >= output_size.y) || (global_uvi.x >= render_size.x) || (global_uvi.y >= render_size.y)) + { + return; + } + + vec2 uvn = (vec2(global_uvi) + vec2(0.5)) / render_size; + + vec4 max_velocity = vec4(0); + + float max_velocity_length = -1; + + //bool foreground = false; + + for(int i = 0; i < tile_size; i++) + { + vec2 current_uv = uvn + vec2(0, float(i) / render_size.y); + vec4 velocity_sample = textureLod(tile_max_x, current_uv, 0.0); + float current_velocity_length = dot(velocity_sample.xy, velocity_sample.xy); + if(current_velocity_length > max_velocity_length)// || (velocity_sample.w > 0 && !foreground)) + { + max_velocity_length = current_velocity_length; + max_velocity = vec4(velocity_sample); +// if(velocity_sample.w > 0) +// { +// foreground = true; +// } + } + } + imageStore(tile_max, uvi, max_velocity); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_y.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_y.glsl.import new file mode 100644 index 0000000..c729a25 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_y.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://cqlltc8f21wre" +path="res://.godot/imported/jf_guertin_tile_max_y.glsl-8b893536de27f9161f4a8be7b8c5058f.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_y.glsl" +dest_files=["res://.godot/imported/jf_guertin_tile_max_y.glsl-8b893536de27f9161f4a8be7b8c5058f.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_max.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_max.glsl new file mode 100644 index 0000000..17376b5 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_max.glsl @@ -0,0 +1,67 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D tile_max; +layout(set = 0, binding = 1) uniform sampler2D tile_max_map; +layout(rgba16f, set = 0, binding = 2) uniform writeonly image2D neighbor_max; + +layout(push_constant, std430) uniform Params +{ + float nan5; + float nan6; + float nan7; + float nan8; + int nan1; + int nan2; + int nan3; + int nan4; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + + +void main() +{ + ivec2 render_size = ivec2(textureSize(tile_max, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + + vec2 uvn = (vec2(uvi) + vec2(0.5)) / render_size; + + vec2 best_sample_uv = vec2(uvn); + + float max_neighbor_velocity_length = -1; + + for(int i = -1; i < 2; i++) + { + for(int j = -1; j < 2; j++) + { + vec2 current_offset = vec2(1) / vec2(render_size) * vec2(i, j); + vec2 current_uv = uvn + current_offset; + if(current_uv.x < 0 || current_uv.x > 1 || current_uv.y < 0 || current_uv.y > 1) + { + continue; + } + + vec2 velocity_map_sample = textureLod(tile_max_map, current_uv, 0.0).xy; + + vec4 velocity_sample = textureLod(tile_max, velocity_map_sample, 0.0); + + float current_velocity_length = dot(velocity_sample.xy, velocity_sample.xy); + + if(current_velocity_length > max_neighbor_velocity_length) + { + max_neighbor_velocity_length = current_velocity_length; + best_sample_uv = velocity_map_sample; + } + } + } + + imageStore(neighbor_max, uvi, vec4(best_sample_uv, 0, 1)); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_max.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_max.glsl.import new file mode 100644 index 0000000..5debb67 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_max.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://cfk5chwlcyay4" +path="res://.godot/imported/jf_neighbor_max.glsl-d9e677fd383d0688a8ad642473870160.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_max.glsl" +dest_files=["res://.godot/imported/jf_neighbor_max.glsl-d9e677fd383d0688a8ad642473870160.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_backtracking_experimental.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_backtracking_experimental.glsl new file mode 100644 index 0000000..43ee73c --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_backtracking_experimental.glsl @@ -0,0 +1,283 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D depth_sampler; +layout(set = 0, binding = 1) uniform sampler2D velocity_sampler; +layout(rgba16f, set = 0, binding = 2) uniform writeonly image2D buffer_a; +layout(rgba16f, set = 0, binding = 3) uniform writeonly image2D buffer_b; +layout(set = 0, binding = 4) uniform sampler2D buffer_a_sampler; +layout(set = 0, binding = 5) uniform sampler2D buffer_b_sampler; + +layout(push_constant, std430) uniform Params +{ + int iteration_index; + int last_iteration_index; + int backtracking_sample_count; + int nan2; + float perpen_error_thresh; + float sample_step_multiplier; + float motion_blur_intensity; + float velocity_match_threshold; + float parallel_sensitivity; + float perpendicular_sensitivity; + float depth_match_threshold; + float step_exponent_modifier; + float step_size; + float max_dilation_radius; + float nan_fl_1; + float nan_fl_2; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +const int kernel_size = 8; + +const vec2 check_step_kernel[kernel_size] = { + vec2(-1, 0), + vec2(1, 0), + vec2(0, -1), + vec2(0, 1), + vec2(-1, 1), + vec2(1, -1), + vec2(1, 1), + vec2(-1, -1), +}; + +void get_value(bool a,inout vec2 uv) +{ + if(a) + { + uv = textureLod(buffer_a_sampler, uv, 0.0).xy; + } + else + { + uv = textureLod(buffer_b_sampler, uv, 0.0).xy; + } +} + +void set_value(bool a, ivec2 uvi, vec4 value) +{ + if(a) + { + imageStore(buffer_a, uvi, value); + } + else + { + imageStore(buffer_b, uvi, value); + } +} + +// Motion similarity +// ---------------------------------------------------------- +float get_motion_difference(vec2 V, vec2 V2) +{ + return clamp(dot(V - V2, V) / dot(V, V), 0, 1); +// vec2 VO = V - V2; +// float parallel = dot(VO, V) / dot(V, V); +// return clamp(parallel, 0, 1); +} +// ---------------------------------------------------------- + +void sample_fitness(vec2 uv_offset, vec4 uv_sample, vec2 render_size, inout vec4 curren_sample_fitness) +{ + vec2 sample_velocity = -uv_sample.xy; + + // if velocity is 0, we never reach it (steps never smaller than 1) + if (dot(sample_velocity, sample_velocity) <= FLT_MIN || uv_sample.w == 0) + { + curren_sample_fitness = vec4(FLT_MAX, FLT_MAX, FLT_MAX, 0); + return; + } + + // velocity space distance (projected pixel offset onto velocity vector) + float velocity_space_distance = dot(sample_velocity, uv_offset) / dot(sample_velocity, sample_velocity); + // the velcity space distance to gravitate the JFA to (found more relieable than doing a 0 - 1 range) + float mid_point = params.motion_blur_intensity / 2; + // centralize the velocity space distance around that mid point + float absolute_velocity_space_distance = abs(velocity_space_distance - mid_point); + // if that distance is half the original, its within range (we centered around a mid point) + float within_velocity_range = step(absolute_velocity_space_distance, mid_point); + // perpendicular offset + float side_offset = abs(dot(vec2(uv_offset.y, -uv_offset.x), sample_velocity)) / dot(sample_velocity, sample_velocity); + // arbitrary perpendicular limit (lower means tighter dilation, but less reliable) + float within_perpen_error_range = step(side_offset, params.perpen_error_thresh * params.motion_blur_intensity); + // store relevant data for use in conditions + curren_sample_fitness = vec4(absolute_velocity_space_distance, velocity_space_distance, uv_sample.w + uv_sample.z * velocity_space_distance, within_velocity_range * within_perpen_error_range); +} + +float is_sample_better(vec4 a, vec4 b) +{ + // see explanation at end of code + return mix(1. - step(b.x * a.w, a.x * b.w), step(b.z, a.z), step(0.5, b.w) * step(0.5, a.w)); +} + +// dilation validation and better sample selection +vec4 get_backtracked_sample(vec2 uvn, vec2 chosen_uv, vec3 chosen_velocity, vec4 best_sample_fitness, vec2 render_size) +{ + //return vec4(chosen_uv, best_sample_fitness.z, best_sample_fitness.w);// comment this to enable backtracking + + float smallest_step = 1 / max(render_size.x, render_size.y); + // choose maximum range to check along (matches with implementation in blur stage) + float general_velocity_multiplier = min(best_sample_fitness.y, params.max_dilation_radius * smallest_step / (length(chosen_velocity) * params.motion_blur_intensity)); + + vec2 best_uv = chosen_uv; + + float best_multiplier = best_sample_fitness.y; + + float best_depth = best_sample_fitness.z; + + // set temp variable to keet track of better matches + float smallest_velocity_difference = 0.99;//params.velocity_match_threshold; + // minimum amount of valid velocities to compare before decision + int initial_steps_to_compare = 2; + + int steps_to_compare = initial_steps_to_compare; + + float velocity_multiplier; + + vec2 check_uv; + + vec3 velocity_test; + + float depth_test; + + float velocity_difference; + + float current_depth; + + for(int i = -params.backtracking_sample_count; i < params.backtracking_sample_count + 1; i++) + { + velocity_multiplier = general_velocity_multiplier * (1 + float(i) / float(params.backtracking_sample_count)); + + if(velocity_multiplier > params.motion_blur_intensity || velocity_multiplier < 0) + { + continue; + } + + check_uv = uvn - chosen_velocity.xy * velocity_multiplier; + + if(any(notEqual(check_uv, clamp(check_uv, vec2(0.0), vec2(1.0))))) + { + continue; + } + // get potential velocity and depth matches + velocity_test = textureLod(velocity_sampler, check_uv, 0.0).xyz; + + depth_test = textureLod(depth_sampler, check_uv, 0.0).x; + + velocity_difference = get_motion_difference(chosen_velocity.xy, velocity_test.xy); + + current_depth = depth_test + chosen_velocity.z * velocity_multiplier; + + // if checked sample matches depth and velocity, it is valid for backtracking + if((abs(current_depth - best_sample_fitness.z) < 0.002) && (velocity_difference <= smallest_velocity_difference)) + { + best_uv = check_uv; + best_multiplier = velocity_multiplier; + best_depth = current_depth; + if(steps_to_compare == 0) + { + return vec4(best_uv, best_depth, 0); + } + steps_to_compare--; + } + // if a sample was found and we lost footing after, go with that found sample right away + else if(initial_steps_to_compare > steps_to_compare) + { + return vec4(best_uv, best_depth, 0); + } + } + + return vec4(uvn, best_sample_fitness.z, 1); +} + +void main() +{ + ivec2 render_size = ivec2(textureSize(velocity_sampler, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + + // must be on pixel center for whole values + vec2 uvn = (vec2(uvi) + vec2(0.5)) / render_size; + + vec2 uv_step = vec2(round(params.step_size)) / render_size; + + vec4 best_sample_fitness = vec4(FLT_MAX, FLT_MAX, FLT_MAX, 0.); + + vec2 chosen_uv = uvn; + + vec3 chosen_velocity = vec3(0.); + + bool set_a = !bool(step(0.5, float(params.iteration_index % 2))); + + vec2 step_offset; + + vec2 check_uv; + + vec4 uv_sample; + + vec4 current_sample_fitness; + + for(int i = 0; i < kernel_size; i++) + { + step_offset = check_step_kernel[i] * uv_step; + check_uv = uvn + step_offset; + + if(any(notEqual(check_uv, clamp(check_uv, vec2(0.0), vec2(1.0))))) + { + continue; + } + + if(params.iteration_index > 0.) + { + get_value(!set_a, check_uv); + + step_offset = check_uv - uvn; + } + + uv_sample = vec4(textureLod(velocity_sampler, check_uv, 0.0).xyz, textureLod(depth_sampler, check_uv, 0.0).x); + + sample_fitness(step_offset, uv_sample, render_size, current_sample_fitness); + + if (mix(1. - step(best_sample_fitness.x * current_sample_fitness.w, current_sample_fitness.x * best_sample_fitness.w), step(best_sample_fitness.z, current_sample_fitness.z), step(0.5, best_sample_fitness.w) * step(0.5, current_sample_fitness.w)) > 0.5)//is_sample_better(current_sample_fitness, best_sample_fitness) > 0.5) + { + best_sample_fitness = current_sample_fitness; + chosen_uv = check_uv; + chosen_velocity = uv_sample.xyz; + } + } + + if(params.iteration_index < params.last_iteration_index) + { + set_value(set_a, uvi, vec4(chosen_uv, 0, 0)); + return; + } + + float depth = textureLod(depth_sampler, uvn, 0.0).x; + + // best_sample_fitness.z contains the depth of the texture + offset of velocity z + vec4 backtracked_sample = get_backtracked_sample(uvn, chosen_uv, chosen_velocity, best_sample_fitness, render_size); + + if(best_sample_fitness.w == 0 || depth > backtracked_sample.z) + { + set_value(set_a, uvi, vec4(uvn, 0, 0)); + return; + } + + set_value(set_a, uvi, backtracked_sample); + + return; +} +// +// if((a.w == b.w) && (a.w == 1)) +// { +// return a.z < b.z ? 0. : 1.; +// } +// +// return a.x * b.w < b.x * a.w ? 1. : 0.; \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_backtracking_experimental.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_backtracking_experimental.glsl.import new file mode 100644 index 0000000..73c03a5 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_backtracking_experimental.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://rkkajixdjosk" +path="res://.godot/imported/jfp_backtracking_experimental.glsl-a7a47621c3999d6edb8c655271f824d5.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_backtracking_experimental.glsl" +dest_files=["res://.godot/imported/jfp_backtracking_experimental.glsl-a7a47621c3999d6edb8c655271f824d5.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_simple.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_simple.glsl new file mode 100644 index 0000000..1007993 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_simple.glsl @@ -0,0 +1,150 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D tile_max_sampler; +layout(rgba16f, set = 0, binding = 1) uniform writeonly image2D buffer_a; +layout(rgba16f, set = 0, binding = 2) uniform writeonly image2D buffer_b; +layout(set = 0, binding = 3) uniform sampler2D buffer_a_sampler; +layout(set = 0, binding = 4) uniform sampler2D buffer_b_sampler; + +layout(push_constant, std430) uniform Params +{ + int iteration_index; + int last_iteration_index; + int nan1; + int nan2; + float perpen_error_thresh; + float sample_step_multiplier; + float motion_blur_intensity; + float nan_fl_5; + float nan_fl_4; + float nan_fl_3; + float nan_fl_6; + float step_exponent_modifier; + float nan_fl_0; + float max_dilation_radius; + float nan_fl_1; + float nan_fl_2; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +const int kernel_size = 8; + +const vec2 check_step_kernel[kernel_size] = { + vec2(-1, 0), + vec2(1, 0), + vec2(0, -1), + vec2(0, 1), + vec2(-1, 1), + vec2(1, -1), + vec2(1, 1), + vec2(-1, -1), +}; + +vec2 get_value(bool a, vec2 uv) +{ + if(a) + { + return textureLod(buffer_a_sampler, uv, 0.0).xy; + } + else + { + return textureLod(buffer_b_sampler, uv, 0.0).xy; + } +} + +void set_value(bool a, ivec2 uvi, vec4 value) +{ + if(a) + { + imageStore(buffer_a, uvi, value); + } + else + { + imageStore(buffer_b, uvi, value); + } +} + +void sample_fitness(vec2 uv_offset, vec4 uv_sample, vec2 render_size, inout vec4 current_sample_fitness) +{ + vec2 sample_velocity = -uv_sample.xy; + + if (dot(sample_velocity, sample_velocity) <= FLT_MIN || uv_sample.w == 0) + { + current_sample_fitness = vec4(10, 10, 0, 0); + return; + } + + float velocity_space_distance = dot(sample_velocity, uv_offset) / dot(sample_velocity, sample_velocity); + + float mid_point = params.motion_blur_intensity / 2; + + float absolute_velocity_space_distance = abs(velocity_space_distance - mid_point); + + float within_velocity_range = step(absolute_velocity_space_distance, mid_point); + + float side_offset = abs(dot(vec2(uv_offset.y, -uv_offset.x), sample_velocity)) / dot(sample_velocity, sample_velocity); + + float within_perpen_error_range = step(side_offset, params.perpen_error_thresh * params.motion_blur_intensity); + + current_sample_fitness = vec4(absolute_velocity_space_distance, velocity_space_distance, uv_sample.w + uv_sample.z * velocity_space_distance, within_velocity_range * within_perpen_error_range); +} + +void main() +{ + ivec2 render_size = ivec2(textureSize(tile_max_sampler, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + + vec2 uvn = (vec2(uvi) + vec2(0.5)) / render_size; + + vec2 step_size = vec2(round(pow(2 + params.step_exponent_modifier, params.last_iteration_index - params.iteration_index))); + + vec2 uv_step = vec2(round(step_size)) / render_size; + + vec4 best_sample_fitness = vec4(10, 10, 0, 0); + + vec2 chosen_uv = uvn; + + bool set_a = !bool(step(0.5, float(params.iteration_index % 2))); + + vec2 step_offset; + + vec2 check_uv; + + vec4 uv_sample; + + vec4 current_sample_fitness; + + for(int i = 0; i < kernel_size; i++) + { + step_offset = check_step_kernel[i] * uv_step; + check_uv = uvn + step_offset; + + if(any(notEqual(check_uv, clamp(check_uv, vec2(0.0), vec2(1.0))))) + { + continue; + } + + check_uv = get_value(!set_a, check_uv).xy; + + step_offset = check_uv - uvn; + + uv_sample = textureLod(tile_max_sampler, check_uv, 0.0); + + sample_fitness(step_offset, uv_sample, render_size, current_sample_fitness); + + float sample_better = 1. - step(current_sample_fitness.z * current_sample_fitness.w, best_sample_fitness.z * best_sample_fitness.w); + best_sample_fitness = mix(best_sample_fitness, current_sample_fitness, sample_better); + chosen_uv = mix(chosen_uv, check_uv, sample_better); + } + + set_value(set_a, uvi, vec4(chosen_uv, 0, 0)); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_simple.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_simple.glsl.import new file mode 100644 index 0000000..632a2c5 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_simple.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://c4dywnp7k8rph" +path="res://.godot/imported/jfp_simple.glsl-96987ba8c42947c7e648d28f42a73f7a.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_simple.glsl" +dest_files=["res://.godot/imported/jfp_simple.glsl-96987ba8c42947c7e648d28f42a73f7a.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_blur.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_blur.glsl new file mode 100644 index 0000000..9b3c001 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_blur.glsl @@ -0,0 +1,192 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 +#define DBL_MAX 1.7976931348623158e+308 +#define DBL_MIN 2.2250738585072014e-308 + +layout(set = 0, binding = 0) uniform sampler2D color_sampler; +layout(set = 0, binding = 1) uniform sampler2D depth_sampler; +layout(set = 0, binding = 2) uniform sampler2D vector_sampler; +layout(set = 0, binding = 3) uniform sampler2D velocity_map; +layout(rgba16f, set = 0, binding = 4) uniform writeonly image2D output_image; + +layout(push_constant, std430) uniform Params +{ + float motion_blur_samples; + float motion_blur_intensity; + float motion_blur_center_fade; + float frame; + float last_iteration_index; + float sample_step_multiplier; + float step_exponent_modifier; + float max_dilation_radius; + int nan0; + int nan1; + int nan2; + int nan3; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +// near plane distance +float npd = 0.05; + +// SOFT_Z_EXTENT +float sze = 0.1; + +// Helper functions +// -------------------------------------------- +// from https://www.shadertoy.com/view/ftKfzc +float interleaved_gradient_noise(vec2 uv, int FrameId){ + uv += float(FrameId) * (vec2(47, 17) * 0.695); + + vec3 magic = vec3( 0.06711056, 0.00583715, 52.9829189 ); + + return fract(magic.z * fract(dot(uv, magic.xy))); +} +float get_motion_difference(vec2 V, vec2 V2, float power) +{ + vec2 VO = V - V2; + float difference = dot(VO, V) / max(FLT_MIN, dot(V, V)); + return pow(clamp(difference, 0, 1), power); +} +// McGuire's function https://docs.google.com/document/d/1IIlAKTj-O01hcXEdGxTErQbCHO9iBmRx6oFUy_Jm0fI/edit +float soft_depth_compare(float depth_X, float depth_Y) +{ + return clamp(1 - (depth_X - depth_Y) / sze, 0, 1); +} +// ------------------------------------------------------- + +void main() +{ + ivec2 render_size = ivec2(textureSize(color_sampler, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + + // must be on pixel center for whole values (tested) + vec2 uvn = vec2(uvi + vec2(0.5)) / render_size; + + vec4 base_color = textureLod(color_sampler, uvn, 0.0); + // get dominant velocity data + vec4 velocity_map_sample = textureLod(velocity_map, uvn, 0.0); + + vec3 dominant_velocity = -textureLod(vector_sampler, velocity_map_sample.xy, 0.0).xyz; + + vec3 naive_velocity = -textureLod(vector_sampler, uvn, 0.0).xyz; + // if velocity is 0 and we dont show debug, return right away. + if ((dot(dominant_velocity, dominant_velocity) == 0 || params.motion_blur_intensity == 0)) + { + imageStore(output_image, uvi, base_color); + return; + } + // offset along velocity to blend between sample steps + float noise_offset = interleaved_gradient_noise(uvi, int(params.frame)) - 1; + // scale of step + float velocity_step_coef = min(params.motion_blur_intensity, params.max_dilation_radius / max(render_size.x, render_size.y) / (length(dominant_velocity) * params.motion_blur_intensity)) / max(1.0, params.motion_blur_samples - 1.0); + + vec3 step_sample = dominant_velocity * velocity_step_coef; + + vec3 naive_step_sample = naive_velocity * velocity_step_coef; + + vec4 velocity_map_step_sample = vec4(0); + + //float d = 1.0 - min(1.0, 2.0 * distance(uvn, vec2(0.5))); + //sample_step *= 1.0 - d * params.fade_padding.x; + + float total_weight = 1; + + vec3 dominant_offset = step_sample * noise_offset; + + vec3 naive_offset = naive_step_sample * noise_offset; + + vec3 dominant_back_offset = -step_sample * (1. - noise_offset); + + vec4 col = base_color * total_weight; + + float naive_depth = textureLod(depth_sampler, uvn, 0.0).x; + + float backstepping_coef = clamp(length(dominant_velocity) / 0.05, 0, 1); + + vec2 dominant_uvo; + + vec2 naive_uvo; + + vec3 current_dominant_offset; + + float current_naive_depth; + + float foreground; + + vec3 current_dominant_velocity; + + float motion_difference; + + float sample_weight; + + float dominant_naive_mix; + + vec2 sample_uv; + + for (int i = 1; i < params.motion_blur_samples; i++) + { + dominant_offset += step_sample; + + naive_offset += naive_step_sample; + + dominant_uvo = uvn + dominant_offset.xy; + + naive_uvo = uvn + naive_offset.xy; + + current_dominant_offset = dominant_offset; + + current_naive_depth = textureLod(depth_sampler, dominant_uvo, 0.0).x; + // is current depth closer than origin of dilation (stepped into a foreground object) + foreground = step(naive_depth + current_dominant_offset.z, current_naive_depth - 0.0001); + + velocity_map_step_sample = textureLod(velocity_map, dominant_uvo, 0.0); + + current_dominant_velocity = -textureLod(vector_sampler, velocity_map_step_sample.xy, 0.0).xyz; + + motion_difference = get_motion_difference(dominant_velocity.xy, current_dominant_velocity.xy, 0.1); + + sample_weight = 1; + + if (any(notEqual(dominant_uvo, clamp(dominant_uvo, vec2(0.0), vec2(1.0)))) || foreground * motion_difference > 0.5) + { + dominant_uvo = uvn + dominant_back_offset.xy; + current_dominant_offset = dominant_back_offset; + dominant_back_offset -= step_sample; + sample_weight = 0.5;//backstepping_coef; + } + + velocity_map_step_sample = textureLod(velocity_map, dominant_uvo, 0.0); + + current_dominant_velocity = -textureLod(vector_sampler, velocity_map_step_sample.xy, 0.0).xyz; + // is current velocity different than dilated velocity + + current_naive_depth = textureLod(depth_sampler, dominant_uvo, 0.0).x; + // is current depth closer than origin of dilation (stepped into a foreground object) + foreground = step(naive_depth + current_dominant_offset.z, current_naive_depth - 0.002); + + motion_difference = get_motion_difference(dominant_velocity.xy, current_dominant_velocity.xy, 0.1); + // if we are sampling a foreground object and its velocity is different, discard this sample (prevent ghosting) + sample_weight *= 1 - (foreground * motion_difference); + + dominant_naive_mix = 1. - step(0.9, motion_difference); + + sample_uv = mix(naive_uvo, dominant_uvo, dominant_naive_mix); + + total_weight += sample_weight; + + col += textureLod(color_sampler, sample_uv, 0.0) * sample_weight; + } + + col /= total_weight; + + imageStore(output_image, uvi, col); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_blur.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_blur.glsl.import new file mode 100644 index 0000000..97b9fad --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_blur.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://c57nhlyxb4m1t" +path="res://.godot/imported/jump_flood_blur.glsl-11f088c8cddfb4c62f32dfa84c694ded.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_blur.glsl" +dest_files=["res://.godot/imported/jump_flood_blur.glsl-11f088c8cddfb4c62f32dfa84c694ded.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_cache.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_cache.glsl new file mode 100644 index 0000000..cdafc46 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_cache.glsl @@ -0,0 +1,46 @@ +#[compute] +#version 450 + +layout(set = 0, binding = 0) uniform sampler2D velocity_sampler; +layout(set = 0, binding = 1) uniform sampler2D color_sampler; +layout(rgba16f, set = 0, binding = 2) uniform image2D past_velocity; +layout(rgba16f, set = 0, binding = 3) uniform image2D past_color; + +// Guertin's functions https://research.nvidia.com/sites/default/files/pubs/2013-11_A-Fast-and/Guertin2013MotionBlur-small.pdf +// ---------------------------------------------------------- +float z_compare(float a, float b, float sze) +{ + return clamp(1. - sze * (a - b), 0, 1); +} +// ---------------------------------------------------------- + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +void main() +{ + ivec2 render_size = ivec2(textureSize(velocity_sampler, 0)); + ivec2 uv = ivec2(gl_GlobalInvocationID.xy); + if ((uv.x >= render_size.x) || (uv.y >= render_size.y)) + { + return; + } + + vec2 x = (vec2(uv) + 0.5) / render_size; + + vec4 past_vx = textureLod(velocity_sampler, x, 0.0); + + vec4 past_vx_vx = textureLod(velocity_sampler, x + past_vx.xy, 0.0); + + vec4 past_col_vx = textureLod(color_sampler, x + past_vx.xy, 0.0); + + vec4 past_col_x = textureLod(color_sampler, x, 0.0); + + float alpha = 1 - z_compare(-past_vx.w, -past_vx_vx.w, 20000); + + vec4 final_past_col = mix(past_col_vx, past_col_x, alpha); + + vec4 final_past_vx = mix(vec4(past_vx_vx.xyz, past_vx.w), past_vx, alpha); + + imageStore(past_color, uv, final_past_col); + imageStore(past_velocity, uv, final_past_vx); +} diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_cache.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_cache.glsl.import new file mode 100644 index 0000000..d72bc96 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_cache.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://quuyr2q5w5kx" +path="res://.godot/imported/jump_flood_cache.glsl-f4eae7ab471d126e0587a3e727d847f6.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_cache.glsl" +dest_files=["res://.godot/imported/jump_flood_cache.glsl-f4eae7ab471d126e0587a3e727d847f6.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_experimental_blur.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_experimental_blur.glsl new file mode 100644 index 0000000..46df805 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_experimental_blur.glsl @@ -0,0 +1,316 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 +#define M_PI 3.1415926535897932384626433832795 + +layout(set = 0, binding = 0) uniform sampler2D color_sampler; +layout(set = 0, binding = 2) uniform sampler2D velocity_sampler; +layout(set = 0, binding = 3) uniform sampler2D velocity_map; +layout(rgba16f, set = 0, binding = 4) uniform writeonly image2D output_image; +layout(set = 0, binding = 5) uniform sampler2D tile_max; +layout(set = 0, binding = 6) uniform sampler2D past_color_sampler; +layout(set = 0, binding = 7) uniform sampler2D past_velocity_sampler; + +layout(push_constant, std430) uniform Params +{ + float motion_blur_samples; + float motion_blur_intensity; + float motion_blur_center_fade; + float frame; + float last_iteration_index; + float sample_step_multiplier; + float step_exponent_modifier; + float max_dilation_radius; + int nan0; + int nan1; + int nan2; + int nan3; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +// McGuire's functions https://docs.google.com/document/d/1IIlAKTj-O01hcXEdGxTErQbCHO9iBmRx6oFUy_Jm0fI/edit +// ---------------------------------------------------------- +float soft_depth_compare(float depth_X, float depth_Y, float sze) +{ + return clamp(1 - (depth_X - depth_Y) / sze, 0, 1); +} + +float cone(float T, float v) +{ + return clamp(1 - T / v, 0, 1); +} + +float cylinder(float T, float v) +{ + return 1.0 - smoothstep(0.95 * v, 1.05 * v, T); +} +// ---------------------------------------------------------- + +// Guertin's functions https://research.nvidia.com/sites/default/files/pubs/2013-11_A-Fast-and/Guertin2013MotionBlur-small.pdf +// ---------------------------------------------------------- +float z_compare(float a, float b, float sze) +{ + return clamp(1. - sze * (a - b), 0, 1); +} +// ---------------------------------------------------------- + +// from https://www.shadertoy.com/view/ftKfzc +// ---------------------------------------------------------- +float interleaved_gradient_noise(vec2 uv){ + uv += float(params.frame) * (vec2(47, 17) * 0.695); + + vec3 magic = vec3( 0.06711056, 0.00583715, 52.9829189 ); + + return fract(magic.z * fract(dot(uv, magic.xy))); +} +// ---------------------------------------------------------- + +// from https://github.com/bradparks/KinoMotion__unity_motion_blur/tree/master +// ---------------------------------------------------------- +vec2 safenorm(vec2 v) +{ + float l = max(length(v), 1e-6); + return v / l * int(l >= 0.5); +} + +vec2 jitter_tile(vec2 uvi) +{ + float rx, ry; + float angle = interleaved_gradient_noise(uvi + vec2(2, 0)) * M_PI * 2; + rx = cos(angle); + ry = sin(angle); + return vec2(rx, ry) / textureSize(tile_max, 0) / 4; +} +// ---------------------------------------------------------- + +void main() +{ + ivec2 render_size = ivec2(textureSize(color_sampler, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + + vec2 x = (vec2(uvi) + vec2(0.5)) / vec2(render_size); + + vec2 velocity_map_sample = textureLod(velocity_map, x + jitter_tile(uvi), 0.0).xy; + + vec3 vnz = textureLod(tile_max, velocity_map_sample, 0.0).xyz * vec3(render_size, 1); + + float vn_length = max(0.5, length(vnz.xy)); + + float multiplier = clamp(vn_length, 0, min(params.max_dilation_radius, vn_length * params.motion_blur_intensity)) / max(FLT_MIN, vn_length); + + vnz.xyz *= multiplier; + + vn_length *= multiplier; + + vec2 vn = vnz.xy; + + vec4 col_x = textureLod(color_sampler, x, 0.0); + + vec4 vxz = textureLod(velocity_sampler, x, 0.0) * vec4(render_size, 1, 1); + + float vx_length = max(0.5, length(vxz.xy)); + + //multiplier = clamp(vx_length, 0, min(params.max_dilation_radius, vn_length * params.motion_blur_intensity)) / max(FLT_MIN, vx_length); + + vxz.xyz *= multiplier; + + vx_length *= multiplier; + + vec2 vx = vxz.xy; + + vec2 wx = safenorm(vx); + + if(vn_length <= 0.5) + { + imageStore(output_image, uvi, col_x); + +#ifdef DEBUG + imageStore(debug_1_image, uvi, col_x); + imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1))); + imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1))); + imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1))); + imageStore(debug_5_image, uvi, col_x); +#endif + + return; + } + + vec3 wvnz = normalize(vnz.xyz); + + float velocity_match = pow(clamp(dot(vx, vn) / dot(vn, vn), 0, 1), 1 / (10000 * pow(abs(vnz.z), 2))); + + vn = mix(vn, vx, velocity_match); + + vnz = mix(vnz, vxz.xyz, velocity_match); + + vec2 wn = safenorm(vn); + + float zx = vxz.w; + + float j = interleaved_gradient_noise(uvi) - 0.5; + + vec4 past_vxz = textureLod(past_velocity_sampler, x, 0.0) * vec4(render_size * multiplier, 1 * multiplier, 1); + + vec2 past_vx = past_vxz.xy; + + vec4 past_col_x = textureLod(past_color_sampler, x, 0.0); + + float t; + float back_t; + float T; + vec2 y; + float y_inside; + vec4 nai_vy; + vec2 nai_y; + vec2 nai_back_y; + float nai_zy; + float nai_b; + float nai_ay; + float nai_y_inside; + vec4 vy; + float vy_length; + float zy; + float f; + float wa; + float ay_trail; + float past_t; + vec2 past_y; + vec2 past_back_y; + float past_ay; + float alpha; + vec4 past_vy; + float past_zy; + float past_b; + float past_y_inside; + float nai_T; + float nai_vy_length; + float nai_wa; + + float weight = 1e-5; + + vec4 sum = col_x * weight; + + float nai_weight = 1e-5; + + float nai_sub_weight = 1e-5; + + vec4 nai_sum = col_x * nai_sub_weight; + + float past_weight = 1e-5; + + float past_sub_weight = 1e-5; + + vec4 past_sum = past_col_x * past_sub_weight; + + float final_sample_count = params.motion_blur_samples + 1e-5; + + for(int i = 0; i < params.motion_blur_samples; i++) + { + t = mix(0., -1., (i + j + 1.0) / (params.motion_blur_samples + 1.0)); + + back_t = mix(1, 0, (i + j + 1.0) / (params.motion_blur_samples + 1.0)); + + T = abs(t * vn_length); + + y = x + (vn / render_size) * t; + + nai_T = abs(t * vx_length); + + nai_y = x + (vx / render_size) * t; + + nai_back_y = x + (vx / render_size) * back_t; + + nai_vy = textureLod(velocity_sampler, nai_y, 0.0) * vec4(render_size * multiplier, 1 * multiplier, 1); + + nai_vy_length = max(0.5, length(nai_vy.xy)); + + nai_zy = nai_vy.w - vxz.z * t; + + nai_b = z_compare(-zx, -nai_zy, 20000); + + float nai_f = z_compare(-nai_zy, -zx, 20000); + + nai_wa = abs(max(0, dot(nai_vy.xy / vy_length, wx))); + + nai_ay = max(nai_b, 0);//step(nai_T, nai_vy_length * nai_wa)); + + nai_weight += 1; + + nai_sub_weight += 1; + + nai_y_inside = step(0, nai_y.x) * step(nai_y.x, 1) * step(0, nai_y.y) * step(nai_y.y, 1); + + nai_sum += mix(textureLod(color_sampler, nai_back_y, 0.0), textureLod(color_sampler, nai_y, 0.0), nai_ay * nai_y_inside); + + past_y = x + (past_vx / render_size) * t; + + past_back_y = x + (past_vx / render_size) * back_t; + + alpha = z_compare(-past_vxz.w, -vxz.w, 20000); + + past_vy = textureLod(past_velocity_sampler, past_y, 0.0) * vec4(render_size * multiplier, 1 * multiplier, 1); + + past_zy = past_vy.w - past_vxz.z * t; + + past_b = z_compare(-past_vxz.w, -past_zy, 20000); + + past_ay = (1 - step(nai_T, nai_vy_length * nai_wa)) * (1 - alpha); + + past_weight += past_ay; + + past_sub_weight += 1; + + past_y_inside = step(0, past_y.x) * step(past_y.x, 1) * step(0, past_y.y) * step(past_y.y, 1); + + past_sum += mix(textureLod(past_color_sampler, past_back_y, 0.0), textureLod(past_color_sampler, past_y, 0.0), past_b * past_y_inside); + + vy = textureLod(velocity_sampler, y, 0.0) * vec4(render_size * multiplier, 1 * multiplier, 1); + + vy_length = max(0.5, length(vy.xy)); + + zy = vy.w - vnz.z * t; + + f = z_compare(-zy, -zx, 20000); + + wa = abs(max(0, dot(vy.xy / vy_length, wn))); + + ay_trail = f * step(T, vy_length * wa); + + y_inside = step(0, y.x) * step(y.x, 1) * step(0, y.y) * step(y.y, 1); + + weight += ay_trail * y_inside; + + sum += textureLod(color_sampler, y, 0.0) * ay_trail * y_inside; + } + + sum /= weight; + + weight /= final_sample_count; + + nai_sum /= nai_sub_weight; + + nai_weight /= final_sample_count; + + past_sum /= past_sub_weight; + + past_weight /= final_sample_count; + + sum = mix(mix(nai_sum, past_sum, past_weight), sum, weight); + + imageStore(output_image, uvi, sum); + +#ifdef DEBUG + imageStore(debug_1_image, uvi, sum); + imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1))); + imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1))); + imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1))); + imageStore(debug_5_image, uvi, col_x); +#endif +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_experimental_blur.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_experimental_blur.glsl.import new file mode 100644 index 0000000..8f395d3 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_experimental_blur.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://bud4a7eh5sqr8" +path="res://.godot/imported/jump_flood_experimental_blur.glsl-27880bed814a937f2189c48828ca161e.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_experimental_blur.glsl" +dest_files=["res://.godot/imported/jump_flood_experimental_blur.glsl-27880bed814a937f2189c48828ca161e.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_overlay.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_overlay.glsl new file mode 100644 index 0000000..b2af387 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_overlay.glsl @@ -0,0 +1,17 @@ +#[compute] +#version 450 + +layout(set = 0, binding = 0) uniform sampler2D blur_sampler; +layout(rgba16f, set = 0, binding = 1) uniform image2D color_image; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; +void main() +{ + ivec2 render_size = ivec2(textureSize(blur_sampler, 0)); + ivec2 uv = ivec2(gl_GlobalInvocationID.xy); + if ((uv.x >= render_size.x) || (uv.y >= render_size.y)) + { + return; + } + imageStore(color_image, uv, textureLod(blur_sampler, (vec2(uv) + 0.5) / render_size, 0.0)); +} diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_overlay.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_overlay.glsl.import new file mode 100644 index 0000000..be6ca36 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_overlay.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://dig08kpnfakuf" +path="res://.godot/imported/jump_flood_overlay.glsl-fc28b3ae9a688e5da04536a5cdb7b76e.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_overlay.glsl" +dest_files=["res://.godot/imported/jump_flood_overlay.glsl-fc28b3ae9a688e5da04536a5cdb7b76e.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_realistic_blur.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_realistic_blur.glsl new file mode 100644 index 0000000..b9aba25 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_realistic_blur.glsl @@ -0,0 +1,292 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 +#define M_PI 3.1415926535897932384626433832795 + +layout(set = 0, binding = 0) uniform sampler2D color_sampler; +layout(set = 0, binding = 1) uniform sampler2D depth_sampler; +layout(set = 0, binding = 2) uniform sampler2D velocity_sampler; +layout(set = 0, binding = 3) uniform sampler2D velocity_map; +layout(rgba16f, set = 0, binding = 4) uniform writeonly image2D output_image; +layout(set = 0, binding = 5) uniform sampler2D tile_max; + +layout(push_constant, std430) uniform Params +{ + float motion_blur_samples; + float motion_blur_intensity; + float motion_blur_center_fade; + float frame; + float last_iteration_index; + float sample_step_multiplier; + float step_exponent_modifier; + float max_dilation_radius; + int nan0; + int nan1; + int nan2; + int nan3; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +// McGuire's functions https://docs.google.com/document/d/1IIlAKTj-O01hcXEdGxTErQbCHO9iBmRx6oFUy_Jm0fI/edit +// ---------------------------------------------------------- +float soft_depth_compare(float depth_X, float depth_Y, float sze) +{ + return clamp(1 - (depth_X - depth_Y) / sze, 0, 1); +} + +float cone(float T, float v) +{ + return clamp(1 - T / v, 0, 1); +} + +float cylinder(float T, float v) +{ + return 1.0 - smoothstep(0.95 * v, 1.05 * v, T); +} +// ---------------------------------------------------------- + +// Guertin's functions https://research.nvidia.com/sites/default/files/pubs/2013-11_A-Fast-and/Guertin2013MotionBlur-small.pdf +// ---------------------------------------------------------- +float z_compare(float a, float b, float sze) +{ + return clamp(1. - sze * (a - b), 0, 1); +} +// ---------------------------------------------------------- + +// from https://www.shadertoy.com/view/ftKfzc +// ---------------------------------------------------------- +float interleaved_gradient_noise(vec2 uv){ + uv += float(params.frame) * (vec2(47, 17) * 0.695); + + vec3 magic = vec3( 0.06711056, 0.00583715, 52.9829189 ); + + return fract(magic.z * fract(dot(uv, magic.xy))); +} +// ---------------------------------------------------------- + +// from https://github.com/bradparks/KinoMotion__unity_motion_blur/tree/master +// ---------------------------------------------------------- +vec2 safenorm(vec2 v) +{ + float l = max(length(v), 1e-6); + return v / l * int(l >= 0.5); +} + +vec2 jitter_tile(vec2 uvi) +{ + float rx, ry; + float angle = interleaved_gradient_noise(uvi + vec2(2, 0)) * M_PI * 2; + rx = cos(angle); + ry = sin(angle); + return vec2(rx, ry) / textureSize(tile_max, 0) / 4; +} +// ---------------------------------------------------------- + +void main() +{ + ivec2 render_size = ivec2(textureSize(color_sampler, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + + vec2 x = (vec2(uvi) + vec2(0.5)) / vec2(render_size); + + vec2 velocity_map_sample = textureLod(velocity_map, x + jitter_tile(uvi), 0.0).xy; + + vec3 vnz = textureLod(tile_max, velocity_map_sample, 0.0).xyz * vec3(render_size, 1); + + float vn_length = max(0.5, length(vnz.xy)); + + float multiplier = clamp(vn_length, 0, min(params.max_dilation_radius, vn_length * params.motion_blur_intensity)) / max(FLT_MIN, vn_length); + + vnz.xyz *= multiplier; + + vn_length *= multiplier; + + vec2 vn = vnz.xy; + + vec4 col_x = textureLod(color_sampler, x, 0.0); + + vec2 wn = safenorm(vn); + + vec4 vxz = textureLod(velocity_sampler, x, 0.0) * vec4(render_size, 1, 1); + + float vx_length = max(0.5, length(vxz.xy)); + + multiplier = clamp(vx_length, 0, min(params.max_dilation_radius, vn_length * params.motion_blur_intensity)) / max(FLT_MIN, vx_length); + + vxz.xyz *= multiplier; + + vx_length *= multiplier; + + vec2 vx = vxz.xy; + + if(vn_length <= 0.5) + { + imageStore(output_image, uvi, col_x); + +#ifdef DEBUG + imageStore(debug_1_image, uvi, col_x); + imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1))); + imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1))); + imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1))); + imageStore(debug_5_image, uvi, col_x); +#endif + + return; + } + + float velocity_match = pow(clamp(dot(vx, vn) / dot(vn, vn), 0, 1), 0.5); + + vn = mix(vn, vx, velocity_match); + + vnz = mix(vnz, vxz.xyz, velocity_match); + + float zx = vxz.w; + + vec2 wx = safenorm(vx); + + float weight = 0; + + vec4 sum = col_x * weight; + + float total_back_weight = 1e-10; + + vec4 back_sum = col_x * total_back_weight; + + float j = interleaved_gradient_noise(uvi) - 0.5; + + int back_amount = 0; + + int nai_back_i = 1; + + for(int i = 0; i < params.motion_blur_samples; i++) + { + float nai_t = mix(0., -1., (i + j + 1.0) / (params.motion_blur_samples + 1.0)); + + float nai_T = abs(nai_t * vx_length); + + vec2 nai_y = x + (vx / render_size) * nai_t; + + float nai_zy = textureLod(depth_sampler, nai_y, 0.0).x - vxz.z * nai_t; + + float nai_b = z_compare(-zx, -nai_zy, 20000); + + float nai_f = z_compare(-nai_zy, -zx, 20000); + + vec4 nai_vy = textureLod(velocity_sampler, nai_y, 0.0) * vec4(render_size, 1, 1); + + float nai_vy_length = max(0.5, length(nai_vy.xy)); + + float nai_ay = nai_b; + + float nai_wb = abs(max(0, dot(nai_vy.xy / nai_vy_length, wx))); + + float nai_ay_f = nai_f * step(nai_T, nai_vy_length * nai_wb); + + if(nai_y.x < 0 || nai_y.x > 1 || nai_y.y < 0 || nai_y.y > 1 || nai_ay + nai_ay_f <= 1e-5) + { + nai_t = mix(0., 1., (nai_back_i + j + 1.0) / (params.motion_blur_samples + 1.0)); + + nai_T = abs(nai_t * vx_length); + + nai_y = x + (vx / render_size) * nai_t; + + nai_zy = textureLod(depth_sampler, nai_y, 0.0).x - vxz.z * nai_t; + + nai_b = z_compare(-zx, -nai_zy, 20000); + + nai_f = z_compare(-nai_zy, -zx, 20000); + + nai_vy = textureLod(velocity_sampler, nai_y, 0.0) * vec4(render_size, 1, 1); + + nai_vy_length = max(0.5, length(nai_vy.xy)); + + nai_ay = nai_b; + + nai_wb = abs(max(0, dot(nai_vy.xy / nai_vy_length, wx))); + + nai_ay_f = nai_f * step(nai_T, nai_vy_length * nai_wb); + + nai_back_i++; + } + + vec4 nai_col_y = textureLod(color_sampler, nai_y, 0.0); + + total_back_weight += nai_ay; + + back_sum += nai_col_y * nai_ay; + + float t = mix(0., -1., (i - back_amount + j + 1.0) / (params.motion_blur_samples + 1.0)); + + float T = abs(t * vn_length); + + vec2 y = x + (vn / render_size) * t; + + if(y.x < 0 || y.x > 1 || y.y < 0 || y.y > 1) + { + continue; +// vn = -vn; +// vnz = -vnz; +// wn = -wn; +// back_amount = i; + } + + vec4 vy = textureLod(velocity_sampler, y, 0.0) * vec4(render_size, 1, 1); + + float vy_length = max(0.5, length(vy.xy)); + + float zy = vy.w - vnz.z * t; + + float f = z_compare(-zy, -zx, 20000); + + float wa = abs(max(0, dot(vy.xy / vy_length, wn))); + + float ay_trail = f * step(T, vy_length * wa); + + vec4 col_y = textureLod(color_sampler, y, 0.0); + + vec2 back_y = x + (vn / render_size) * -t; + + vec4 back_vy = textureLod(velocity_sampler, back_y, 0.0) * vec4(render_size, 1, 1); + + float back_vy_length = max(0.5, length(back_vy.xy)); + + float back_zy = back_vy.w - vnz.z * -t; + + float back_wa = abs(max(0, dot(back_vy.xy / back_vy_length, -wn))); + + float back_f = z_compare(-back_zy, -zx, 20000); + + float back_ay_trail = back_f * step(T, back_vy_length * back_wa); + + vec4 back_col_y = textureLod(color_sampler, back_y, 0.0); + + weight += back_ay_trail + (back_ay_trail > 0 ? 0 : ay_trail); + + sum += back_col_y * back_ay_trail + (back_ay_trail > 0 ? vec4(0) : col_y * ay_trail); + + + } + + back_sum *= (params.motion_blur_samples - weight) / total_back_weight; + + sum /= params.motion_blur_samples; + + back_sum /= params.motion_blur_samples; + + imageStore(output_image, uvi, sum + back_sum); + +#ifdef DEBUG + imageStore(debug_1_image, uvi, sum + back_sum); + imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1))); + imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1))); + imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1))); + imageStore(debug_5_image, uvi, col_x); +#endif +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_realistic_blur.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_realistic_blur.glsl.import new file mode 100644 index 0000000..4859444 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_realistic_blur.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://b1fr5qhhrbpst" +path="res://.godot/imported/jump_flood_realistic_blur.glsl-c7d6d91d942d788c7b2fc3bc2c1c8e38.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_realistic_blur.glsl" +dest_files=["res://.godot/imported/jump_flood_realistic_blur.glsl-c7d6d91d942d788c7b2fc3bc2c1c8e38.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_blur.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_blur.glsl new file mode 100644 index 0000000..7d3fbb0 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_blur.glsl @@ -0,0 +1,245 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 +#define M_PI 3.1415926535897932384626433832795 + +layout(set = 0, binding = 0) uniform sampler2D color_sampler; +layout(set = 0, binding = 2) uniform sampler2D velocity_sampler; +layout(set = 0, binding = 3) uniform sampler2D velocity_map; +layout(rgba16f, set = 0, binding = 4) uniform writeonly image2D output_image; +layout(set = 0, binding = 5) uniform sampler2D tile_max; + +layout(push_constant, std430) uniform Params +{ + float motion_blur_samples; + float motion_blur_intensity; + float motion_blur_center_fade; + float frame; + float last_iteration_index; + float sample_step_multiplier; + float step_exponent_modifier; + float max_dilation_radius; + int nan0; + int nan1; + int nan2; + int nan3; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +// McGuire's functions https://docs.google.com/document/d/1IIlAKTj-O01hcXEdGxTErQbCHO9iBmRx6oFUy_Jm0fI/edit +// ---------------------------------------------------------- +float soft_depth_compare(float depth_X, float depth_Y, float sze) +{ + return clamp(1 - (depth_X - depth_Y) / sze, 0, 1); +} + +float cone(float T, float v) +{ + return clamp(1 - T / v, 0, 1); +} + +float cylinder(float T, float v) +{ + return 1.0 - smoothstep(0.95 * v, 1.05 * v, T); +} +// ---------------------------------------------------------- + +// Guertin's functions https://research.nvidia.com/sites/default/files/pubs/2013-11_A-Fast-and/Guertin2013MotionBlur-small.pdf +// ---------------------------------------------------------- +float z_compare(float a, float b, float sze) +{ + return clamp(1. - sze * (a - b), 0, 1); +} +// ---------------------------------------------------------- + +// from https://www.shadertoy.com/view/ftKfzc +// ---------------------------------------------------------- +float interleaved_gradient_noise(vec2 uv){ + uv += float(params.frame) * (vec2(47, 17) * 0.695); + + vec3 magic = vec3( 0.06711056, 0.00583715, 52.9829189 ); + + return fract(magic.z * fract(dot(uv, magic.xy))); +} +// ---------------------------------------------------------- + +// from https://github.com/bradparks/KinoMotion__unity_motion_blur/tree/master +// ---------------------------------------------------------- +vec2 safenorm(vec2 v) +{ + float l = max(length(v), 1e-6); + return v / l * int(l >= 0.5); +} + +vec2 jitter_tile(vec2 uvi) +{ + float rx, ry; + float angle = interleaved_gradient_noise(uvi + vec2(2, 0)) * M_PI * 2; + rx = cos(angle); + ry = sin(angle); + return vec2(rx, ry) / textureSize(tile_max, 0) / 4; +} +// ---------------------------------------------------------- + +void main() +{ + ivec2 render_size = ivec2(textureSize(color_sampler, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + + vec2 x = (vec2(uvi) + vec2(0.5)) / vec2(render_size); + + vec2 velocity_map_sample = textureLod(velocity_map, x + jitter_tile(uvi), 0.0).xy; + + vec3 vnz = textureLod(tile_max, velocity_map_sample, 0.0).xyz * vec3(render_size, 1); + + float vn_length = max(0.5, length(vnz.xy)); + + float multiplier = clamp(vn_length, 0, min(params.max_dilation_radius, vn_length * params.motion_blur_intensity)) / max(FLT_MIN, vn_length); + + vnz.xyz *= multiplier; + + vn_length *= multiplier; + + vec2 vn = vnz.xy; + + vec4 col_x = textureLod(color_sampler, x, 0.0); + + vec2 wn = safenorm(vn); + + vec4 vxz = textureLod(velocity_sampler, x, 0.0) * vec4(render_size, 1, 1); + + float vx_length = max(0.5, length(vxz.xy)); + + multiplier = clamp(vx_length, 0, min(params.max_dilation_radius, vn_length * params.motion_blur_intensity)) / max(FLT_MIN, vx_length); + + vxz.xyz *= multiplier; + + vx_length *= multiplier; + + vec2 vx = vxz.xy; + + if(vn_length <= 0.5) + { + imageStore(output_image, uvi, col_x); + +#ifdef DEBUG + imageStore(debug_1_image, uvi, col_x); + imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1))); + imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1))); + imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1))); + imageStore(debug_5_image, uvi, col_x); +#endif + + return; + } + + float velocity_match = pow(clamp(dot(vx, vn) / dot(vn, vn), 0, 1), 0.5); + + vn = mix(vn, vx, velocity_match); + + vnz = mix(vnz, vxz.xyz, velocity_match); + + float zx = vxz.w; + + vec2 wx = safenorm(vx); + + float weight = 0; + + vec4 sum = col_x * weight; + + float total_back_weight = 1e-10; + + vec4 back_sum = col_x * total_back_weight; + + float j = interleaved_gradient_noise(uvi) - 0.5; + + float nai_t; + float nai_T; + vec2 nai_y; + float t; + float T; + vec2 y; + vec4 nai_vy; + float nai_zy; + float nai_b; + float nai_ay; + vec4 nai_col_y; + vec4 vy; + float vy_length; + float zy; + float f; + float wa; + float ay_trail; + vec4 col_y; + + for(int i = 0; i < params.motion_blur_samples; i++) + { + t = mix(0., -1., (i + j + 1.0) / (params.motion_blur_samples + 1.0)); + + nai_y = x + (vx / render_size) * t; + + T = abs(t * vn_length); + + y = x + (vn / render_size) * t; + + if(nai_y.x < 0 || nai_y.x > 1 || nai_y.y < 0 || nai_y.y > 1 || y.x < 0 || y.x > 1 || y.y < 0 || y.y > 1) + { + continue; + } + + nai_vy = textureLod(velocity_sampler, nai_y, 0.0) * vec4(render_size, 1, 1); + + nai_zy = nai_vy.w - vxz.z * t; + + nai_b = z_compare(-zx, -nai_zy, 20000); + + nai_ay = nai_b; + + nai_col_y = textureLod(color_sampler, nai_y, 0.0); + + total_back_weight += nai_ay; + + back_sum += nai_col_y * nai_ay; + + vy = textureLod(velocity_sampler, y, 0.0) * vec4(render_size, 1, 1); + + vy_length = max(0.5, length(vy.xy)); + + zy = vy.w - vnz.z * t; + + f = z_compare(-zy, -zx, 20000); + + wa = abs(max(0, dot(vy.xy / vy_length, wn))); + + ay_trail = f * step(T, vy_length * wa); + + col_y = textureLod(color_sampler, y, 0.0); + + weight += ay_trail; + + sum += col_y * ay_trail; + } + + back_sum *= (params.motion_blur_samples - weight) / total_back_weight; + + sum /= params.motion_blur_samples; + + back_sum /= params.motion_blur_samples; + + imageStore(output_image, uvi, sum + back_sum); + +#ifdef DEBUG + imageStore(debug_1_image, uvi, sum + back_sum); + imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1))); + imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1))); + imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1))); + imageStore(debug_5_image, uvi, col_x); +#endif +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_blur.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_blur.glsl.import new file mode 100644 index 0000000..6ef1a5c --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_blur.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://bdm5t4l1y3ts7" +path="res://.godot/imported/jump_flood_simple_blur.glsl-cf442320d0e724df4bd151fec5d94fae.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_blur.glsl" +dest_files=["res://.godot/imported/jump_flood_simple_blur.glsl-cf442320d0e724df4bd151fec5d94fae.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_new_blur.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_new_blur.glsl new file mode 100644 index 0000000..148ea2d --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_new_blur.glsl @@ -0,0 +1,239 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 +#define M_PI 3.1415926535897932384626433832795 + +layout(set = 0, binding = 0) uniform sampler2D color_sampler; +layout(set = 0, binding = 2) uniform sampler2D velocity_sampler; +layout(set = 0, binding = 3) uniform sampler2D velocity_map; +layout(rgba16f, set = 0, binding = 4) uniform writeonly image2D output_image; +layout(set = 0, binding = 5) uniform sampler2D tile_max; + +layout(push_constant, std430) uniform Params +{ + float motion_blur_samples; + float motion_blur_intensity; + float motion_blur_center_fade; + float frame; + float last_iteration_index; + float sample_step_multiplier; + float step_exponent_modifier; + float max_dilation_radius; + int nan0; + int nan1; + int nan2; + int nan3; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +// McGuire's functions https://docs.google.com/document/d/1IIlAKTj-O01hcXEdGxTErQbCHO9iBmRx6oFUy_Jm0fI/edit +// ---------------------------------------------------------- +float soft_depth_compare(float depth_X, float depth_Y, float sze) +{ + return clamp(1 - (depth_X - depth_Y) / sze, 0, 1); +} + +float cone(float T, float v) +{ + return clamp(1 - T / v, 0, 1); +} + +float cylinder(float T, float v) +{ + return 1.0 - smoothstep(0.95 * v, 1.05 * v, T); +} +// ---------------------------------------------------------- + +// Guertin's functions https://research.nvidia.com/sites/default/files/pubs/2013-11_A-Fast-and/Guertin2013MotionBlur-small.pdf +// ---------------------------------------------------------- +float z_compare(float a, float b, float sze) +{ + return clamp(1. - sze * (a - b), 0, 1); +} +// ---------------------------------------------------------- + +// from https://www.shadertoy.com/view/ftKfzc +// ---------------------------------------------------------- +float interleaved_gradient_noise(vec2 uv){ + uv += float(params.frame) * (vec2(47, 17) * 0.695); + + vec3 magic = vec3( 0.06711056, 0.00583715, 52.9829189 ); + + return fract(magic.z * fract(dot(uv, magic.xy))); +} +// ---------------------------------------------------------- + +// from https://github.com/bradparks/KinoMotion__unity_motion_blur/tree/master +// ---------------------------------------------------------- +vec2 safenorm(vec2 v) +{ + float l = max(length(v), 1e-6); + return v / l * int(l >= 0.5); +} + +vec2 jitter_tile(vec2 uvi) +{ + float rx, ry; + float angle = interleaved_gradient_noise(uvi + vec2(2, 0)) * M_PI * 2; + rx = cos(angle); + ry = sin(angle); + return vec2(rx, ry) / textureSize(tile_max, 0) / 4; +} +// ---------------------------------------------------------- + +void main() +{ + ivec2 render_size = ivec2(textureSize(color_sampler, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + + vec2 x = (vec2(uvi) + vec2(0.5)) / vec2(render_size); + + vec2 velocity_map_sample = textureLod(velocity_map, x + jitter_tile(uvi), 0.0).xy; + + vec3 vnz = textureLod(tile_max, velocity_map_sample, 0.0).xyz * vec3(render_size, 1); + + float vn_length = max(0.5, length(vnz.xy)); + + float multiplier = clamp(vn_length, 0, min(params.max_dilation_radius, vn_length * params.motion_blur_intensity)) / max(FLT_MIN, vn_length); + + vnz.xyz *= multiplier; + + vn_length *= multiplier; + + vec2 vn = vnz.xy; + + vec4 col_x = textureLod(color_sampler, x, 0.0); + + vec2 wn = safenorm(vn); + + vec4 vxz = textureLod(velocity_sampler, x, 0.0) * vec4(render_size, 1, 1); + + float vx_length = max(0.5, length(vxz.xy)); + + multiplier = clamp(vx_length, 0, min(params.max_dilation_radius, vn_length * params.motion_blur_intensity)) / max(FLT_MIN, vx_length); + + vxz.xyz *= multiplier; + + vx_length *= multiplier; + + vec2 vx = vxz.xy; + + if(vn_length <= 0.5) + { + imageStore(output_image, uvi, col_x); + +#ifdef DEBUG + imageStore(debug_1_image, uvi, col_x); + imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1))); + imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1))); + imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1))); + imageStore(debug_5_image, uvi, col_x); +#endif + + return; + } + + float velocity_match = pow(clamp(dot(vx, vn) / dot(vn, vn), 0, 1), 1 / (1000 * abs(vnz.z))); + + vn = mix(vn, vx, velocity_match); + + vnz = mix(vnz, vxz.xyz, velocity_match); + + float zx = vxz.w; + + float j = interleaved_gradient_noise(uvi) - 0.5; + + vec2 nai_y; + float t; + float T; + vec2 y; + vec4 nai_vy; + float nai_zy; + float nai_b; + float nai_ay; + vec4 vy; + float vy_length; + float zy; + float f; + float wa; + float ay_trail; + float y_inside; + + float weight = 1e-5; + + vec4 sum = col_x * weight; + + float nai_weight = 1e-5; + + vec4 nai_sum = col_x * weight; + + float final_sample_count = params.motion_blur_samples; + + for(int i = 0; i < params.motion_blur_samples; i++) + { + t = mix(0., -1., (i + j + 1.0) / (params.motion_blur_samples + 1.0)); + + nai_y = x + (vx / render_size) * t; + + T = abs(t * vn_length); + + y = x + (vn / render_size) * t; + + nai_vy = textureLod(velocity_sampler, nai_y, 0.0) * vec4(render_size, 1, 1); + + nai_zy = nai_vy.w - vxz.z * t; + + nai_b = z_compare(-zx, -nai_zy, 20000); + + nai_ay = nai_b; + + nai_weight += 1; + + nai_sum += mix(col_x, textureLod(color_sampler, nai_y, 0.0), nai_ay); + + vy = textureLod(velocity_sampler, y, 0.0) * vec4(render_size, 1, 1); + + vy_length = max(0.5, length(vy.xy)); + + zy = vy.w - vnz.z * t; + + f = z_compare(-zy, -zx, 20000); + + wa = abs(max(0, dot(vy.xy / vy_length, wn))); + + ay_trail = f * step(T, vy_length * wa); + + y_inside = step(0, y.x) * step(y.x, 1) * step(0, y.y) * step(y.y, 1); + + weight += ay_trail * y_inside; + + sum += textureLod(color_sampler, y, 0.0) * ay_trail * y_inside; + } + + sum /= weight; + + weight /= final_sample_count; + + nai_sum /= nai_weight; + + nai_weight /= final_sample_count; + + sum = mix(nai_sum, sum, weight); + + imageStore(output_image, uvi, sum); + +#ifdef DEBUG + imageStore(debug_1_image, uvi, sum); + imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1))); + imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1))); + imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1))); + imageStore(debug_5_image, uvi, col_x); +#endif +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_new_blur.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_new_blur.glsl.import new file mode 100644 index 0000000..976c977 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_new_blur.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://c1vndulne5a5r" +path="res://.godot/imported/jump_flood_simple_new_blur.glsl-eae32754cec4350c64665a4ed0291739.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_new_blur.glsl" +dest_files=["res://.godot/imported/jump_flood_simple_new_blur.glsl-eae32754cec4350c64665a4ed0291739.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/base_jump_flood_motion_blur.gd b/addons/SphynxMotionBlurToolkit/JumpFlood/base_jump_flood_motion_blur.gd new file mode 100644 index 0000000..a3af9d6 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/base_jump_flood_motion_blur.gd @@ -0,0 +1,26 @@ +extends "res://addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor_effect.gd" + +@export_group("Shader Parameters") +## the portion of speed that is allowed for side bleed of velocities +## during the jfa dilation passes and before backtracking. Getting this a higher value +## would make it so that meshes at movement blur more reliably, but also bleed +## further perpendicularly to their velocity, thus wash elemets behind them out. +@export var perpen_error_threshold : float = 0.5 + +## an initial step size that can increase the dilation radius proportionally, at the +## sacrifice of some quality in the final resolution of the dilation.[br][br] +## the formula for the maximum radius of the dilation (in pixels) is: pow(2 + step_exponent_modifier, JFA_pass_count) * sample_step_multiplier +@export var sample_step_multiplier : int = 16 + +## by default, the jump flood makes samples along distances that start +## at 2 to the power of the pass count you want to perform, which is also +## the dilation radius you desire. You can change it to values higher than +## 2 with this variable, and reach higher dilation radius at the sacrifice of +## some accuracy in the dilation. +## the formula for the maximum radius of the dilation (in pixels) is: pow(2 + step_exponent_modifier, JFA_pass_count) * sample_step_multiplier +@export var step_exponent_modifier : float = 1 + +## the number of passes performed by the jump flood algorithm based dilation, +## each pass added doubles the maximum radius of dilation available.[br][br] +## the formula for the maximum radius of the dilation (in pixels) is: pow(2 + step_exponent_modifier, JFA_pass_count) * sample_step_multiplier +@export var JFA_pass_count : int = 3 diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/experimental_jf_motion_blur.gd b/addons/SphynxMotionBlurToolkit/JumpFlood/experimental_jf_motion_blur.gd new file mode 100644 index 0000000..e1e2c5b --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/experimental_jf_motion_blur.gd @@ -0,0 +1,294 @@ +extends "res://addons/SphynxMotionBlurToolkit/JumpFlood/base_jump_flood_motion_blur.gd" +class_name ExperimentalJumpFloodMotionBlur + +@export_group("Shader Stages") +@export var tile_max_x_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_x_stage.tres"): + set(value): + unsubscribe_shader_stage(tile_max_x_stage) + tile_max_x_stage = value + subscirbe_shader_stage(value) + +@export var tile_max_y_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_y_stage.tres"): + set(value): + unsubscribe_shader_stage(tile_max_y_stage) + tile_max_y_stage = value + subscirbe_shader_stage(value) + +@export var construct_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jf_simple_stage.tres"): + set(value): + unsubscribe_shader_stage(construct_stage) + construct_stage = value + subscirbe_shader_stage(value) + +@export var neighbor_max_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_neighbor_max_stage.tres"): + set(value): + unsubscribe_shader_stage(neighbor_max_stage) + neighbor_max_stage = value + subscirbe_shader_stage(value) + +@export var blur_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/experimental_jump_flood_blur_stage.tres"): + set(value): + unsubscribe_shader_stage(blur_stage) + blur_stage = value + subscirbe_shader_stage(value) + +@export var cache_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_cache_stage.tres"): + set(value): + unsubscribe_shader_stage(cache_stage) + cache_stage = value + subscirbe_shader_stage(value) + +@export var overlay_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_overlay_stage.tres"): + set(value): + unsubscribe_shader_stage(overlay_stage) + overlay_stage = value + subscirbe_shader_stage(value) + +var tile_max_x : StringName = "tile_max_x" + +var tile_max : StringName = "tile_max" + +var neighbor_max : StringName = "neighbor_max" + +var output_color : StringName = "output_color" + +var past_color : StringName = "past_color_cache" + +var past_velocity : StringName = "past_velocity_cache" + +var buffer_a : StringName = "buffer_a" +var buffer_b : StringName = "buffer_b" + +var custom_velocity : StringName = "custom_velocity" + +var temp_intensity : float + +var previous_time : float = 0 + +func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSceneBuffersRD, render_scene_data : RenderSceneDataRD): + var time : float = float(Time.get_ticks_msec()) / 1000 + + var delta_time : float = time - previous_time + + previous_time = time + + temp_intensity = intensity + + if framerate_independent: + var capped_frame_time : float = 1 / target_constant_framerate + + if !uncapped_independence: + capped_frame_time = min(capped_frame_time, delta_time) + + temp_intensity = intensity * capped_frame_time / delta_time + + ensure_texture(custom_velocity, render_scene_buffers) + ensure_texture(tile_max_x, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1.)) + ensure_texture(tile_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier)) + ensure_texture(buffer_a, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier)) + ensure_texture(buffer_b, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier)) + ensure_texture(neighbor_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier)) + ensure_texture(output_color, render_scene_buffers) + ensure_texture(past_color, render_scene_buffers) + ensure_texture(past_velocity, render_scene_buffers) + + rd.draw_command_begin_label("Motion Blur", Color(1.0, 1.0, 1.0, 1.0)) + + var last_iteration_index : int = JFA_pass_count - 1; + + var max_dilation_radius : float = pow(2 + step_exponent_modifier, last_iteration_index) * sample_step_multiplier / intensity; + + var tile_max_x_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_tile_max_x_push_constants : PackedInt32Array = [ + sample_step_multiplier, + 0, + 0, + 0 + ] + var tile_max_x_push_constants_byte_array = tile_max_x_push_constants.to_byte_array() + tile_max_x_push_constants_byte_array.append_array(int_tile_max_x_push_constants.to_byte_array()) + + var tile_max_y_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_tile_max_y_push_constants : PackedInt32Array = [ + sample_step_multiplier, + 0, + 0, + 0 + ] + var tile_max_y_push_constants_byte_array = tile_max_y_push_constants.to_byte_array() + tile_max_y_push_constants_byte_array.append_array(int_tile_max_y_push_constants.to_byte_array()) + var neighbor_max_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_neighbor_max_push_constants : PackedInt32Array = [ + 0, + 0, + 0, + 0 + ] + var neighbor_max_push_constants_byte_array = neighbor_max_push_constants.to_byte_array() + neighbor_max_push_constants_byte_array.append_array(int_neighbor_max_push_constants.to_byte_array()) + + var push_constant: PackedFloat32Array = [ + samples, + temp_intensity, + center_fade, + Engine.get_frames_drawn() % 8, + last_iteration_index, + sample_step_multiplier, + step_exponent_modifier, + max_dilation_radius, + ] + var int_push_constant : PackedInt32Array = [ + 0, + 0, + 0, + 0 + ] + var byte_array = push_constant.to_byte_array() + byte_array.append_array(int_push_constant.to_byte_array()) + + var view_count = render_scene_buffers.get_view_count() + for view in range(view_count): + var color_image := render_scene_buffers.get_color_layer(view) + var depth_image := render_scene_buffers.get_depth_layer(view) + var output_color_image := render_scene_buffers.get_texture_slice(context, output_color, view, 0, 1, 1) + var past_color_image := render_scene_buffers.get_texture_slice(context, past_color, view, 0, 1, 1) + var past_velocity_image := render_scene_buffers.get_texture_slice(context, past_velocity, view, 0, 1, 1) + var buffer_a_image := render_scene_buffers.get_texture_slice(context, buffer_a, view, 0, 1, 1) + var buffer_b_image := render_scene_buffers.get_texture_slice(context, buffer_b, view, 0, 1, 1) + var custom_velocity_image := render_scene_buffers.get_texture_slice(context, custom_velocity, view, 0, 1, 1) + var tile_max_x_image := render_scene_buffers.get_texture_slice(context, tile_max_x, view, 0, 1, 1) + var tile_max_image := render_scene_buffers.get_texture_slice(context, tile_max, view, 0, 1, 1) + var neighbor_max_image := render_scene_buffers.get_texture_slice(context, neighbor_max, view, 0, 1, 1) + + var x_groups := floori((render_size.x / sample_step_multiplier - 1) / 16 + 1) + var y_groups := floori((render_size.y - 1) / 16 + 1) + + dispatch_stage(tile_max_x_stage, + [ + get_sampler_uniform(custom_velocity_image, 0, false), + get_image_uniform(tile_max_x_image, 1) + ], + tile_max_x_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "TileMaxX", + view) + + x_groups = floori((render_size.x / sample_step_multiplier - 1) / 16 + 1) + y_groups = floori((render_size.y / sample_step_multiplier - 1) / 16 + 1) + + dispatch_stage(tile_max_y_stage, + [ + get_sampler_uniform(tile_max_x_image, 0, false), + get_image_uniform(tile_max_image, 1) + ], + tile_max_y_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "TileMaxY", + view) + + for i in JFA_pass_count: + var jf_push_constants : PackedInt32Array = [ + i, + last_iteration_index, + 0, + 16 + ] + + var jf_float_push_constants_test : PackedFloat32Array = [ + perpen_error_threshold, + sample_step_multiplier, + temp_intensity, + 0, + 0, + 0, + 0, + step_exponent_modifier, + 0, + max_dilation_radius, + 0, + 0 + ] + var jf_byte_array = jf_push_constants.to_byte_array() + jf_byte_array.append_array(jf_float_push_constants_test.to_byte_array()) + + dispatch_stage(construct_stage, + [ + get_sampler_uniform(tile_max_image, 0, false), + get_image_uniform(buffer_a_image, 1), + get_image_uniform(buffer_b_image, 2), + get_sampler_uniform(buffer_a_image, 3, false), + get_sampler_uniform(buffer_b_image, 4, false), + ], + jf_byte_array, + Vector3i(x_groups, y_groups, 1), + "Construct Blur", + view) + + dispatch_stage(neighbor_max_stage, + [ + get_sampler_uniform(tile_max_image, 0, false), + get_sampler_uniform(buffer_b_image if last_iteration_index % 2 else buffer_a_image, 1, false), + get_image_uniform(neighbor_max_image, 2) + ], + neighbor_max_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "NeighborMax", + view) + + x_groups = floori((render_size.x - 1) / 16 + 1) + y_groups = floori((render_size.y - 1) / 16 + 1) + + dispatch_stage(blur_stage, + [ + get_sampler_uniform(color_image, 0, false), + get_sampler_uniform(depth_image, 1, false), + get_sampler_uniform(custom_velocity_image, 2, false), + get_sampler_uniform(neighbor_max_image, 3, false), + get_image_uniform(output_color_image, 4), + get_sampler_uniform(tile_max_image, 5, false), + get_sampler_uniform(past_color_image, 6, false), + get_sampler_uniform(past_velocity_image, 7, false) + ], + byte_array, + Vector3i(x_groups, y_groups, 1), + "Compute Blur", + view) + + dispatch_stage(cache_stage, + [ + get_sampler_uniform(custom_velocity_image, 0), + get_sampler_uniform(color_image, 1), + get_image_uniform(past_velocity_image, 2), + get_image_uniform(past_color_image, 3), + ], + [], + Vector3i(x_groups, y_groups, 1), + "Past Color Copy", + view) + + dispatch_stage(overlay_stage, + [ + get_sampler_uniform(output_color_image, 0), + get_image_uniform(color_image, 1), + ], + [], + Vector3i(x_groups, y_groups, 1), + "Overlay Result", + view) + + rd.draw_command_end_label() diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/experimental_jump_flood_blur_stage.tres b/addons/SphynxMotionBlurToolkit/JumpFlood/experimental_jump_flood_blur_stage.tres new file mode 100644 index 0000000..54650bc --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/experimental_jump_flood_blur_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://cvavvqqstnm1j"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_3q423"] +[ext_resource type="RDShaderFile" uid="uid://bud4a7eh5sqr8" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_experimental_blur.glsl" id="2_8flx6"] + +[resource] +script = ExtResource("1_3q423") +shader_file = ExtResource("2_8flx6") diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/jf_simple_stage.tres b/addons/SphynxMotionBlurToolkit/JumpFlood/jf_simple_stage.tres new file mode 100644 index 0000000..af7fc15 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/jf_simple_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://bj3exhmsfcx4w"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_v4e3u"] +[ext_resource type="RDShaderFile" uid="uid://c4dywnp7k8rph" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_simple.glsl" id="2_msxel"] + +[resource] +script = ExtResource("1_v4e3u") +shader_file = ExtResource("2_msxel") diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_blur_stage.tres b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_blur_stage.tres new file mode 100644 index 0000000..684a55a --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_blur_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://nhb123qs0ja8"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_fyqxe"] +[ext_resource type="RDShaderFile" uid="uid://c57nhlyxb4m1t" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_blur.glsl" id="2_c1vs2"] + +[resource] +script = ExtResource("1_fyqxe") +shader_file = ExtResource("2_c1vs2") diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_cache_stage.tres b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_cache_stage.tres new file mode 100644 index 0000000..c5b760d --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_cache_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://bq18dhoelcexm"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_3clo0"] +[ext_resource type="RDShaderFile" uid="uid://quuyr2q5w5kx" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_cache.glsl" id="2_val47"] + +[resource] +script = ExtResource("1_3clo0") +shader_file = ExtResource("2_val47") diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_construction_stage.tres b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_construction_stage.tres new file mode 100644 index 0000000..8631f8c --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_construction_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://clwi2fnp1nm3r"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_eeyf1"] +[ext_resource type="RDShaderFile" uid="uid://rkkajixdjosk" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_backtracking_experimental.glsl" id="2_o6bvw"] + +[resource] +script = ExtResource("1_eeyf1") +shader_file = ExtResource("2_o6bvw") diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_motion_blur.gd b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_motion_blur.gd new file mode 100644 index 0000000..db046ce --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_motion_blur.gd @@ -0,0 +1,190 @@ +extends "res://addons/SphynxMotionBlurToolkit/JumpFlood/base_jump_flood_motion_blur.gd" +class_name SphynxOldJumpFloodMotionBlur + +@export_group("Shader Stages") +@export var blur_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_blur_stage.tres"): + set(value): + unsubscribe_shader_stage(blur_stage) + blur_stage = value + subscirbe_shader_stage(value) + +@export var overlay_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_overlay_stage.tres"): + set(value): + unsubscribe_shader_stage(overlay_stage) + overlay_stage = value + subscirbe_shader_stage(value) + +@export var construct_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_construction_stage.tres"): + set(value): + unsubscribe_shader_stage(construct_stage) + construct_stage = value + subscirbe_shader_stage(value) + +## how many steps along a range of 2 velocities from the +## dilation target velocity space do we go along to find a better fitting velocity sample +## higher samples meaning higher detail getting captured and blurred +@export var backtracking_sample_count : int = 8 + +## how sensitive the backtracking for velocities be +@export var backtracking_velocity_match_threshold : float = 0.9 + +## how sensitively the backtracking should treat velocities that are a different +## length along that velocity +@export var backtracking_velocity_match_parallel_sensitivity : float = 1 + +## how sensitively the backtracking should treat velcoities that have perpendicular +## offset to that velocity +@export var backtracking_velcoity_match_perpendicular_sensitivity : float = 0.05 + +## how closely does the depth of the backtracked sample has to match the original sample to be +## considered (in NDC space) +@export var backtracbing_depth_match_threshold : float = 0.001 + +var texture: StringName = "texture" + +var buffer_a : StringName = "buffer_a" +var buffer_b : StringName = "buffer_b" + +var custom_velocity : StringName = "custom_velocity" + +var temp_intensity : float + +var previous_time : float = 0 + +func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSceneBuffersRD, render_scene_data : RenderSceneDataRD): + var time : float = float(Time.get_ticks_msec()) / 1000 + + var delta_time : float = time - previous_time + + previous_time = time + + temp_intensity = intensity + + if framerate_independent: + var capped_frame_time : float = 1 / target_constant_framerate + + if !uncapped_independence: + capped_frame_time = min(capped_frame_time, delta_time) + + temp_intensity = intensity * capped_frame_time / delta_time + + + ensure_texture(texture, render_scene_buffers) + ensure_texture(buffer_a, render_scene_buffers)#, RenderingDevice.DATA_FORMAT_R16G16_SFLOAT) + ensure_texture(buffer_b, render_scene_buffers)#, RenderingDevice.DATA_FORMAT_R16G16_SFLOAT) + ensure_texture(custom_velocity, render_scene_buffers) + + rd.draw_command_begin_label("Motion Blur", Color(1.0, 1.0, 1.0, 1.0)) + + var last_iteration_index : int = JFA_pass_count - 1; + + var max_dilation_radius : float = pow(2 + step_exponent_modifier, last_iteration_index) * sample_step_multiplier / intensity; + + var push_constant: PackedFloat32Array = [ + samples, + temp_intensity, + center_fade, + Engine.get_frames_drawn() % 8, + last_iteration_index, + sample_step_multiplier, + step_exponent_modifier, + max_dilation_radius, + ] + var int_push_constant : PackedInt32Array = [ + 0, + 0, + 0, + 0 + ] + var byte_array = push_constant.to_byte_array() + byte_array.append_array(int_push_constant.to_byte_array()) + + var view_count = render_scene_buffers.get_view_count() + for view in range(view_count): + var color_image := render_scene_buffers.get_color_layer(view) + var depth_image := render_scene_buffers.get_depth_layer(view) + var texture_image := render_scene_buffers.get_texture_slice(context, texture, view, 0, 1, 1) + var buffer_a_image := render_scene_buffers.get_texture_slice(context, buffer_a, view, 0, 1, 1) + var buffer_b_image := render_scene_buffers.get_texture_slice(context, buffer_b, view, 0, 1, 1) + var custom_velocity_image := render_scene_buffers.get_texture_slice(context, custom_velocity, view, 0, 1, 1) + + rd.draw_command_begin_label("Construct blur " + str(view), Color(1.0, 1.0, 1.0, 1.0)) + + var tex_uniform_set + var compute_list + + var x_groups := floori((render_size.x - 1) / 16 + 1) + var y_groups := floori((render_size.y - 1) / 16 + 1) + + tex_uniform_set = UniformSetCacheRD.get_cache(construct_stage.shader, 0, [ + get_sampler_uniform(depth_image, 0, false), + get_sampler_uniform(custom_velocity_image, 1, false), + get_image_uniform(buffer_a_image, 2), + get_image_uniform(buffer_b_image, 3), + get_sampler_uniform(buffer_a_image, 4, false), + get_sampler_uniform(buffer_b_image, 5, false) + ]) + + compute_list = rd.compute_list_begin() + rd.compute_list_bind_compute_pipeline(compute_list, construct_stage.pipeline) + rd.compute_list_bind_uniform_set(compute_list, tex_uniform_set, 0) + + for i in JFA_pass_count: + var jf_push_constants : PackedInt32Array = [ + i, + last_iteration_index, + backtracking_sample_count, + 16 + ] + + var step_size : float = round(pow(2 + step_exponent_modifier, last_iteration_index - i)) * sample_step_multiplier; + + var jf_float_push_constants_test : PackedFloat32Array = [ + perpen_error_threshold, + sample_step_multiplier, + temp_intensity, + backtracking_velocity_match_threshold, + backtracking_velocity_match_parallel_sensitivity, + backtracking_velcoity_match_perpendicular_sensitivity, + backtracbing_depth_match_threshold, + step_exponent_modifier, + step_size, + max_dilation_radius, + 0, + 0 + ] + + var jf_byte_array = jf_push_constants.to_byte_array() + jf_byte_array.append_array(jf_float_push_constants_test.to_byte_array()) + + rd.compute_list_set_push_constant(compute_list, jf_byte_array, jf_byte_array.size()) + rd.compute_list_dispatch(compute_list, x_groups, y_groups, 1) + + rd.compute_list_end() + + rd.draw_command_end_label() + + dispatch_stage(blur_stage, + [ + get_sampler_uniform(color_image, 0, false), + get_sampler_uniform(depth_image, 1, false), + get_sampler_uniform(custom_velocity_image, 2, false), + get_sampler_uniform(buffer_b_image if last_iteration_index % 2 else buffer_a_image, 3, false), + get_image_uniform(texture_image, 4), + ], + byte_array, + Vector3i(x_groups, y_groups, 1), + "Compute Blur", + view) + + dispatch_stage(overlay_stage, + [ + get_sampler_uniform(texture_image, 0), + get_image_uniform(color_image, 1) + ], + [], + Vector3i(x_groups, y_groups, 1), + "Overlay Result", + view) + + rd.draw_command_end_label() diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_neighbor_max_stage.tres b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_neighbor_max_stage.tres new file mode 100644 index 0000000..532788e --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_neighbor_max_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://co5k7plgmxepi"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_8et3l"] +[ext_resource type="RDShaderFile" uid="uid://cfk5chwlcyay4" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_max.glsl" id="2_fub7x"] + +[resource] +script = ExtResource("1_8et3l") +shader_file = ExtResource("2_fub7x") diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_overlay_stage.tres b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_overlay_stage.tres new file mode 100644 index 0000000..1016abe --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_overlay_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://dc5fr84ue3dn5"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_6wgo2"] +[ext_resource type="RDShaderFile" uid="uid://dig08kpnfakuf" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_overlay.glsl" id="2_ljukb"] + +[resource] +script = ExtResource("1_6wgo2") +shader_file = ExtResource("2_ljukb") diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_x_stage.tres b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_x_stage.tres new file mode 100644 index 0000000..bd10947 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_x_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://c10aboaly701b"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_5367c"] +[ext_resource type="RDShaderFile" uid="uid://djp3da364fk2l" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_x.glsl" id="2_1b71e"] + +[resource] +script = ExtResource("1_5367c") +shader_file = ExtResource("2_1b71e") diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_y_stage.tres b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_y_stage.tres new file mode 100644 index 0000000..17ed1c7 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_y_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://cymk87e4nyxva"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_5vg08"] +[ext_resource type="RDShaderFile" uid="uid://cqlltc8f21wre" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_y.glsl" id="2_iusae"] + +[resource] +script = ExtResource("1_5vg08") +shader_file = ExtResource("2_iusae") diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/realistic_jf_blur_stage.tres b/addons/SphynxMotionBlurToolkit/JumpFlood/realistic_jf_blur_stage.tres new file mode 100644 index 0000000..9a28052 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/realistic_jf_blur_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://ceav72kvj4qbw"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_qdmen"] +[ext_resource type="RDShaderFile" uid="uid://b1fr5qhhrbpst" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_realistic_blur.glsl" id="2_bdp68"] + +[resource] +script = ExtResource("1_qdmen") +shader_file = ExtResource("2_bdp68") diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/realistic_jf_motion_blur.gd b/addons/SphynxMotionBlurToolkit/JumpFlood/realistic_jf_motion_blur.gd new file mode 100644 index 0000000..cfcce2c --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/realistic_jf_motion_blur.gd @@ -0,0 +1,268 @@ +extends "res://addons/SphynxMotionBlurToolkit/JumpFlood/base_jump_flood_motion_blur.gd" +class_name SphynxRealisticJumpFloodMotionBlur + +@export_group("Shader Stages") +@export var tile_max_x_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_x_stage.tres"): + set(value): + unsubscribe_shader_stage(tile_max_x_stage) + tile_max_x_stage = value + subscirbe_shader_stage(value) + +@export var tile_max_y_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_y_stage.tres"): + set(value): + unsubscribe_shader_stage(tile_max_y_stage) + tile_max_y_stage = value + subscirbe_shader_stage(value) + +@export var construct_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jf_simple_stage.tres"): + set(value): + unsubscribe_shader_stage(construct_stage) + construct_stage = value + subscirbe_shader_stage(value) + +@export var neighbor_max_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_neighbor_max_stage.tres"): + set(value): + unsubscribe_shader_stage(neighbor_max_stage) + neighbor_max_stage = value + subscirbe_shader_stage(value) + +@export var blur_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/realistic_jf_blur_stage.tres"): + set(value): + unsubscribe_shader_stage(blur_stage) + blur_stage = value + subscirbe_shader_stage(value) + +@export var overlay_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_overlay_stage.tres"): + set(value): + unsubscribe_shader_stage(overlay_stage) + overlay_stage = value + subscirbe_shader_stage(value) + +var tile_max_x : StringName = "tile_max_x" + +var tile_max : StringName = "tile_max" + +var neighbor_max : StringName = "neighbor_max" + +var output_color : StringName = "output_color" + +var buffer_a : StringName = "buffer_a" +var buffer_b : StringName = "buffer_b" + +var custom_velocity : StringName = "custom_velocity" +var temp_intensity : float + +var previous_time : float = 0 + +func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSceneBuffersRD, render_scene_data : RenderSceneDataRD): + var time : float = float(Time.get_ticks_msec()) / 1000 + + var delta_time : float = time - previous_time + + previous_time = time + + temp_intensity = intensity + + if framerate_independent: + var capped_frame_time : float = 1 / target_constant_framerate + + if !uncapped_independence: + capped_frame_time = min(capped_frame_time, delta_time) + + temp_intensity = intensity * capped_frame_time / delta_time + + ensure_texture(custom_velocity, render_scene_buffers) + ensure_texture(tile_max_x, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1.)) + ensure_texture(tile_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier)) + ensure_texture(buffer_a, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier)) + ensure_texture(buffer_b, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier)) + ensure_texture(neighbor_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier)) + ensure_texture(output_color, render_scene_buffers) + + rd.draw_command_begin_label("Motion Blur", Color(1.0, 1.0, 1.0, 1.0)) + + var last_iteration_index : int = JFA_pass_count - 1; + + var max_dilation_radius : float = pow(2 + step_exponent_modifier, last_iteration_index) * sample_step_multiplier; + + var tile_max_x_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_tile_max_x_push_constants : PackedInt32Array = [ + sample_step_multiplier, + 0, + 0, + 0 + ] + var tile_max_x_push_constants_byte_array = tile_max_x_push_constants.to_byte_array() + tile_max_x_push_constants_byte_array.append_array(int_tile_max_x_push_constants.to_byte_array()) + + var tile_max_y_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_tile_max_y_push_constants : PackedInt32Array = [ + sample_step_multiplier, + 0, + 0, + 0 + ] + var tile_max_y_push_constants_byte_array = tile_max_y_push_constants.to_byte_array() + tile_max_y_push_constants_byte_array.append_array(int_tile_max_y_push_constants.to_byte_array()) + var neighbor_max_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_neighbor_max_push_constants : PackedInt32Array = [ + 0, + 0, + 0, + 0 + ] + var neighbor_max_push_constants_byte_array = neighbor_max_push_constants.to_byte_array() + neighbor_max_push_constants_byte_array.append_array(int_neighbor_max_push_constants.to_byte_array()) + + var push_constant: PackedFloat32Array = [ + samples, + temp_intensity, + center_fade, + Engine.get_frames_drawn() % 8, + last_iteration_index, + sample_step_multiplier, + step_exponent_modifier, + max_dilation_radius, + ] + var int_push_constant : PackedInt32Array = [ + 0, + 0, + 0, + 0 + ] + var byte_array = push_constant.to_byte_array() + byte_array.append_array(int_push_constant.to_byte_array()) + + var view_count = render_scene_buffers.get_view_count() + for view in range(view_count): + var color_image := render_scene_buffers.get_color_layer(view) + var depth_image := render_scene_buffers.get_depth_layer(view) + var output_color_image := render_scene_buffers.get_texture_slice(context, output_color, view, 0, 1, 1) + var buffer_a_image := render_scene_buffers.get_texture_slice(context, buffer_a, view, 0, 1, 1) + var buffer_b_image := render_scene_buffers.get_texture_slice(context, buffer_b, view, 0, 1, 1) + var custom_velocity_image := render_scene_buffers.get_texture_slice(context, custom_velocity, view, 0, 1, 1) + var tile_max_x_image := render_scene_buffers.get_texture_slice(context, tile_max_x, view, 0, 1, 1) + var tile_max_image := render_scene_buffers.get_texture_slice(context, tile_max, view, 0, 1, 1) + var neighbor_max_image := render_scene_buffers.get_texture_slice(context, neighbor_max, view, 0, 1, 1) + + var x_groups := floori((render_size.x / sample_step_multiplier - 1) / 16 + 1) + var y_groups := floori((render_size.y - 1) / 16 + 1) + + dispatch_stage(tile_max_x_stage, + [ + get_sampler_uniform(custom_velocity_image, 0, false), + get_image_uniform(tile_max_x_image, 1) + ], + tile_max_x_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "TileMaxX", + view) + + x_groups = floori((render_size.x / sample_step_multiplier - 1) / 16 + 1) + y_groups = floori((render_size.y / sample_step_multiplier - 1) / 16 + 1) + + dispatch_stage(tile_max_y_stage, + [ + get_sampler_uniform(tile_max_x_image, 0, false), + get_image_uniform(tile_max_image, 1) + ], + tile_max_y_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "TileMaxY", + view) + + for i in JFA_pass_count: + var jf_push_constants : PackedInt32Array = [ + i, + last_iteration_index, + 0, + 16 + ] + + var step_size : float = round(pow(2 + step_exponent_modifier, last_iteration_index - i)); + + var jf_float_push_constants_test : PackedFloat32Array = [ + perpen_error_threshold, + sample_step_multiplier, + temp_intensity, + 0, + 0, + 0, + 0, + step_exponent_modifier, + step_size, + max_dilation_radius, + 0, + 0 + ] + + var jf_byte_array = jf_push_constants.to_byte_array() + jf_byte_array.append_array(jf_float_push_constants_test.to_byte_array()) + + dispatch_stage(construct_stage, + [ + get_sampler_uniform(tile_max_image, 0, false), + get_image_uniform(buffer_a_image, 1), + get_image_uniform(buffer_b_image, 2), + get_sampler_uniform(buffer_a_image, 3, false), + get_sampler_uniform(buffer_b_image, 4, false), + ], + jf_byte_array, + Vector3i(x_groups, y_groups, 1), + "Construct Blur", + view) + + dispatch_stage(neighbor_max_stage, + [ + get_sampler_uniform(tile_max_image, 0, false), + get_sampler_uniform(buffer_b_image if last_iteration_index % 2 else buffer_a_image, 1, false), + get_image_uniform(neighbor_max_image, 2) + ], + neighbor_max_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "NeighborMax", + view) + + x_groups = floori((render_size.x - 1) / 16 + 1) + y_groups = floori((render_size.y - 1) / 16 + 1) + + dispatch_stage(blur_stage, + [ + get_sampler_uniform(color_image, 0, false), + get_sampler_uniform(depth_image, 1, false), + get_sampler_uniform(custom_velocity_image, 2, false), + get_sampler_uniform(neighbor_max_image, 3, false), + get_image_uniform(output_color_image, 4), + get_sampler_uniform(tile_max_image, 5, false), + ], + byte_array, + Vector3i(x_groups, y_groups, 1), + "Compute Blur", + view) + + dispatch_stage(overlay_stage, + [ + get_sampler_uniform(output_color_image, 0), + get_image_uniform(color_image, 1), + ], + [], + Vector3i(x_groups, y_groups, 1), + "Overlay Result", + view) + + rd.draw_command_end_label() diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/simple_jf_blur_stage.tres b/addons/SphynxMotionBlurToolkit/JumpFlood/simple_jf_blur_stage.tres new file mode 100644 index 0000000..5698a6c --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/simple_jf_blur_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://bk5yd5plopwi2"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_ljx3c"] +[ext_resource type="RDShaderFile" uid="uid://c1vndulne5a5r" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_new_blur.glsl" id="2_i8sdd"] + +[resource] +script = ExtResource("1_ljx3c") +shader_file = ExtResource("2_i8sdd") diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/simple_jf_motion_blur.gd b/addons/SphynxMotionBlurToolkit/JumpFlood/simple_jf_motion_blur.gd new file mode 100644 index 0000000..6c875da --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/simple_jf_motion_blur.gd @@ -0,0 +1,264 @@ +extends "res://addons/SphynxMotionBlurToolkit/JumpFlood/base_jump_flood_motion_blur.gd" +class_name SphynxSimpleJumpFloodMotionBlur +@export_group("Shader Stages") +@export var tile_max_x_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_x_stage.tres"): + set(value): + unsubscribe_shader_stage(tile_max_x_stage) + tile_max_x_stage = value + subscirbe_shader_stage(value) + +@export var tile_max_y_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_y_stage.tres"): + set(value): + unsubscribe_shader_stage(tile_max_y_stage) + tile_max_y_stage = value + subscirbe_shader_stage(value) + +@export var construct_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jf_simple_stage.tres"): + set(value): + unsubscribe_shader_stage(construct_stage) + construct_stage = value + subscirbe_shader_stage(value) + +@export var neighbor_max_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_neighbor_max_stage.tres"): + set(value): + unsubscribe_shader_stage(neighbor_max_stage) + neighbor_max_stage = value + subscirbe_shader_stage(value) + +@export var blur_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/simple_jf_blur_stage.tres"): + set(value): + unsubscribe_shader_stage(blur_stage) + blur_stage = value + subscirbe_shader_stage(value) + +@export var overlay_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_overlay_stage.tres"): + set(value): + unsubscribe_shader_stage(overlay_stage) + overlay_stage = value + subscirbe_shader_stage(value) + +var tile_max_x : StringName = "tile_max_x" + +var tile_max : StringName = "tile_max" + +var neighbor_max : StringName = "neighbor_max" + +var output_color : StringName = "output_color" + +var buffer_a : StringName = "buffer_a" +var buffer_b : StringName = "buffer_b" + +var custom_velocity : StringName = "custom_velocity" +var temp_intensity : float + +var previous_time : float = 0 + +func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSceneBuffersRD, render_scene_data : RenderSceneDataRD): + var time : float = float(Time.get_ticks_msec()) / 1000 + + var delta_time : float = time - previous_time + + previous_time = time + + temp_intensity = intensity + + if framerate_independent: + var capped_frame_time : float = 1 / target_constant_framerate + + if !uncapped_independence: + capped_frame_time = min(capped_frame_time, delta_time) + + temp_intensity = intensity * capped_frame_time / delta_time + + ensure_texture(custom_velocity, render_scene_buffers) + ensure_texture(tile_max_x, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1.)) + ensure_texture(tile_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier)) + ensure_texture(buffer_a, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier)) + ensure_texture(buffer_b, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier)) + ensure_texture(neighbor_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier)) + ensure_texture(output_color, render_scene_buffers) + + rd.draw_command_begin_label("Motion Blur", Color(1.0, 1.0, 1.0, 1.0)) + + var last_iteration_index : int = JFA_pass_count - 1; + + var max_dilation_radius : float = pow(2 + step_exponent_modifier, last_iteration_index) * sample_step_multiplier; + + var tile_max_x_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_tile_max_x_push_constants : PackedInt32Array = [ + sample_step_multiplier, + 0, + 0, + 0 + ] + var tile_max_x_push_constants_byte_array = tile_max_x_push_constants.to_byte_array() + tile_max_x_push_constants_byte_array.append_array(int_tile_max_x_push_constants.to_byte_array()) + + var tile_max_y_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_tile_max_y_push_constants : PackedInt32Array = [ + sample_step_multiplier, + 0, + 0, + 0 + ] + var tile_max_y_push_constants_byte_array = tile_max_y_push_constants.to_byte_array() + tile_max_y_push_constants_byte_array.append_array(int_tile_max_y_push_constants.to_byte_array()) + var neighbor_max_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_neighbor_max_push_constants : PackedInt32Array = [ + 0, + 0, + 0, + 0 + ] + var neighbor_max_push_constants_byte_array = neighbor_max_push_constants.to_byte_array() + neighbor_max_push_constants_byte_array.append_array(int_neighbor_max_push_constants.to_byte_array()) + + var push_constant: PackedFloat32Array = [ + samples, + temp_intensity, + center_fade, + Engine.get_frames_drawn() % 8, + last_iteration_index, + sample_step_multiplier, + step_exponent_modifier, + max_dilation_radius, + ] + var int_push_constant : PackedInt32Array = [ + 0, + 0, + 0, + 0 + ] + var byte_array = push_constant.to_byte_array() + byte_array.append_array(int_push_constant.to_byte_array()) + + var view_count = render_scene_buffers.get_view_count() + for view in range(view_count): + var color_image := render_scene_buffers.get_color_layer(view) + var depth_image := render_scene_buffers.get_depth_layer(view) + var output_color_image := render_scene_buffers.get_texture_slice(context, output_color, view, 0, 1, 1) + var buffer_a_image := render_scene_buffers.get_texture_slice(context, buffer_a, view, 0, 1, 1) + var buffer_b_image := render_scene_buffers.get_texture_slice(context, buffer_b, view, 0, 1, 1) + var custom_velocity_image := render_scene_buffers.get_texture_slice(context, custom_velocity, view, 0, 1, 1) + var tile_max_x_image := render_scene_buffers.get_texture_slice(context, tile_max_x, view, 0, 1, 1) + var tile_max_image := render_scene_buffers.get_texture_slice(context, tile_max, view, 0, 1, 1) + var neighbor_max_image := render_scene_buffers.get_texture_slice(context, neighbor_max, view, 0, 1, 1) + + var x_groups := floori((render_size.x / sample_step_multiplier - 1) / 16 + 1) + var y_groups := floori((render_size.y - 1) / 16 + 1) + + dispatch_stage(tile_max_x_stage, + [ + get_sampler_uniform(custom_velocity_image, 0, false), + get_image_uniform(tile_max_x_image, 1) + ], + tile_max_x_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "TileMaxX", + view) + + x_groups = floori((render_size.x / sample_step_multiplier - 1) / 16 + 1) + y_groups = floori((render_size.y / sample_step_multiplier - 1) / 16 + 1) + + dispatch_stage(tile_max_y_stage, + [ + get_sampler_uniform(tile_max_x_image, 0, false), + get_image_uniform(tile_max_image, 1) + ], + tile_max_y_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "TileMaxY", + view) + + for i in JFA_pass_count: + var jf_push_constants : PackedInt32Array = [ + i, + last_iteration_index, + 0, + 16 + ] + + var jf_float_push_constants_test : PackedFloat32Array = [ + perpen_error_threshold, + sample_step_multiplier, + temp_intensity, + 0, + 0, + 0, + 0, + step_exponent_modifier, + 0, + max_dilation_radius, + 0, + 0 + ] + var jf_byte_array = jf_push_constants.to_byte_array() + jf_byte_array.append_array(jf_float_push_constants_test.to_byte_array()) + + dispatch_stage(construct_stage, + [ + get_sampler_uniform(tile_max_image, 0, false), + get_image_uniform(buffer_a_image, 1), + get_image_uniform(buffer_b_image, 2), + get_sampler_uniform(buffer_a_image, 3, false), + get_sampler_uniform(buffer_b_image, 4, false), + ], + jf_byte_array, + Vector3i(x_groups, y_groups, 1), + "Construct Blur", + view) + + dispatch_stage(neighbor_max_stage, + [ + get_sampler_uniform(tile_max_image, 0, false), + get_sampler_uniform(buffer_b_image if last_iteration_index % 2 else buffer_a_image, 1, false), + get_image_uniform(neighbor_max_image, 2) + ], + neighbor_max_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "NeighborMax", + view) + + x_groups = floori((render_size.x - 1) / 16 + 1) + y_groups = floori((render_size.y - 1) / 16 + 1) + + dispatch_stage(blur_stage, + [ + get_sampler_uniform(color_image, 0, false), + get_sampler_uniform(depth_image, 1, false), + get_sampler_uniform(custom_velocity_image, 2, false), + get_sampler_uniform(neighbor_max_image, 3, false), + get_image_uniform(output_color_image, 4), + get_sampler_uniform(tile_max_image, 5, false), + ], + byte_array, + Vector3i(x_groups, y_groups, 1), + "Compute Blur", + view) + + dispatch_stage(overlay_stage, + [ + get_sampler_uniform(output_color_image, 0), + get_image_uniform(color_image, 1), + ], + [], + Vector3i(x_groups, y_groups, 1), + "Overlay Result", + view) + + rd.draw_command_end_label() diff --git a/addons/SphynxMotionBlurToolkit/LICENSE b/addons/SphynxMotionBlurToolkit/LICENSE new file mode 100644 index 0000000..2dea453 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 sphynx-owner + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/addons/SphynxMotionBlurToolkit/LinearBlurToolkit/LinearMotionBlurMesh.gdshader b/addons/SphynxMotionBlurToolkit/LinearBlurToolkit/LinearMotionBlurMesh.gdshader new file mode 100644 index 0000000..d0e2929 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/LinearBlurToolkit/LinearMotionBlurMesh.gdshader @@ -0,0 +1,152 @@ +shader_type spatial; + +render_mode unshaded, depth_draw_always, fog_disabled; + +uniform sampler2D screen_texture : hint_screen_texture, filter_nearest; +uniform sampler2D depth_texture : hint_depth_texture, filter_nearest; + +uniform vec3 local_stretch_axis = vec3(0, 1, 0); + +uniform float movement_speed = 0; + +uniform int sample_count = 8; + +uniform float debug_toggle = 0; + +uniform vec4 debug_color : source_color = vec4(0); + +//https://www.shadertoy.com/view/fdtfWM +vec3 rotate(float angle, vec3 axis, vec3 point) // NOTE: axis must be unit! +{ + float c = cos(angle); + float s = sin(angle); + return c * point + s * cross(axis, point) + (1.0 - c) * (dot(point, axis) * axis); // Rodrigues' Rotation Formula +} + +// from https://www.shadertoy.com/view/ftKfzc +float interleaved_gradient_noise(vec2 uv, int FrameId){ + uv += float(FrameId) * (vec2(47, 17) * 0.695); + + vec3 magic = vec3( 0.06711056, 0.00583715, 52.9829189 ); + + return fract(magic.z * fract(dot(uv, magic.xy))); +} + +vec3 get_projection_onto_plane(vec3 plane_origin, vec3 normal, vec3 vector) +{ + float plane_distance = dot(plane_origin, normal); + return vector * plane_distance / dot(normal, vector); +} + +float soft_depth_compare(float x, float y, float sze) +{ + return clamp(1. - (x - y) / sze, 0., 1.); +} + +vec2 intersect_cylinder(vec3 eye_point, vec3 end_point, vec3 origin, vec3 axis, float radius) +{ + eye_point -= axis * dot(eye_point - origin, axis) + origin; + + end_point -= axis * dot(end_point - origin, axis) + origin; + + vec3 direction = end_point - eye_point; + + float A = dot(direction, direction); + float B = 2. * dot(eye_point, direction); + float C = dot(eye_point, eye_point) - radius * radius; + + float square_component = sqrt(B * B - 4. * A * C); + + return vec2(-B + square_component, -B - square_component) / (2. * A); +} + +vec2 within_cylinder(vec3 point, vec3 origin, vec3 axis, float radius, float depth, float axis_offset) +{ + float within_depth = step(abs(dot(point - origin - axis * axis_offset, axis)), depth / 2.); + vec3 perpendicular_component = point - axis * dot(axis, point - origin) - origin; + float within_radius = step(dot(perpendicular_component, perpendicular_component), radius * radius); + + return vec2(within_depth * within_radius, step(0, dot(point - origin, axis))); +} + +vec3 color_corrected(vec3 color) +{ + return color / mix( + pow((vec3(1.) + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), + vec3(1.) * (1.0 / 12.92), + lessThan(vec3(1.), vec3(0.04045))); +} + +void fragment() { + vec2 screen_uv = SCREEN_UV; + + float depth = texture(depth_texture, screen_uv).x; + vec3 ndc = vec3(screen_uv * 2.0 - 1.0, depth); + vec4 world_position = INV_VIEW_MATRIX * INV_PROJECTION_MATRIX * vec4(ndc, 1.0); + world_position.xyz /= world_position.w; + + vec4 world_mesh_position = INV_VIEW_MATRIX * INV_PROJECTION_MATRIX * vec4(screen_uv * 2.0 - 1.0, FRAGCOORD.z, 1.0); + world_mesh_position.xyz /= world_mesh_position.w; + + vec3 node_relative_position = world_position.xyz - NODE_POSITION_WORLD; + + vec3 camera_node_position = NODE_POSITION_WORLD - CAMERA_POSITION_WORLD; + + vec3 camera_relative_position = world_position.xyz - CAMERA_POSITION_WORLD; + + float on_mesh = 1.; + + vec3 raw_clamped_difference = vec3(0.); + + node_relative_position = world_mesh_position.xyz - NODE_POSITION_WORLD; + + float noise_variation = interleaved_gradient_noise(SCREEN_UV * vec2(textureSize(screen_texture, 0)), int(TIME * 100.)) / float(sample_count); + + float sum = 1.; + + vec4 base_sample = texture(screen_texture, screen_uv); + + vec4 col = base_sample; + + float original_depth = 0.05 / depth; + + for(int i = 0; i < sample_count; i++) + { + vec3 node_rotated_sample = node_relative_position.xyz + mat3(MODEL_MATRIX) * vec3(movement_speed * (local_stretch_axis * (float(i) / float(sample_count) + noise_variation))); + + vec4 current_ndc = (PROJECTION_MATRIX * VIEW_MATRIX * (vec4(node_rotated_sample, 1) + vec4(NODE_POSITION_WORLD, 0))); + + current_ndc.xyz /= current_ndc.w; + + vec2 current_uv_sample = ((current_ndc + 1.) / 2.).xy ; + + float current_depth = texture(depth_texture, current_uv_sample).x; + + vec4 current_world_position = INV_VIEW_MATRIX * INV_PROJECTION_MATRIX * vec4(vec3(current_ndc.xy, current_depth), 1.0); + + current_world_position.xyz /= current_world_position.w; + + current_depth = 0.05 / current_depth; + + float current_sample_depth = 0.05 / current_ndc.z; + + if (current_uv_sample.x < 0. || current_uv_sample.x > 1. || current_uv_sample.y < 0. || current_uv_sample.y > 1.) + { + continue; + } + + float is_inside = step(current_depth - current_sample_depth, 1); + + float original_inside = 1. - step(current_depth - original_depth, 1); + + float revert_texture = max(is_inside, original_inside); + + float weight = 1.; + sum += weight; + col += mix(base_sample, texture(screen_texture, current_uv_sample), revert_texture) * weight; + } + + col /= sum; + + ALBEDO = col.xyz + debug_color.xyz;//vec3(depth * 10.);// +} diff --git a/addons/SphynxMotionBlurToolkit/LinearBlurToolkit/LinearMotionBlurMesh.tscn b/addons/SphynxMotionBlurToolkit/LinearBlurToolkit/LinearMotionBlurMesh.tscn new file mode 100644 index 0000000..d2153b3 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/LinearBlurToolkit/LinearMotionBlurMesh.tscn @@ -0,0 +1,21 @@ +[gd_scene load_steps=5 format=3 uid="uid://b8aytbebcsmv8"] + +[ext_resource type="Shader" path="res://addons/SphynxMotionBlurToolkit/LinearBlurToolkit/LinearMotionBlurMesh.gdshader" id="1_m7mjv"] +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/LinearBlurToolkit/linear_motion_blur_mesh.gd" id="2_glqur"] + +[sub_resource type="BoxMesh" id="BoxMesh_lylv4"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_oosyj"] +resource_local_to_scene = true +render_priority = 0 +shader = ExtResource("1_m7mjv") +shader_parameter/local_stretch_axis = Vector3(0, 1, 0) +shader_parameter/movement_speed = 0.0 +shader_parameter/sample_count = 8 +shader_parameter/debug_toggle = 0.0 +shader_parameter/debug_color = Color(0, 0, 0, 0) + +[node name="LinearMotionBlurMesh" type="MeshInstance3D"] +mesh = SubResource("BoxMesh_lylv4") +surface_material_override/0 = SubResource("ShaderMaterial_oosyj") +script = ExtResource("2_glqur") diff --git a/addons/SphynxMotionBlurToolkit/LinearBlurToolkit/linear_motion_blur_mesh.gd b/addons/SphynxMotionBlurToolkit/LinearBlurToolkit/linear_motion_blur_mesh.gd new file mode 100644 index 0000000..886d345 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/LinearBlurToolkit/linear_motion_blur_mesh.gd @@ -0,0 +1,63 @@ +extends MeshInstance3D +class_name LinearMotionBlurMesh + +@export var target_node : Node3D + +## the rotation vector the current mesh blur's around +## locally +@export_enum("x", "y", "z") var local_stretch_axis : int + +@export var negate_local_stretch_axis : bool = false + +@onready var local_stretch_vector : Vector3 = Vector3(1 if local_stretch_axis == 0 else 0, 1 if local_stretch_axis == 1 else 0, 1 if local_stretch_axis == 2 else 0) * (1 if !negate_local_stretch_axis else -1) + +## At what speed does the mesh become visible and start blurring +@export var speed_visibility_threshold : float = 0.2 + +## make mesh visible for debugging +@export var show_debug : bool = false + +var previous_mesh_transform : Transform3D = Transform3D() + +var shape_depth : float = 0 + +func _ready(): + get_surface_override_material(0).set_shader_parameter("debug_color", Color(0, 0, 0, 0) if !show_debug else Color(1, 0, 0, 0)) + + var mesh_aabb : AABB = mesh.get_aabb() + + var extent : Vector3 = mesh_aabb.size * global_basis.get_scale() + + var center : Vector3 = mesh_aabb.get_center() * global_basis.get_scale() + + var all_axis : Array[float] = [extent.x, extent.y, extent.z] + + shape_depth = all_axis[local_stretch_axis] + + previous_mesh_transform = target_node.global_transform + + deferred_update_cylinder_data.call_deferred() + +func deferred_update_cylinder_data(): + get_surface_override_material(0).set_shader_parameter("local_stretch_axis", local_stretch_vector) + +func _process(delta: float) -> void: + var target_transform : Transform3D = target_node.global_transform + + var offset : Vector3 = target_transform.origin - previous_mesh_transform.origin + + var distance : float = (offset).length() + + visible = distance > speed_visibility_threshold + + get_surface_override_material(0).set_shader_parameter("movement_speed", distance / (distance + shape_depth)) + + global_position = target_transform.origin - offset / 2 + + previous_mesh_transform = target_transform + + var alignment_quaternion : Quaternion = Quaternion(global_basis.orthonormalized() * local_stretch_vector, offset.normalized()) + + global_basis = Basis(alignment_quaternion) * global_basis; + + scale = scale * (Vector3(1, 1, 1) - local_stretch_vector) + local_stretch_vector * (distance + shape_depth) diff --git a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_blur.glsl b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_blur.glsl new file mode 100644 index 0000000..a3e9681 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_blur.glsl @@ -0,0 +1,137 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D color_sampler; +layout(set = 0, binding = 1) uniform sampler2D depth_sampler; +layout(set = 0, binding = 2) uniform sampler2D velocity_sampler; +layout(set = 0, binding = 3) uniform sampler2D neighbor_max; +layout(set = 0, binding = 4) uniform sampler2D tile_variance; +layout(rgba16f, set = 0, binding = 5) uniform writeonly image2D output_color; +layout(rgba16f, set = 0, binding = 6) uniform image2D past_color_image; + +layout(push_constant, std430) uniform Params +{ + float nan5; + float nan6; + float nan7; + float nan8; + int tile_size; + int sample_count; + int frame; + int nan4; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +// McGuire's functions https://docs.google.com/document/d/1IIlAKTj-O01hcXEdGxTErQbCHO9iBmRx6oFUy_Jm0fI/edit +// ---------------------------------------------------------- +float soft_depth_compare(float depth_X, float depth_Y, float sze) +{ + return clamp(1 - (depth_X - depth_Y) / sze, 0, 1); +} + +float cone(float T, float v) +{ + return clamp(1 - abs(T) / v, 0, 1); +} + +float cylinder(float T, float v) +{ + return 1.0 - smoothstep(0.95 * v, 1.05 * v, abs(T)); +} +// ---------------------------------------------------------- + +// Guertin's functions https://research.nvidia.com/sites/default/files/pubs/2013-11_A-Fast-and/Guertin2013MotionBlur-small.pdf +// ---------------------------------------------------------- +float z_compare(float a, float b, float multiplier) +{ + return clamp(1. + (a - b) * multiplier, 0, 1); +} +// ---------------------------------------------------------- + +// from https://www.shadertoy.com/view/ftKfzc +// ---------------------------------------------------------- +float interleaved_gradient_noise(vec2 uv, int FrameId){ + uv += float(FrameId) * (vec2(47, 17) * 0.695); + + vec3 magic = vec3( 0.06711056, 0.00583715, 52.9829189 ); + + return fract(magic.z * fract(dot(uv, magic.xy))); +} +// ---------------------------------------------------------- + +vec2 sample_random_offset(vec2 uv, float j) +{ + return vec2(0); +} + +void main() +{ + ivec2 render_size = ivec2(textureSize(color_sampler, 0)); + ivec2 tile_render_size = ivec2(textureSize(neighbor_max, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + + vec2 x = (vec2(uvi) + vec2(0.5)) / vec2(render_size); + + vec2 vn = textureLod(neighbor_max, x, 0.0).xy * render_size / 2; + + float vn_length = max(0.5, length(vn)); + + vec4 base_color = textureLod(color_sampler, x, 0.0); + + if(vn_length <= 0.5) + { + imageStore(output_color, uvi, base_color); + return; + } + + vec2 vx = textureLod(velocity_sampler, x, 0.0).xy * render_size / 2; + + float zx = -0.05 / textureLod(depth_sampler, x, 0.0).x; + + float vx_length = max(0.5, length(vx)); + + float weight = 1. / vx_length; + + vec4 sum = base_color * weight; + + float j = interleaved_gradient_noise(uvi, params.frame) - 0.5; + + for(int i = 0; i < params.sample_count; i++) + { + if(i == (params.sample_count - 1) / 2) + { + continue; + } + float t = mix(-1, 1, (i + j + 1.0) / (params.sample_count + 1.0)); + + float T = t * vn_length; + + vec2 y = x + (vn / render_size) * t; + + vec2 vy = textureLod(velocity_sampler, y, 0.0).xy * render_size / 2; + + float vy_length = max(0.5, length(vy)); + + float zy = -0.05 / textureLod(depth_sampler, y, 0.0).x; + + float f = soft_depth_compare(zx, zy, 0.01); + float b = soft_depth_compare(zy, zx, 0.01); + + float ay = f * cone(T, vy_length) + b * cone(T, vx_length) + cylinder(T, vy_length) * cylinder(T, vx_length) * 2; + + weight += ay; + sum += ay * textureLod(color_sampler, y, 0.0); + } + + sum /= weight; + + imageStore(output_color, uvi, sum); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_blur.glsl.import b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_blur.glsl.import new file mode 100644 index 0000000..06fe5dd --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_blur.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://7fjex8wuiejk" +path="res://.godot/imported/mcguire_blur.glsl-0cc0e90626b85e4aae8d4b21c9368b86.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_blur.glsl" +dest_files=["res://.godot/imported/mcguire_blur.glsl-0cc0e90626b85e4aae8d4b21c9368b86.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_neighbor_max.glsl b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_neighbor_max.glsl new file mode 100644 index 0000000..ccd3b7f --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_neighbor_max.glsl @@ -0,0 +1,72 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D tile_max; +layout(rgba16f, set = 0, binding = 1) uniform writeonly image2D neighbor_max; + +layout(push_constant, std430) uniform Params +{ + float nan5; + float nan6; + float nan7; + float nan8; + int nan1; + int nan2; + int nan3; + int nan4; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + + +void main() +{ + ivec2 render_size = ivec2(textureSize(tile_max, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + + vec2 uvn = (vec2(uvi) + vec2(0.5)) / render_size; + + vec2 max_neighbor_velocity = vec2(0); + + float max_neighbor_velocity_length = 0; + + for(int i = -1; i < 2; i++) + { + for(int j = -1; j < 2; j++) + { + vec2 current_offset = vec2(1) / vec2(render_size) * vec2(i, j); + vec2 current_uv = uvn + current_offset; + if(current_uv.x < 0 || current_uv.x > 1 || current_uv.y < 0 || current_uv.y > 1) + { + continue; + } + + bool is_diagonal = (abs(i) + abs(j) == 2); + + vec2 current_neighbor_velocity = textureLod(tile_max, current_uv, 0.0).xy; + + bool facing_center = dot(current_neighbor_velocity, current_offset) > 0; + + if(is_diagonal && !facing_center) + { + continue; + } + + float current_neighbor_velocity_length = dot(current_neighbor_velocity, current_neighbor_velocity); + if(current_neighbor_velocity_length > max_neighbor_velocity_length) + { + max_neighbor_velocity_length = current_neighbor_velocity_length; + max_neighbor_velocity = current_neighbor_velocity; + } + } + } + + imageStore(neighbor_max, uvi, vec4(max_neighbor_velocity, 0, 1)); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_neighbor_max.glsl.import b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_neighbor_max.glsl.import new file mode 100644 index 0000000..a1d726c --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_neighbor_max.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://byfogr1qtbafi" +path="res://.godot/imported/mcguire_neighbor_max.glsl-aa40cc8d534a08ad7aaf84bf0615cc3a.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_neighbor_max.glsl" +dest_files=["res://.godot/imported/mcguire_neighbor_max.glsl-aa40cc8d534a08ad7aaf84bf0615cc3a.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_overlay.glsl b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_overlay.glsl new file mode 100644 index 0000000..c85ac5b --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_overlay.glsl @@ -0,0 +1,18 @@ +#[compute] +#version 450 + +layout(set = 0, binding = 0) uniform sampler2D blur_sampler; +layout(rgba16f, set = 0, binding = 1) uniform image2D color_image; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; +void main() +{ + ivec2 render_size = ivec2(textureSize(blur_sampler, 0)); + ivec2 output_size = imageSize(color_image); + ivec2 uv = ivec2(gl_GlobalInvocationID.xy); + if ((uv.x >= output_size.x) || (uv.y >= output_size.y)) + { + return; + } + imageStore(color_image, uv, textureLod(blur_sampler, (vec2(uv) + 0.5) / output_size, 0.0)); +} diff --git a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_overlay.glsl.import b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_overlay.glsl.import new file mode 100644 index 0000000..96ed706 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_overlay.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://ylkrbqh7unvl" +path="res://.godot/imported/mcguire_overlay.glsl-a331e470c95eacb608a05976de7b2202.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_overlay.glsl" +dest_files=["res://.godot/imported/mcguire_overlay.glsl-a331e470c95eacb608a05976de7b2202.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_x.glsl b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_x.glsl new file mode 100644 index 0000000..4106f70 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_x.glsl @@ -0,0 +1,54 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D velocity_sampler; +layout(rgba16f, set = 0, binding = 1) uniform writeonly image2D tile_max_x; + +layout(push_constant, std430) uniform Params +{ + float nan5; + float nan6; + float nan7; + float nan8; + int tile_size; + int nan2; + int nan3; + int nan4; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + + +void main() +{ + ivec2 render_size = ivec2(textureSize(velocity_sampler, 0)); + ivec2 output_size = imageSize(tile_max_x); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + ivec2 global_uvi = uvi * ivec2(params.tile_size, 1); + if ((uvi.x >= output_size.x) || (uvi.y >= output_size.y)) + { + return; + } + + vec2 uvn = (vec2(global_uvi) + vec2(0.5)) / render_size; + + vec2 max_velocity = vec2(0); + + float max_velocity_length = 0; + + for(int i = 0; i < params.tile_size; i++) + { + vec2 current_uv = uvn + vec2(float(i) / render_size.x, 0); + vec2 velocity_sample = textureLod(velocity_sampler, current_uv, 0.0).xy; + float current_velocity_length = dot(velocity_sample, velocity_sample); + if(current_velocity_length > max_velocity_length) + { + max_velocity_length = current_velocity_length; + max_velocity = velocity_sample; + } + } + imageStore(tile_max_x, uvi, vec4(max_velocity, 0, 1)); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_x.glsl.import b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_x.glsl.import new file mode 100644 index 0000000..e0e6e03 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_x.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://bp5jl5351ph2d" +path="res://.godot/imported/mcguire_tile_max_x.glsl-9c459b3d537ec225893d39ee91be1c1e.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_x.glsl" +dest_files=["res://.godot/imported/mcguire_tile_max_x.glsl-9c459b3d537ec225893d39ee91be1c1e.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_y.glsl b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_y.glsl new file mode 100644 index 0000000..ecd2c84 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_y.glsl @@ -0,0 +1,54 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D tile_max_x; +layout(rgba16f, set = 0, binding = 1) uniform writeonly image2D tile_max; + +layout(push_constant, std430) uniform Params +{ + float nan5; + float nan6; + float nan7; + float nan8; + int tile_size; + int nan2; + int nan3; + int nan4; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + + +void main() +{ + ivec2 render_size = ivec2(textureSize(tile_max_x, 0)); + ivec2 output_size = imageSize(tile_max); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + ivec2 global_uvi = uvi * ivec2(1, params.tile_size); + if ((uvi.x >= output_size.x) || (uvi.y >= output_size.y)) + { + return; + } + + vec2 uvn = (vec2(global_uvi) + vec2(0.5)) / render_size; + + vec2 max_velocity = vec2(0); + + float max_velocity_length = 0; + + for(int i = 0; i < params.tile_size; i++) + { + vec2 current_uv = uvn + vec2(0, float(i) / render_size.y); + vec2 velocity_sample = textureLod(tile_max_x, current_uv, 0.0).xy; + float current_velocity_length = dot(velocity_sample, velocity_sample); + if(current_velocity_length > max_velocity_length) + { + max_velocity_length = current_velocity_length; + max_velocity = velocity_sample; + } + } + imageStore(tile_max, uvi, vec4(max_velocity, 0, 1)); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_y.glsl.import b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_y.glsl.import new file mode 100644 index 0000000..1fa0c65 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_y.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://deow8m5u2ji84" +path="res://.godot/imported/mcguire_tile_max_y.glsl-d6c42f715f0dbdbc13190532231a64e9.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_y.glsl" +dest_files=["res://.godot/imported/mcguire_tile_max_y.glsl-d6c42f715f0dbdbc13190532231a64e9.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_variance.glsl b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_variance.glsl new file mode 100644 index 0000000..24ec95c --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_variance.glsl @@ -0,0 +1,68 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D tile_max; +layout(rgba16f, set = 0, binding = 1) uniform writeonly image2D tile_variance; + +layout(push_constant, std430) uniform Params +{ + float nan5; + float nan6; + float nan7; + float nan8; + int nan1; + int nan2; + int nan3; + int nan4; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + + +void main() +{ + ivec2 render_size = ivec2(textureSize(tile_max, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + + vec2 uvn = (vec2(uvi) + vec2(0.5)) / render_size; + + float variance = 0; + + vec2 current_velocity = abs(normalize(textureLod(tile_max, uvn, 0.0).xy)); + + float tile_count = 0; + + for(int i = -1; i < 2; i++) + { + for(int j = -1; j < 2; j++) + { + vec2 current_offset = vec2(1) / vec2(render_size) * vec2(i, j); + vec2 current_uv = uvn + current_offset; + if(current_uv.x < 0 || current_uv.x > 1 || current_uv.y < 0 || current_uv.y > 1) + { + continue; + } + if(i == j && i == 0) + { + continue; + } + + tile_count += 1; + + vec2 current_neighbor_velocity = abs(normalize(textureLod(tile_max, current_uv, 0.0).xy)); + + variance += dot(current_velocity, current_neighbor_velocity); + } + } + + variance /= tile_count; + + imageStore(tile_variance, uvi, vec4(1 - variance)); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_variance.glsl.import b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_variance.glsl.import new file mode 100644 index 0000000..f2f84e2 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_variance.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://ddo60n85uqwbk" +path="res://.godot/imported/mcguire_tile_variance.glsl-2a5a77e5f43c4a3d379a9c7c55e12bf6.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_variance.glsl" +dest_files=["res://.godot/imported/mcguire_tile_variance.glsl-2a5a77e5f43c4a3d379a9c7c55e12bf6.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/McGuire/base_mcguire_motion_blur.gd b/addons/SphynxMotionBlurToolkit/McGuire/base_mcguire_motion_blur.gd new file mode 100644 index 0000000..a858ad8 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/base_mcguire_motion_blur.gd @@ -0,0 +1,4 @@ +extends "res://addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor_effect.gd" + +@export_group("Shader Parameters") +@export var tile_size : int = 40 diff --git a/addons/SphynxMotionBlurToolkit/McGuire/mcguire_blur_stage.tres b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_blur_stage.tres new file mode 100644 index 0000000..4bae310 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_blur_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://cp5pmuoa15e5g"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_16plp"] +[ext_resource type="RDShaderFile" uid="uid://7fjex8wuiejk" path="res://addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_blur.glsl" id="2_nk2ao"] + +[resource] +script = ExtResource("1_16plp") +shader_file = ExtResource("2_nk2ao") diff --git a/addons/SphynxMotionBlurToolkit/McGuire/mcguire_motion_blur.gd b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_motion_blur.gd new file mode 100644 index 0000000..1a95dc6 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_motion_blur.gd @@ -0,0 +1,230 @@ +extends "res://addons/SphynxMotionBlurToolkit/McGuire/base_mcguire_motion_blur.gd" +class_name McGuireMotionBlur + +@export_group("Shader Stages") +@export var blur_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/McGuire/mcguire_blur_stage.tres"): + set(value): + unsubscribe_shader_stage(blur_stage) + blur_stage = value + subscirbe_shader_stage(value) + +@export var overlay_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/McGuire/mcguire_overlay_stage.tres"): + set(value): + unsubscribe_shader_stage(overlay_stage) + overlay_stage = value + subscirbe_shader_stage(value) + +@export var tile_max_x_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/McGuire/mcguire_tile_max_x_stage.tres"): + set(value): + unsubscribe_shader_stage(tile_max_x_stage) + tile_max_x_stage = value + subscirbe_shader_stage(value) + +@export var tile_max_y_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/McGuire/mcguire_tile_max_y_stage.tres"): + set(value): + unsubscribe_shader_stage(tile_max_y_stage) + tile_max_y_stage = value + subscirbe_shader_stage(value) + +@export var neighbor_max_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/McGuire/mcguire_neighbor_max_stage.tres"): + set(value): + unsubscribe_shader_stage(neighbor_max_stage) + neighbor_max_stage = value + subscirbe_shader_stage(value) + +@export var tile_variance_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/McGuire/mcguire_tile_variance_stage.tres"): + set(value): + unsubscribe_shader_stage(tile_variance_stage) + tile_variance_stage = value + subscirbe_shader_stage(value) + +var output_color: StringName = "output_color" + +var tile_max_x : StringName = "tile_max_x" + +var tile_max : StringName = "tile_max" + +var neighbor_max : StringName = "neighbor_max" + +var tile_variance : StringName = "tile_variance" + +var past_color : StringName = "past_color" + +var custom_velocity : StringName = "custom_velocity" + +var freeze : bool = false + +func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSceneBuffersRD, render_scene_data : RenderSceneDataRD): + ensure_texture(tile_max_x, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1.)) + ensure_texture(tile_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1. / tile_size)) + ensure_texture(neighbor_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1. / tile_size)) + ensure_texture(tile_variance, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1. / tile_size)) + ensure_texture(past_color, render_scene_buffers) + ensure_texture(custom_velocity, render_scene_buffers) + ensure_texture(output_color, render_scene_buffers) + + rd.draw_command_begin_label("Motion Blur", Color(1.0, 1.0, 1.0, 1.0)) + + var tile_max_x_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_tile_max_x_push_constants : PackedInt32Array = [ + tile_size, + 0, + 0, + 0 + ] + var tile_max_x_push_constants_byte_array = tile_max_x_push_constants.to_byte_array() + tile_max_x_push_constants_byte_array.append_array(int_tile_max_x_push_constants.to_byte_array()) + + var tile_max_y_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_tile_max_y_push_constants : PackedInt32Array = [ + tile_size, + 0, + 0, + 0 + ] + var tile_max_y_push_constants_byte_array = tile_max_y_push_constants.to_byte_array() + tile_max_y_push_constants_byte_array.append_array(int_tile_max_y_push_constants.to_byte_array()) + + var neighbor_max_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_neighbor_max_push_constants : PackedInt32Array = [ + 0, + 0, + 0, + 0 + ] + var neighbor_max_push_constants_byte_array = neighbor_max_push_constants.to_byte_array() + neighbor_max_push_constants_byte_array.append_array(int_neighbor_max_push_constants.to_byte_array()) + + var tile_variance_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_tile_variance_push_constants : PackedInt32Array = [ + 0, + 0, + 0, + 0 + ] + var tile_variance_push_constants_byte_array = tile_variance_push_constants.to_byte_array() + tile_variance_push_constants_byte_array.append_array(int_tile_variance_push_constants.to_byte_array()) + + var blur_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0, + ] + var int_blur_push_constants : PackedInt32Array = [ + tile_size, + samples, + Engine.get_frames_drawn() % 8, + 0 + ] + var blur_push_constants_byte_array = blur_push_constants.to_byte_array() + blur_push_constants_byte_array.append_array(int_blur_push_constants.to_byte_array()) + + var view_count = render_scene_buffers.get_view_count() + + for view in range(view_count): + var color_image := render_scene_buffers.get_color_layer(view) + var depth_image := render_scene_buffers.get_depth_layer(view) + var output_color_image := render_scene_buffers.get_texture_slice(context, output_color, view, 0, 1, 1) + var tile_max_x_image := render_scene_buffers.get_texture_slice(context, tile_max_x, view, 0, 1, 1) + var tile_max_image := render_scene_buffers.get_texture_slice(context, tile_max, view, 0, 1, 1) + var neighbor_max_image := render_scene_buffers.get_texture_slice(context, neighbor_max, view, 0, 1, 1) + var tile_variance_image := render_scene_buffers.get_texture_slice(context, tile_variance, view, 0, 1, 1) + var past_color_image := render_scene_buffers.get_texture_slice(context, past_color, view, 0, 1, 1) + var custom_velocity_image := render_scene_buffers.get_texture_slice(context, custom_velocity, view, 0, 1, 1) + + var x_groups := floori((render_size.x / tile_size - 1) / 16 + 1) + var y_groups := floori((render_size.y - 1) / 16 + 1) + + dispatch_stage(tile_max_x_stage, + [ + get_sampler_uniform(custom_velocity_image, 0, false), + get_image_uniform(tile_max_x_image, 1) + ], + tile_max_x_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "TileMaxX", + view) + + x_groups = floori((render_size.x / tile_size - 1) / 16 + 1) + y_groups = floori((render_size.y / tile_size - 1) / 16 + 1) + + dispatch_stage(tile_max_y_stage, + [ + get_sampler_uniform(tile_max_x_image, 0, false), + get_image_uniform(tile_max_image, 1) + ], + tile_max_y_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "TileMaxY", + view) + + dispatch_stage(neighbor_max_stage, + [ + get_sampler_uniform(tile_max_image, 0, false), + get_image_uniform(neighbor_max_image, 1) + ], + neighbor_max_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "NeighborMax", + view) + + dispatch_stage(tile_variance_stage, + [ + get_sampler_uniform(tile_max_image, 0, false), + get_image_uniform(tile_variance_image, 1) + ], + tile_variance_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "TileVariance", + view) + + x_groups = floori((render_size.x - 1) / 16 + 1) + y_groups = floori((render_size.y - 1) / 16 + 1) + + dispatch_stage(blur_stage, + [ + get_sampler_uniform(color_image, 0, false), + get_sampler_uniform(depth_image, 1, false), + get_sampler_uniform(custom_velocity_image, 2, false), + get_sampler_uniform(neighbor_max_image, 3, false), + get_sampler_uniform(tile_variance_image, 4, true), + get_image_uniform(output_color_image, 5), + get_image_uniform(past_color_image, 6) + ], + blur_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "Blur", + view) + + dispatch_stage(overlay_stage, + [ + get_sampler_uniform(output_color_image, 0, false), + get_image_uniform(color_image, 1) + ], + [], + Vector3i(x_groups, y_groups, 1), + "Overlay result", + view) + + rd.draw_command_end_label() diff --git a/addons/SphynxMotionBlurToolkit/McGuire/mcguire_neighbor_max_stage.tres b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_neighbor_max_stage.tres new file mode 100644 index 0000000..126d347 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_neighbor_max_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://bk8tn7n5k0b1r"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_6n3p7"] +[ext_resource type="RDShaderFile" uid="uid://byfogr1qtbafi" path="res://addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_neighbor_max.glsl" id="2_ig0yf"] + +[resource] +script = ExtResource("1_6n3p7") +shader_file = ExtResource("2_ig0yf") diff --git a/addons/SphynxMotionBlurToolkit/McGuire/mcguire_overlay_stage.tres b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_overlay_stage.tres new file mode 100644 index 0000000..681c723 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_overlay_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://chg1vh0sap86j"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_rpgp3"] +[ext_resource type="RDShaderFile" uid="uid://ylkrbqh7unvl" path="res://addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_overlay.glsl" id="2_sx8p0"] + +[resource] +script = ExtResource("1_rpgp3") +shader_file = ExtResource("2_sx8p0") diff --git a/addons/SphynxMotionBlurToolkit/McGuire/mcguire_tile_max_x_stage.tres b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_tile_max_x_stage.tres new file mode 100644 index 0000000..a93d0ef --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_tile_max_x_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://kgrk5sdoor7t"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_50cqr"] +[ext_resource type="RDShaderFile" uid="uid://bp5jl5351ph2d" path="res://addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_x.glsl" id="2_m4c7y"] + +[resource] +script = ExtResource("1_50cqr") +shader_file = ExtResource("2_m4c7y") diff --git a/addons/SphynxMotionBlurToolkit/McGuire/mcguire_tile_max_y_stage.tres b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_tile_max_y_stage.tres new file mode 100644 index 0000000..14bea9e --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_tile_max_y_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://d2rdmkpi41wf1"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_4imrj"] +[ext_resource type="RDShaderFile" uid="uid://deow8m5u2ji84" path="res://addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_y.glsl" id="2_8ewid"] + +[resource] +script = ExtResource("1_4imrj") +shader_file = ExtResource("2_8ewid") diff --git a/addons/SphynxMotionBlurToolkit/McGuire/mcguire_tile_variance_stage.tres b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_tile_variance_stage.tres new file mode 100644 index 0000000..d578417 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_tile_variance_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://d1ckx52l74p0"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_bipj1"] +[ext_resource type="RDShaderFile" uid="uid://ddo60n85uqwbk" path="res://addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_variance.glsl" id="2_5lusy"] + +[resource] +script = ExtResource("1_bipj1") +shader_file = ExtResource("2_5lusy") diff --git a/addons/SphynxMotionBlurToolkit/PreBlurProcessing/Shaders/pre_blur_processor.glsl b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/Shaders/pre_blur_processor.glsl new file mode 100644 index 0000000..9c400f2 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/Shaders/pre_blur_processor.glsl @@ -0,0 +1,204 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D depth_sampler; +layout(set = 0, binding = 1) uniform sampler2D vector_sampler; +layout(rgba32f, set = 0, binding = 2) uniform writeonly image2D vector_output; + +struct SceneData { + highp mat4 projection_matrix; + highp mat4 inv_projection_matrix; + highp mat4 inv_view_matrix; + highp mat4 view_matrix; + + // only used for multiview + highp mat4 projection_matrix_view[2]; + highp mat4 inv_projection_matrix_view[2]; + highp vec4 eye_offset[2]; + + // Used for billboards to cast correct shadows. + highp mat4 main_cam_inv_view_matrix; + + highp vec2 viewport_size; + highp vec2 screen_pixel_size; + + // Use vec4s because std140 doesn't play nice with vec2s, z and w are wasted. + highp vec4 directional_penumbra_shadow_kernel[32]; + highp vec4 directional_soft_shadow_kernel[32]; + highp vec4 penumbra_shadow_kernel[32]; + highp vec4 soft_shadow_kernel[32]; + + mediump mat3 radiance_inverse_xform; + + mediump vec4 ambient_light_color_energy; + + mediump float ambient_color_sky_mix; + bool use_ambient_light; + bool use_ambient_cubemap; + bool use_reflection_cubemap; + + highp vec2 shadow_atlas_pixel_size; + highp vec2 directional_shadow_pixel_size; + + uint directional_light_count; + mediump float dual_paraboloid_side; + highp float z_far; + highp float z_near; + + bool roughness_limiter_enabled; + mediump float roughness_limiter_amount; + mediump float roughness_limiter_limit; + mediump float opaque_prepass_threshold; + + bool fog_enabled; + uint fog_mode; + highp float fog_density; + highp float fog_height; + highp float fog_height_density; + + highp float fog_depth_curve; + highp float pad; + highp float fog_depth_begin; + + mediump vec3 fog_light_color; + highp float fog_depth_end; + + mediump float fog_sun_scatter; + mediump float fog_aerial_perspective; + highp float time; + mediump float reflection_multiplier; // one normally, zero when rendering reflections + + vec2 taa_jitter; + bool material_uv2_mode; + float emissive_exposure_normalization; + + float IBL_exposure_normalization; + bool pancake_shadows; + uint camera_visible_layers; + float pass_alpha_multiplier; +}; + +layout(set = 0, binding = 5, std140) uniform SceneDataBlock { + SceneData data; + SceneData prev_data; +} +scene; + +layout(push_constant, std430) uniform Params +{ + float rotation_velocity_multiplier; + float movement_velocity_multiplier; + float object_velocity_multiplier; + float rotation_velocity_lower_threshold; + float movement_velocity_lower_threshold; + float object_velocity_lower_threshold; + float rotation_velocity_upper_threshold; + float movement_velocity_upper_threshold; + float object_velocity_upper_threshold; + float is_fsr2; + float motion_blur_intensity; + float nan_fl_2; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +float sharp_step(float lower, float upper, float x) +{ + return clamp((x - lower) / (upper - lower), 0, 1); +} + +float get_view_depth(float depth) +{ + return 0.; +} + +void main() +{ + ivec2 render_size = ivec2(textureSize(vector_sampler, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + // must be on pixel center for whole values (tested) + vec2 uvn = vec2(uvi + vec2(0.5)) / render_size; + + SceneData scene_data = scene.data; + + SceneData previous_scene_data = scene.prev_data; + + float depth = textureLod(depth_sampler, uvn, 0.0).x; + + vec4 view_position = inverse(scene_data.projection_matrix) * vec4(uvn * 2.0 - 1.0, depth, 1.0); + + view_position.xyz /= view_position.w; + // get full change + vec4 world_local_position = inverse(scene_data.view_matrix) * vec4(view_position.xyz, 1.0); + + vec4 view_past_position = mat4(previous_scene_data.view_matrix) * vec4(world_local_position.xyz, 1.0); + + vec4 view_past_ndc = previous_scene_data.projection_matrix * view_past_position; + + view_past_ndc.xyz /= view_past_ndc.w; + + vec3 past_uv = vec3(view_past_ndc.xy * 0.5 + 0.5, view_past_ndc.z); + + vec4 view_past_ndc_cache = view_past_ndc; + + vec3 camera_uv_change = past_uv - vec3(uvn, depth); + + // get just rotation change + world_local_position = mat4(mat3(inverse(scene_data.view_matrix))) * vec4(view_position.xyz, 1.0); + + view_past_position = mat4(mat3(previous_scene_data.view_matrix)) * vec4(world_local_position.xyz, 1.0); + + view_past_ndc = previous_scene_data.projection_matrix * view_past_position; + + view_past_ndc.xyz /= view_past_ndc.w; + + past_uv = vec3(view_past_ndc.xy * 0.5 + 0.5, view_past_ndc.z); + + vec3 camera_rotation_uv_change = past_uv - vec3(uvn, depth); + // get just movement change + vec3 camera_movement_uv_change = camera_uv_change - camera_rotation_uv_change; + // fill in gaps in base velocity (skybox, z velocity) + vec3 base_velocity = vec3(textureLod(vector_sampler, uvn, 0.0).xy + mix(vec2(0), camera_uv_change.xy, step(depth, 0.)), camera_uv_change.z); + // fsr just makes it so values are larger than 1, I assume its the only case when it happens + if(params.is_fsr2 > 0.5 && dot(base_velocity.xy, base_velocity.xy) >= 1) + { + base_velocity = camera_uv_change; + } + // get object velocity + vec3 object_uv_change = base_velocity - camera_uv_change.xyz; + // construct final velocity with user defined weights + vec3 total_velocity = camera_rotation_uv_change * params.rotation_velocity_multiplier * sharp_step(params.rotation_velocity_lower_threshold, params.rotation_velocity_upper_threshold, length(camera_rotation_uv_change) * params.rotation_velocity_multiplier * params.motion_blur_intensity) + + camera_movement_uv_change * params.movement_velocity_multiplier * sharp_step(params.movement_velocity_lower_threshold, params.movement_velocity_upper_threshold, length(camera_movement_uv_change) * params.movement_velocity_multiplier * params.motion_blur_intensity) + + object_uv_change * params.object_velocity_multiplier * sharp_step(params.object_velocity_lower_threshold, params.object_velocity_upper_threshold, length(object_uv_change) * params.object_velocity_multiplier * params.motion_blur_intensity); + // if objects move, clear z direction, (z only correct for static environment) + if(dot(object_uv_change.xy, object_uv_change.xy) > 0.000001) + { + total_velocity.z = 0; + base_velocity.z = 0; + } + // choose the smaller option out of the two based on amgnitude, seems to work well + if(dot(total_velocity.xy * 99, total_velocity.xy * 100) >= dot(base_velocity.xy * 100, base_velocity.xy * 100)) + { + total_velocity = base_velocity; + } + + float total_velocity_length = max(FLT_MIN, length(total_velocity)); + total_velocity = total_velocity * clamp(total_velocity_length, 0, 1) / total_velocity_length; + + imageStore(vector_output, uvi, vec4(total_velocity * (view_past_ndc_cache.w < 0 ? -1 : 1), depth));//, depth));// + +#ifdef DEBUG + vec2 velocity = textureLod(vector_sampler, uvn, 0.0).xy; + float velocity_length = length(velocity); + velocity = velocity * clamp(velocity_length, 0, 10) / velocity_length; + imageStore(debug_6_image, uvi, vec4(velocity * (view_past_ndc_cache.w < 0 ? -1 : 1), view_past_ndc_cache.w < 0 ? 1 : 0, 1)); + imageStore(debug_7_image, uvi, vec4(camera_uv_change.xy, 0, 1)); +#endif +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/PreBlurProcessing/Shaders/pre_blur_processor.glsl.import b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/Shaders/pre_blur_processor.glsl.import new file mode 100644 index 0000000..97aacbe --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/Shaders/pre_blur_processor.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://ojudxyx6f4rx" +path="res://.godot/imported/pre_blur_processor.glsl-5b87a82e9bf310f86ebf23e533cacd1d.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/Shaders/pre_blur_processor.glsl" +dest_files=["res://.godot/imported/pre_blur_processor.glsl-5b87a82e9bf310f86ebf23e533cacd1d.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/PreBlurProcessing/blur_velocity_component_resource.gd b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/blur_velocity_component_resource.gd new file mode 100644 index 0000000..524b799 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/blur_velocity_component_resource.gd @@ -0,0 +1,9 @@ +extends Resource +class_name BlurVelocityComponentResource + +## the overal multiplier of the velocity component +@export var multiplier : float = 1.0 +## a lower threshold for the velocity to be blurred +@export var lower_threshold : float = 0.0 +## an upper threshold for the velocity to be blurred +@export var upper_threshold : float = 0.0 diff --git a/addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_camera_movement_component.tres b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_camera_movement_component.tres new file mode 100644 index 0000000..3d06652 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_camera_movement_component.tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" script_class="BlurVelocityComponentResource" load_steps=2 format=3 uid="uid://cslvcweyejh3c"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/blur_velocity_component_resource.gd" id="1_856ea"] + +[resource] +script = ExtResource("1_856ea") +multiplier = 1.0 +lower_threshold = 0.0 +upper_threshold = 0.0 diff --git a/addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_camera_rotation_component.tres b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_camera_rotation_component.tres new file mode 100644 index 0000000..f2f1b05 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_camera_rotation_component.tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" script_class="BlurVelocityComponentResource" load_steps=2 format=3 uid="uid://iru8ynu04i00"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/blur_velocity_component_resource.gd" id="1_j2iku"] + +[resource] +script = ExtResource("1_j2iku") +multiplier = 1.0 +lower_threshold = 0.0 +upper_threshold = 0.0 diff --git a/addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_object_movement_component.tres b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_object_movement_component.tres new file mode 100644 index 0000000..25bcaa1 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_object_movement_component.tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" script_class="BlurVelocityComponentResource" load_steps=2 format=3 uid="uid://rp3mpjmisoyh"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/blur_velocity_component_resource.gd" id="1_ijikr"] + +[resource] +script = ExtResource("1_ijikr") +multiplier = 1.0 +lower_threshold = 0.0 +upper_threshold = 0.0 diff --git a/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processing_stage.tres b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processing_stage.tres new file mode 100644 index 0000000..87811f1 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processing_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://c8ulad7utgrg7"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_8hijg"] +[ext_resource type="RDShaderFile" uid="uid://ojudxyx6f4rx" path="res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/Shaders/pre_blur_processor.glsl" id="2_w54vd"] + +[resource] +script = ExtResource("1_8hijg") +shader_file = ExtResource("2_w54vd") diff --git a/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processor.gd b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processor.gd new file mode 100644 index 0000000..eef06ba --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processor.gd @@ -0,0 +1,91 @@ +extends "res://addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor_effect.gd" +class_name PreBlurProcessor + +@export_group("Shader Stages") +@export var pre_blur_processor_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processing_stage.tres"): + set(value): + unsubscribe_shader_stage(pre_blur_processor_stage) + pre_blur_processor_stage = value + subscirbe_shader_stage(value) + +@export_group("Blur Components") +@export var camera_rotation_component : BlurVelocityComponentResource = preload("res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_camera_rotation_component.tres") +@export var camera_movement_component : BlurVelocityComponentResource = preload("res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_camera_movement_component.tres") +@export var object_movement_component : BlurVelocityComponentResource = preload("res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_object_movement_component.tres") + +var custom_velocity : StringName = "custom_velocity" + +var temp_intensity : float + +var previous_time : float = 0 + +func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSceneBuffersRD, render_scene_data : RenderSceneDataRD): + var time : float = float(Time.get_ticks_msec()) / 1000 + + var delta_time : float = time - previous_time + + previous_time = time + + temp_intensity = intensity + + if framerate_independent: + var capped_frame_time : float = 1 / target_constant_framerate + + if !uncapped_independence: + capped_frame_time = min(capped_frame_time, delta_time) + + temp_intensity = intensity * capped_frame_time / delta_time + + ensure_texture(custom_velocity, render_scene_buffers) + + rd.draw_command_begin_label("Pre Blur Processing", Color(1.0, 1.0, 1.0, 1.0)) + + var float_pre_blur_push_constants: PackedFloat32Array = [ + camera_rotation_component.multiplier, + camera_movement_component.multiplier, + object_movement_component.multiplier, + camera_rotation_component.lower_threshold, + camera_movement_component.lower_threshold, + object_movement_component.lower_threshold, + camera_rotation_component.upper_threshold, + camera_movement_component.upper_threshold, + object_movement_component.upper_threshold, + 1 if true else 0, + temp_intensity, + 0, + ] + + var int_pre_blur_push_constants : PackedInt32Array = [ + ] + + var byte_array = float_pre_blur_push_constants.to_byte_array() + byte_array.append_array(int_pre_blur_push_constants.to_byte_array()) + + var view_count = render_scene_buffers.get_view_count() + + for view in range(view_count): + var depth_image := render_scene_buffers.get_depth_layer(view) + var velocity_image := render_scene_buffers.get_velocity_layer(view) + var custom_velocity_image := render_scene_buffers.get_texture_slice(context, custom_velocity, view, 0, 1, 1) + var scene_data_buffer : RID = render_scene_data.get_uniform_buffer() + var scene_data_buffer_uniform := RDUniform.new() + scene_data_buffer_uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_UNIFORM_BUFFER + scene_data_buffer_uniform.binding = 5 + scene_data_buffer_uniform.add_id(scene_data_buffer) + + var x_groups := floori((render_size.x - 1) / 16 + 1) + var y_groups := floori((render_size.y - 1) / 16 + 1) + + dispatch_stage(pre_blur_processor_stage, + [ + get_sampler_uniform(depth_image, 0, false), + get_sampler_uniform(velocity_image, 1, false), + get_image_uniform(custom_velocity_image, 2), + scene_data_buffer_uniform + ], + byte_array, + Vector3i(x_groups, y_groups, 1), + "Process Velocity Buffer", + view) + + rd.draw_command_end_label() diff --git a/addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.gd b/addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.gd new file mode 100644 index 0000000..25fe78d --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.gd @@ -0,0 +1,118 @@ +extends MeshInstance3D +class_name RadialBlurMesh + +@export var target_node : Node3D + +## the rotation vector the current mesh blur's around +## locally +@export_enum("x", "y", "z") var local_rotation_axis : int + +@export var negate_local_rotation_axis : bool = false + +## the rotation vector that the target mesh spins along locally +@export_enum("x", "y", "z") var target_local_rotation_axis : int + +@export var negate_target_local_rotation_axis : bool = false + +## At what speed does the mesh become visible and start blurring +@export var speed_visibility_threshold : float = 0.2 + +## make mesh visible for debugging +@export var show_debug : bool = false + +@onready var local_rotation_vector : Vector3 = Vector3(1 if local_rotation_axis == 0 else 0, 1 if local_rotation_axis == 1 else 0, 1 if local_rotation_axis == 2 else 0) * (1 if !negate_local_rotation_axis else -1) + +@onready var target_local_rotation_vector : Vector3 = Vector3(1 if target_local_rotation_axis == 0 else 0, 1 if target_local_rotation_axis == 1 else 0, 1 if target_local_rotation_axis == 2 else 0) * (1 if !negate_target_local_rotation_axis else -1) + +var mesh_last_rotation : float = 0; + +var previous_mesh_basis : Basis = Basis() + +var mesh_has_rotation_signal : bool = false + +var signal_rotation_velocity : float = 0 + +var debug_toggle : float = 0 + +var axis_offset : float + +var shape_radius : float = 0 + +var shape_depth : float = 0 + +var shape_axis_offset : float = 0 + +func _ready(): + get_surface_override_material(0).set_shader_parameter("debug_color", Color(0, 0, 0, 0) if !show_debug else Color(1, 0, 0, 0)) + + previous_mesh_basis = target_node.global_basis + + var target_rotation_vector : Vector3 = previous_mesh_basis.orthonormalized() * target_local_rotation_vector + + axis_offset = target_rotation_vector.dot(global_position - target_node.global_position) + + var mesh_aabb : AABB = mesh.get_aabb() + + var extent : Vector3 = mesh_aabb.size * global_basis.get_scale() + + var all_axis : Array[float] = [extent.x, extent.y, extent.z] + + var center : Vector3 = mesh_aabb.get_center() * global_basis.get_scale() + + var all_centers : Array[float] = [center.x, center.y, center.z] + + shape_depth = all_axis[local_rotation_axis] + + shape_axis_offset = all_centers[local_rotation_axis] * (1 if !negate_local_rotation_axis else -1) + + shape_radius = 0 + + for i in all_axis.size(): + if i == local_rotation_axis: + continue + shape_radius = max(shape_radius, all_axis[i] / 2) + + #print(name, "has the shape depth of ", shape_depth, ", radius of ", shape_radius, " and axis offset of ", shape_axis_offset) + + if target_node.has_signal("rotation_velocity_signal"): + mesh_has_rotation_signal = true + target_node.rotation_velocity_signal.connect(on_rotation_velocity_signal) + + deferred_update_cylinder_data.call_deferred() + +func on_rotation_velocity_signal(velocity : float): + signal_rotation_velocity = velocity + +func deferred_update_cylinder_data(): + get_surface_override_material(0).set_shader_parameter("shape_depth", shape_depth) + get_surface_override_material(0).set_shader_parameter("shape_radius", shape_radius) + get_surface_override_material(0).set_shader_parameter("shape_axis_offset", shape_axis_offset) + get_surface_override_material(0).set_shader_parameter("local_rotation_axis", local_rotation_vector) + +func _process(delta: float) -> void: + var target_transform : Transform3D = target_node.global_transform + + var target_rotation_vector : Vector3 = target_transform.orthonormalized().basis * target_local_rotation_vector + + var current_mesh_basis : Basis = target_transform.basis + + var difference_quat : Quaternion = Quaternion(current_mesh_basis.get_rotation_quaternion() * previous_mesh_basis.get_rotation_quaternion().inverse()) + + var centered_angle : float = difference_quat.get_angle() - PI + + var angle = (PI - abs(centered_angle)) * abs(target_rotation_vector.dot(difference_quat.get_axis())) + + if mesh_has_rotation_signal: + angle = signal_rotation_velocity + + visible = abs(angle) > speed_visibility_threshold + + get_surface_override_material(0).set_shader_parameter("rotation_speed", clamp(angle, -TAU, TAU)) + + previous_mesh_basis = current_mesh_basis + + global_position = target_transform.origin + target_rotation_vector * axis_offset + + var alignment_quaternion : Quaternion = Quaternion(global_basis.orthonormalized() * local_rotation_vector, target_rotation_vector) + + global_basis = Basis(alignment_quaternion) * global_basis; diff --git a/addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.gdshader b/addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.gdshader new file mode 100644 index 0000000..acfdb05 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.gdshader @@ -0,0 +1,219 @@ +shader_type spatial; + +render_mode unshaded, depth_draw_always, fog_disabled; + +uniform sampler2D screen_texture : hint_screen_texture, filter_nearest; +uniform sampler2D depth_texture : hint_depth_texture, filter_nearest; + +uniform vec3 local_rotation_axis = vec3(0, 1, 0); + +uniform float rotation_speed = 0; + +uniform int sample_count = 8; + +uniform float shape_depth = 1; + +uniform float shape_radius = 1; + +uniform float shape_axis_offset = 0; + +uniform float debug_toggle = 0; + +uniform vec4 debug_color : source_color = vec4(0); + +//https://www.shadertoy.com/view/fdtfWM +vec3 rotate(float angle, vec3 axis, vec3 point) // NOTE: axis must be unit! +{ + float c = cos(angle); + float s = sin(angle); + return c * point + s * cross(axis, point) + (1.0 - c) * (dot(point, axis) * axis); // Rodrigues' Rotation Formula +} + +// from https://www.shadertoy.com/view/ftKfzc +float interleaved_gradient_noise(vec2 uv, int FrameId){ + uv += float(FrameId) * (vec2(47, 17) * 0.695); + + vec3 magic = vec3( 0.06711056, 0.00583715, 52.9829189 ); + + return fract(magic.z * fract(dot(uv, magic.xy))); +} + +vec3 get_projection_onto_plane(vec3 plane_origin, vec3 normal, vec3 vector) +{ + float plane_distance = dot(plane_origin, normal); + return vector * plane_distance / dot(normal, vector); +} + +float soft_depth_compare(float x, float y, float sze) +{ + return clamp(1. - (x - y) / sze, 0., 1.); +} + +vec2 intersect_cylinder(vec3 eye_point, vec3 end_point, vec3 origin, vec3 axis, float radius) +{ + eye_point -= axis * dot(eye_point - origin, axis) + origin; + + end_point -= axis * dot(end_point - origin, axis) + origin; + + vec3 direction = end_point - eye_point; + + float A = dot(direction, direction); + float B = 2. * dot(eye_point, direction); + float C = dot(eye_point, eye_point) - radius * radius; + + float square_component = sqrt(B * B - 4. * A * C); + + return vec2(-B + square_component, -B - square_component) / (2. * A); +} + +vec2 within_cylinder(vec3 point, vec3 origin, vec3 axis, float radius, float depth, float axis_offset) +{ + float within_depth = step(abs(dot(point - origin - axis * axis_offset, axis)), depth / 2.); + vec3 perpendicular_component = point - axis * dot(axis, point - origin) - origin; + float within_radius = step(dot(perpendicular_component, perpendicular_component), radius * radius); + + return vec2(within_depth * within_radius, step(0, dot(point - origin, axis))); +} + +vec3 color_corrected(vec3 color) +{ + return color / mix( + pow((vec3(1.) + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), + vec3(1.) * (1.0 / 12.92), + lessThan(vec3(1.), vec3(0.04045))); +} + +void fragment() { + vec2 screen_uv = SCREEN_UV; + + float depth = texture(depth_texture, screen_uv).x; + vec3 ndc = vec3(screen_uv * 2.0 - 1.0, depth); + vec4 world_position = INV_VIEW_MATRIX * INV_PROJECTION_MATRIX * vec4(ndc, 1.0); + world_position.xyz /= world_position.w; + + vec4 world_mesh_position = INV_VIEW_MATRIX * INV_PROJECTION_MATRIX * vec4(screen_uv * 2.0 - 1.0, FRAGCOORD.z, 1.0); + world_mesh_position.xyz /= world_mesh_position.w; + + vec3 node_relative_position = world_position.xyz - NODE_POSITION_WORLD; + + vec3 world_rotation_axis = normalize(mat3(MODEL_MATRIX) * local_rotation_axis); + + float axis_parallel_offset = dot(node_relative_position, world_rotation_axis); + + vec3 axis_parallel_component = axis_parallel_offset * world_rotation_axis; + + vec3 axis_perpendicular_component = node_relative_position - axis_parallel_component; + + float axis_perpendicular_offset = length(axis_perpendicular_component); + + vec3 camera_node_position = NODE_POSITION_WORLD - CAMERA_POSITION_WORLD; + + vec3 camera_cylinder_back_plane_origin = camera_node_position + world_rotation_axis * (clamp(axis_parallel_offset - shape_axis_offset, -shape_depth / 2., shape_depth / 2.) + shape_axis_offset); + + vec3 camera_relative_position = world_position.xyz - CAMERA_POSITION_WORLD; + + vec3 camera_plane_projected_results = get_projection_onto_plane(camera_cylinder_back_plane_origin, world_rotation_axis, camera_relative_position); + + vec2 world_cylinder_intersect_result = intersect_cylinder(CAMERA_POSITION_WORLD, camera_plane_projected_results + CAMERA_POSITION_WORLD, NODE_POSITION_WORLD, world_rotation_axis, shape_radius); + + float lands_within_cylinder = step(1, world_cylinder_intersect_result.x); + + camera_plane_projected_results *= mix(world_cylinder_intersect_result.x, 1, lands_within_cylinder); + + vec3 node_cylinder_clamped_result = camera_plane_projected_results - camera_node_position; + + float on_mesh = 1.; + + vec3 raw_clamed_difference = node_cylinder_clamped_result - node_relative_position; + + if(dot(raw_clamed_difference, raw_clamed_difference) > 0.001) + { + node_relative_position = world_mesh_position.xyz - NODE_POSITION_WORLD; + on_mesh = 0.; + } + + float noise_variation = interleaved_gradient_noise(SCREEN_UV * vec2(textureSize(screen_texture, 0)), int(TIME * 100.)) / float(sample_count); + + float sum = 1.; + + vec4 base_sample = texture(screen_texture, screen_uv); + + vec4 col = base_sample; + + vec2 nearest_ahead_of_mesh_uv = screen_uv; + + float nearest_ahead_of_mesh_set = 0.; + + vec2 past_mesh_uv_found = screen_uv; + + float was_mesh_uv_found = 0.; + + vec3 camera_relative_position_normalized = normalize(node_relative_position.xyz + camera_node_position); + + for(int i = 0; i < sample_count; i++) + { + float angle = (float(i) / float(sample_count) + noise_variation) * rotation_speed; + + vec3 node_rotated_sample = rotate(-angle, world_rotation_axis.xyz, node_relative_position.xyz); + + vec4 current_ndc = (PROJECTION_MATRIX * VIEW_MATRIX * (vec4(node_rotated_sample, 1) + vec4(NODE_POSITION_WORLD, 0))); + + current_ndc.xyz /= current_ndc.w; + + vec2 current_uv_sample = ((current_ndc + 1.) / 2.).xy ; + + float current_depth = texture(depth_texture, current_uv_sample).x; + + vec4 current_world_position = INV_VIEW_MATRIX * INV_PROJECTION_MATRIX * vec4(vec3(current_ndc.xy, current_depth), 1.0); + + current_world_position.xyz /= current_world_position.w; + + vec3 current_camera_unrotated_position = rotate(angle, world_rotation_axis.xyz, current_world_position.xyz - NODE_POSITION_WORLD) + camera_node_position; + + vec3 current_unrotated_perpendicular_component = current_camera_unrotated_position - camera_relative_position_normalized * dot(current_camera_unrotated_position, camera_relative_position_normalized); + + float current_unrotated_perpendicular_offset = length(current_unrotated_perpendicular_component); + + current_depth = 0.05 / current_depth; + + float current_sample_depth = 0.05 / current_ndc.z; + + vec2 current_sample_inside_cylinder = within_cylinder(current_world_position.xyz, NODE_POSITION_WORLD, world_rotation_axis, shape_radius, shape_depth, shape_axis_offset); + + float occluding_mesh = soft_depth_compare(current_depth + 0.1, current_sample_depth, 0.1) * (1. - current_sample_inside_cylinder.x); + + float choose_best_uv = on_mesh * (1. - current_sample_inside_cylinder.x); + + current_uv_sample = mix(screen_uv, current_uv_sample, 1. - (1. - current_sample_inside_cylinder.x) * (1. - on_mesh)); + + current_uv_sample = mix(current_uv_sample, past_mesh_uv_found, occluding_mesh); + + current_uv_sample = mix(current_uv_sample, nearest_ahead_of_mesh_uv, nearest_ahead_of_mesh_set * choose_best_uv); + + if (current_uv_sample.x < 0. || current_uv_sample.x > 1. || current_uv_sample.y < 0. || current_uv_sample.y > 1.) + { + continue; + } + + nearest_ahead_of_mesh_uv = mix(nearest_ahead_of_mesh_uv, current_uv_sample, (1. - nearest_ahead_of_mesh_set) * choose_best_uv); + + nearest_ahead_of_mesh_set = mix(nearest_ahead_of_mesh_set, 1., (1. - nearest_ahead_of_mesh_set) * choose_best_uv); + + past_mesh_uv_found = mix(current_uv_sample, past_mesh_uv_found, current_sample_inside_cylinder.x); + + was_mesh_uv_found = mix(1, was_mesh_uv_found, current_sample_inside_cylinder.x); + + float unrotated_sample_within_perpendicular_range = step(current_unrotated_perpendicular_offset, 0.1); + + float on_mesh_in_front = on_mesh * (1. - soft_depth_compare(current_sample_depth - 0.02, current_depth, 0.01)) * (1. - unrotated_sample_within_perpendicular_range); + + float weight = 1. - on_mesh_in_front * (1. - debug_toggle); + //weight = 1. - (1. - was_mesh_uv_found) * (occluding_mesh); + sum += weight; + col += texture(screen_texture, current_uv_sample) * weight; + } + + col /= sum; + + ALBEDO = col.xyz + debug_color.xyz;//vec3(depth * 10.);// +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.tscn b/addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.tscn new file mode 100644 index 0000000..0bf0585 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.tscn @@ -0,0 +1,27 @@ +[gd_scene load_steps=5 format=3 uid="uid://8p6li7o742g3"] + +[ext_resource type="Shader" path="res://addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.gdshader" id="1_36vys"] +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.gd" id="2_cfhks"] + +[sub_resource type="CylinderMesh" id="CylinderMesh_pgvyt"] +resource_local_to_scene = true +height = 0.25 + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_stapv"] +resource_local_to_scene = true +render_priority = 0 +shader = ExtResource("1_36vys") +shader_parameter/local_rotation_axis = Vector3(0, 1, 0) +shader_parameter/rotation_speed = 0.0 +shader_parameter/sample_count = 8 +shader_parameter/shape_depth = 1.0 +shader_parameter/shape_radius = 1.0 +shader_parameter/shape_axis_offset = 0.0 +shader_parameter/debug_toggle = 0.0 +shader_parameter/debug_color = Color(1, 0, 0, 0) + +[node name="RadialBlurMesh" type="MeshInstance3D"] +process_priority = 1 +mesh = SubResource("CylinderMesh_pgvyt") +surface_material_override/0 = SubResource("ShaderMaterial_stapv") +script = ExtResource("2_cfhks") diff --git a/addons/SphynxMotionBlurToolkit/SphynxMotionBlurToolkit.gd b/addons/SphynxMotionBlurToolkit/SphynxMotionBlurToolkit.gd new file mode 100644 index 0000000..aa1b8e0 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/SphynxMotionBlurToolkit.gd @@ -0,0 +1,12 @@ +@tool +extends EditorPlugin + + +func _enter_tree() -> void: + # Initialization of the plugin goes here. + pass + + +func _exit_tree() -> void: + # Clean-up of the plugin goes here. + pass diff --git a/addons/SphynxMotionBlurToolkit/plugin.cfg b/addons/SphynxMotionBlurToolkit/plugin.cfg new file mode 100644 index 0000000..bf53cf0 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/plugin.cfg @@ -0,0 +1,7 @@ +[plugin] + +name="SphynxMotionBlurToolkit" +description="A toolkit containinp multiple motion blur implementations, as well as debug stages, and radial blur toolkit for propellers and wheels" +author="Sphynx" +version="4.3" +script="SphynxMotionBlurToolkit.gd" diff --git a/addons/rokojori_action_library b/addons/rokojori_action_library new file mode 160000 index 0000000..5c4afd2 --- /dev/null +++ b/addons/rokojori_action_library @@ -0,0 +1 @@ +Subproject commit 5c4afd2dfe53f94916b26426ee02c06137201eeb diff --git a/project.godot b/project.godot index 0268e28..35c0be1 100644 --- a/project.godot +++ b/project.godot @@ -11,9 +11,26 @@ config_version=5 [application] config/name="Rokojori Action Library Examples" -config/features=PackedStringArray("4.3", "Forward Plus") +config/features=PackedStringArray("4.3", "C#", "Forward Plus") config/icon="res://icon.svg" +[autoload] + +Root="*res://addons/rokojori_action_library/Runtime/Godot/Root.cs" + [dotnet] project/assembly_name="Rokojori Action Library Examples" + +[editor_plugins] + +enabled=PackedStringArray("res://addons/SphynxMotionBlurToolkit/plugin.cfg", "res://addons/rokojori_action_library/plugin.cfg") + +[rendering] + +lights_and_shadows/directional_shadow/soft_shadow_filter_quality=5 +lights_and_shadows/positional_shadow/soft_shadow_filter_quality=5 +anti_aliasing/quality/msaa_2d=3 +anti_aliasing/quality/msaa_3d=3 +anti_aliasing/quality/screen_space_aa=1 +anti_aliasing/quality/use_debanding=true