22class_name PostProcessShader
33extends CompositorEffect
44
5- const template_shader := """#version 450
5+ const TEMPLATE_SHADER : String = """#version 450
6+
7+ #define MAX_VIEWS 2
8+
9+ #include "godot/scene_data_inc.glsl"
610
711// Invocations in the (x, y, z) dimension.
812layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
913
10- layout(rgba16f, set = 0, binding = 0) uniform image2D color_image;
14+ layout(set = 0, binding = 0, std140) uniform SceneDataBlock {
15+ SceneData data;
16+ SceneData prev_data;
17+ }
18+ scene_data_block;
19+
20+ layout(rgba16f, set = 0, binding = 1) uniform image2D color_image;
21+ layout(set = 0, binding = 2) uniform sampler2D depth_texture;
1122
1223// Our push constant.
1324// Must be aligned to 16 bytes, just like the push constant we passed from the script.
1425layout(push_constant, std430) uniform Params {
1526 vec2 raster_size;
16- vec2 pad;
27+ float view;
28+ float pad;
1729} params;
1830
1931// The code we want to execute in each invocation.
2032void main() {
2133 ivec2 uv = ivec2(gl_GlobalInvocationID.xy);
2234 ivec2 size = ivec2(params.raster_size);
35+ int view = int(params.view);
2336
2437 if (uv.x >= size.x || uv.y >= size.y) {
2538 return;
2639 }
2740
41+ vec2 uv_norm = vec2(uv) / params.raster_size;
42+
2843 vec4 color = imageLoad(color_image, uv);
44+ float depth = texture(depth_texture, uv_norm).r;
2945
3046 #COMPUTE_CODE
3147
@@ -42,9 +58,10 @@ void main() {
4258var rd : RenderingDevice
4359var shader : RID
4460var pipeline : RID
61+ var nearest_sampler : RID
4562
4663var mutex := Mutex .new ()
47- var shader_is_dirty : = true
64+ var shader_is_dirty : bool = true
4865
4966
5067func _init () -> void :
@@ -58,7 +75,9 @@ func _notification(what: int) -> void:
5875 if what == NOTIFICATION_PREDELETE :
5976 if shader .is_valid ():
6077 # Freeing our shader will also free any dependents such as the pipeline!
61- rd .free_rid (shader )
78+ RenderingServer .free_rid (shader )
79+ if nearest_sampler .is_valid ():
80+ rd .free_rid (nearest_sampler )
6281
6382
6483#region Code in this region runs on the rendering thread.
@@ -67,7 +86,7 @@ func _check_shader() -> bool:
6786 if not rd :
6887 return false
6988
70- var new_shader_code : = ""
89+ var new_shader_code : String = ""
7190
7291 # Check if our shader is dirty.
7392 mutex .lock ()
@@ -81,7 +100,7 @@ func _check_shader() -> bool:
81100 return pipeline .is_valid ()
82101
83102 # Apply template.
84- new_shader_code = template_shader .replace ("#COMPUTE_CODE" , new_shader_code );
103+ new_shader_code = TEMPLATE_SHADER .replace ("#COMPUTE_CODE" , new_shader_code );
85104
86105 # Out with the old.
87106 if shader .is_valid ():
@@ -93,7 +112,7 @@ func _check_shader() -> bool:
93112 var shader_source := RDShaderSource .new ()
94113 shader_source .language = RenderingDevice .SHADER_LANGUAGE_GLSL
95114 shader_source .source_compute = new_shader_code
96- var shader_spirv : RDShaderSPIRV = rd .shader_compile_spirv_from_source (shader_source )
115+ var shader_spirv : RDShaderSPIRV = rd .shader_compile_spirv_from_source (shader_source )
97116
98117 if shader_spirv .compile_error_compute != "" :
99118 push_error (shader_spirv .compile_error_compute )
@@ -114,19 +133,20 @@ func _render_callback(p_effect_callback_type: EffectCallbackType, p_render_data:
114133 if rd and p_effect_callback_type == EFFECT_CALLBACK_TYPE_POST_TRANSPARENT and _check_shader ():
115134 # Get our render scene buffers object, this gives us access to our render buffers.
116135 # Note that implementation differs per renderer hence the need for the cast.
117- var render_scene_buffers := p_render_data .get_render_scene_buffers ()
118- if render_scene_buffers :
136+ var render_scene_buffers : RenderSceneBuffers = p_render_data .get_render_scene_buffers ()
137+ var scene_data : RenderSceneData = p_render_data .get_render_scene_data ()
138+ if render_scene_buffers and scene_data :
119139 # Get our render size, this is the 3D render resolution!
120140 var size : Vector2i = render_scene_buffers .get_internal_size ()
121141 if size .x == 0 and size .y == 0 :
122142 return
123143
124144 # We can use a compute shader here.
125145 @warning_ignore ("integer_division" )
126- var x_groups : = (size .x - 1 ) / 8 + 1
146+ var x_groups : int = (size .x - 1 ) / 8 + 1
127147 @warning_ignore ("integer_division" )
128- var y_groups : = (size .y - 1 ) / 8 + 1
129- var z_groups : = 1
148+ var y_groups : int = (size .y - 1 ) / 8 + 1
149+ var z_groups : int = 1
130150
131151 # Create push constant.
132152 # 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:
137157 0.0 ,
138158 ])
139159
160+ # Make sure we have a sampler.
161+ if not nearest_sampler .is_valid ():
162+ var sampler_state : RDSamplerState = RDSamplerState .new ()
163+ sampler_state .min_filter = RenderingDevice .SAMPLER_FILTER_NEAREST
164+ sampler_state .mag_filter = RenderingDevice .SAMPLER_FILTER_NEAREST
165+ nearest_sampler = rd .sampler_create (sampler_state )
166+
140167 # Loop through views just in case we're doing stereo rendering. No extra cost if this is mono.
141168 var view_count : int = render_scene_buffers .get_view_count ()
142169 for view in view_count :
170+ # Get the RID for our scene data buffer.
171+ var scene_data_buffers : RID = scene_data .get_uniform_buffer ()
172+
143173 # Get the RID for our color image, we will be reading from and writing to it.
144- var input_image : RID = render_scene_buffers .get_color_layer (view )
174+ var color_image : RID = render_scene_buffers .get_color_layer (view )
175+
176+ # Get the RID for our depth image, we will be reading from it.
177+ var depth_image : RID = render_scene_buffers .get_depth_layer (view )
145178
146179 # Create a uniform set, this will be cached, the cache will be cleared if our viewports configuration is changed.
147- var uniform := RDUniform .new ()
148- uniform .uniform_type = RenderingDevice .UNIFORM_TYPE_IMAGE
149- uniform .binding = 0
150- uniform .add_id (input_image )
151- var uniform_set := UniformSetCacheRD .get_cache (shader , 0 , [uniform ])
180+ var scene_data_uniform := RDUniform .new ()
181+ scene_data_uniform .uniform_type = RenderingDevice .UNIFORM_TYPE_UNIFORM_BUFFER
182+ scene_data_uniform .binding = 0
183+ scene_data_uniform .add_id (scene_data_buffers )
184+ var color_uniform := RDUniform .new ()
185+ color_uniform .uniform_type = RenderingDevice .UNIFORM_TYPE_IMAGE
186+ color_uniform .binding = 1
187+ color_uniform .add_id (color_image )
188+ var depth_uniform := RDUniform .new ()
189+ depth_uniform .uniform_type = RenderingDevice .UNIFORM_TYPE_SAMPLER_WITH_TEXTURE
190+ depth_uniform .binding = 2
191+ depth_uniform .add_id (nearest_sampler )
192+ depth_uniform .add_id (depth_image )
193+ var uniform_set_rid : RID = UniformSetCacheRD .get_cache (shader , 0 , [scene_data_uniform , color_uniform , depth_uniform ])
194+
195+ # Set our view.
196+ push_constant [2 ] = view
152197
153198 # Run our compute shader.
154- var compute_list : = rd .compute_list_begin ()
199+ var compute_list : int = rd .compute_list_begin ()
155200 rd .compute_list_bind_compute_pipeline (compute_list , pipeline )
156- rd .compute_list_bind_uniform_set (compute_list , uniform_set , 0 )
201+ rd .compute_list_bind_uniform_set (compute_list , uniform_set_rid , 0 )
157202 rd .compute_list_set_push_constant (compute_list , push_constant .to_byte_array (), push_constant .size () * 4 )
158203 rd .compute_list_dispatch (compute_list , x_groups , y_groups , z_groups )
159204 rd .compute_list_end ()
0 commit comments