diff --git a/compute/post_shader/icon.svg.import b/compute/post_shader/icon.svg.import index acb9daf3..34f0599a 100644 --- a/compute/post_shader/icon.svg.import +++ b/compute/post_shader/icon.svg.import @@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.cte compress/mode=0 compress/high_quality=false compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 compress/hdr_compression=1 compress/normal_map=0 compress/channel_pack=0 @@ -25,6 +27,10 @@ mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 process/fix_alpha_border=true process/premult_alpha=false process/normal_map_invert_y=false diff --git a/compute/post_shader/main.gd b/compute/post_shader/main.gd index 27f333b3..5a39b20a 100644 --- a/compute/post_shader/main.gd +++ b/compute/post_shader/main.gd @@ -20,4 +20,3 @@ Shader effect: %s "Enabled" if compositor.compositor_effects[0].enabled else "Disabled", "Enabled" if compositor.compositor_effects[1].enabled else "Disabled", ] - diff --git a/compute/post_shader/main.tscn b/compute/post_shader/main.tscn index c48445be..dd453be2 100644 --- a/compute/post_shader/main.tscn +++ b/compute/post_shader/main.tscn @@ -35,8 +35,13 @@ effect_callback_type = 4 needs_motion_vectors = false needs_normal_roughness = false script = ExtResource("1_rkpno") -shader_code = " // Invert color. - color.rgb = vec3(1.0 - color.r, 1.0 - color.g, 1.0 - color.b); +shader_code = "// Unproject +vec4 unproj = vec4(uv_norm * 2.0 - 1.0, depth, 1.0); +mat4 inv_projection_matrix = scene_data_block.data.inv_projection_matrix_view[view]; +vec4 vertex = inv_projection_matrix * unproj; +vertex.xyz = vertex.xyz / vertex.w; + +color.rgb = clamp(vec3(vertex.x/20.0, vertex.y/20.0, -vertex.z/20.0), 0.0, 1.0); " [sub_resource type="Compositor" id="Compositor_xxhi4"] diff --git a/compute/post_shader/pattern.png.import b/compute/post_shader/pattern.png.import index 65c3b4c9..ad497db4 100644 --- a/compute/post_shader/pattern.png.import +++ b/compute/post_shader/pattern.png.import @@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/pattern.png-888ea151ee9fa7a079d3252596260765. compress/mode=0 compress/high_quality=false compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 compress/hdr_compression=1 compress/normal_map=0 compress/channel_pack=0 @@ -25,6 +27,10 @@ mipmaps/generate=true mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 process/fix_alpha_border=true process/premult_alpha=false process/normal_map_invert_y=false diff --git a/compute/post_shader/post_process_shader.gd b/compute/post_shader/post_process_shader.gd index d4395823..0e4e4f51 100644 --- a/compute/post_shader/post_process_shader.gd +++ b/compute/post_shader/post_process_shader.gd @@ -2,30 +2,46 @@ class_name PostProcessShader extends CompositorEffect -const template_shader := """#version 450 +const TEMPLATE_SHADER: String = """#version 450 + +#define MAX_VIEWS 2 + +#include "godot/scene_data_inc.glsl" // Invocations in the (x, y, z) dimension. layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; -layout(rgba16f, set = 0, binding = 0) uniform image2D color_image; +layout(set = 0, binding = 0, std140) uniform SceneDataBlock { + SceneData data; + SceneData prev_data; +} +scene_data_block; + +layout(rgba16f, set = 0, binding = 1) uniform image2D color_image; +layout(set = 0, binding = 2) uniform sampler2D depth_texture; // Our push constant. // Must be aligned to 16 bytes, just like the push constant we passed from the script. layout(push_constant, std430) uniform Params { vec2 raster_size; - vec2 pad; + float view; + float pad; } params; // The code we want to execute in each invocation. void main() { ivec2 uv = ivec2(gl_GlobalInvocationID.xy); ivec2 size = ivec2(params.raster_size); + int view = int(params.view); if (uv.x >= size.x || uv.y >= size.y) { return; } + vec2 uv_norm = vec2(uv) / params.raster_size; + vec4 color = imageLoad(color_image, uv); + float depth = texture(depth_texture, uv_norm).r; #COMPUTE_CODE @@ -42,9 +58,10 @@ void main() { var rd: RenderingDevice var shader: RID var pipeline: RID +var nearest_sampler: RID var mutex := Mutex.new() -var shader_is_dirty := true +var shader_is_dirty: bool = true func _init() -> void: @@ -58,7 +75,9 @@ func _notification(what: int) -> void: if what == NOTIFICATION_PREDELETE: if shader.is_valid(): # Freeing our shader will also free any dependents such as the pipeline! - rd.free_rid(shader) + RenderingServer.free_rid(shader) + if nearest_sampler.is_valid(): + rd.free_rid(nearest_sampler) #region Code in this region runs on the rendering thread. @@ -67,7 +86,7 @@ func _check_shader() -> bool: if not rd: return false - var new_shader_code := "" + var new_shader_code: String = "" # Check if our shader is dirty. mutex.lock() @@ -81,7 +100,7 @@ func _check_shader() -> bool: return pipeline.is_valid() # Apply template. - new_shader_code = template_shader.replace("#COMPUTE_CODE", new_shader_code); + new_shader_code = TEMPLATE_SHADER.replace("#COMPUTE_CODE", new_shader_code); # Out with the old. if shader.is_valid(): @@ -93,7 +112,7 @@ func _check_shader() -> bool: var shader_source := RDShaderSource.new() shader_source.language = RenderingDevice.SHADER_LANGUAGE_GLSL shader_source.source_compute = new_shader_code - var shader_spirv : RDShaderSPIRV = rd.shader_compile_spirv_from_source(shader_source) + var shader_spirv: RDShaderSPIRV = rd.shader_compile_spirv_from_source(shader_source) if shader_spirv.compile_error_compute != "": push_error(shader_spirv.compile_error_compute) @@ -114,8 +133,9 @@ func _render_callback(p_effect_callback_type: EffectCallbackType, p_render_data: if rd and p_effect_callback_type == EFFECT_CALLBACK_TYPE_POST_TRANSPARENT and _check_shader(): # Get our render scene buffers object, this gives us access to our render buffers. # Note that implementation differs per renderer hence the need for the cast. - var render_scene_buffers := p_render_data.get_render_scene_buffers() - if render_scene_buffers: + var render_scene_buffers: RenderSceneBuffers = p_render_data.get_render_scene_buffers() + var scene_data: RenderSceneData = p_render_data.get_render_scene_data() + if render_scene_buffers and scene_data: # Get our render size, this is the 3D render resolution! var size: Vector2i = render_scene_buffers.get_internal_size() if size.x == 0 and size.y == 0: @@ -123,10 +143,10 @@ func _render_callback(p_effect_callback_type: EffectCallbackType, p_render_data: # We can use a compute shader here. @warning_ignore("integer_division") - var x_groups := (size.x - 1) / 8 + 1 + var x_groups: int = (size.x - 1) / 8 + 1 @warning_ignore("integer_division") - var y_groups := (size.y - 1) / 8 + 1 - var z_groups := 1 + var y_groups: int = (size.y - 1) / 8 + 1 + var z_groups: int = 1 # Create push constant. # Must be aligned to 16 bytes and be in the same order as defined in the shader. @@ -137,23 +157,48 @@ func _render_callback(p_effect_callback_type: EffectCallbackType, p_render_data: 0.0, ]) + # Make sure we have a sampler. + if not nearest_sampler.is_valid(): + var sampler_state: RDSamplerState = RDSamplerState.new() + sampler_state.min_filter = RenderingDevice.SAMPLER_FILTER_NEAREST + sampler_state.mag_filter = RenderingDevice.SAMPLER_FILTER_NEAREST + nearest_sampler = rd.sampler_create(sampler_state) + # Loop through views just in case we're doing stereo rendering. No extra cost if this is mono. var view_count: int = render_scene_buffers.get_view_count() for view in view_count: + # Get the RID for our scene data buffer. + var scene_data_buffers: RID = scene_data.get_uniform_buffer() + # Get the RID for our color image, we will be reading from and writing to it. - var input_image: RID = render_scene_buffers.get_color_layer(view) + var color_image: RID = render_scene_buffers.get_color_layer(view) + + # Get the RID for our depth image, we will be reading from it. + var depth_image: RID = render_scene_buffers.get_depth_layer(view) # Create a uniform set, this will be cached, the cache will be cleared if our viewports configuration is changed. - var uniform := RDUniform.new() - uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_IMAGE - uniform.binding = 0 - uniform.add_id(input_image) - var uniform_set := UniformSetCacheRD.get_cache(shader, 0, [uniform]) + var scene_data_uniform := RDUniform.new() + scene_data_uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_UNIFORM_BUFFER + scene_data_uniform.binding = 0 + scene_data_uniform.add_id(scene_data_buffers) + var color_uniform := RDUniform.new() + color_uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_IMAGE + color_uniform.binding = 1 + color_uniform.add_id(color_image) + var depth_uniform := RDUniform.new() + depth_uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_SAMPLER_WITH_TEXTURE + depth_uniform.binding = 2 + depth_uniform.add_id(nearest_sampler) + depth_uniform.add_id(depth_image) + var uniform_set_rid: RID = UniformSetCacheRD.get_cache(shader, 0, [scene_data_uniform, color_uniform, depth_uniform]) + + # Set our view. + push_constant[2] = view # Run our compute shader. - var compute_list := rd.compute_list_begin() + var compute_list: int = rd.compute_list_begin() rd.compute_list_bind_compute_pipeline(compute_list, pipeline) - rd.compute_list_bind_uniform_set(compute_list, uniform_set, 0) + rd.compute_list_bind_uniform_set(compute_list, uniform_set_rid, 0) rd.compute_list_set_push_constant(compute_list, push_constant.to_byte_array(), push_constant.size() * 4) rd.compute_list_dispatch(compute_list, x_groups, y_groups, z_groups) rd.compute_list_end() diff --git a/compute/post_shader/project.godot b/compute/post_shader/project.godot index a1e2faf4..effd62de 100644 --- a/compute/post_shader/project.godot +++ b/compute/post_shader/project.godot @@ -12,7 +12,7 @@ config_version=5 config/name="Compositor Effects (Post-Processing)" run/main_scene="res://main.tscn" -config/features=PackedStringArray("4.4", "Forward Plus") +config/features=PackedStringArray("4.5", "Forward Plus") config/icon="res://icon.svg" [debug] @@ -28,12 +28,12 @@ window/stretch/aspect="expand" toggle_grayscale_effect={ "deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":71,"physical_keycode":0,"key_label":0,"unicode":103,"location":0,"echo":false,"script":null) +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":71,"key_label":0,"unicode":103,"location":0,"echo":false,"script":null) ] } toggle_shader_effect={ "deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":83,"physical_keycode":0,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null) +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null) ] }