mirror of
https://github.com/godotengine/godot-demo-projects.git
synced 2026-01-04 23:10:08 +01:00
Modify shader example to show using built-in includes (#1086)
This commit is contained in:
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.cte
|
|||||||
compress/mode=0
|
compress/mode=0
|
||||||
compress/high_quality=false
|
compress/high_quality=false
|
||||||
compress/lossy_quality=0.7
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
compress/hdr_compression=1
|
compress/hdr_compression=1
|
||||||
compress/normal_map=0
|
compress/normal_map=0
|
||||||
compress/channel_pack=0
|
compress/channel_pack=0
|
||||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
|||||||
mipmaps/limit=-1
|
mipmaps/limit=-1
|
||||||
roughness/mode=0
|
roughness/mode=0
|
||||||
roughness/src_normal=""
|
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/fix_alpha_border=true
|
||||||
process/premult_alpha=false
|
process/premult_alpha=false
|
||||||
process/normal_map_invert_y=false
|
process/normal_map_invert_y=false
|
||||||
|
|||||||
@@ -20,4 +20,3 @@ Shader effect: %s
|
|||||||
"Enabled" if compositor.compositor_effects[0].enabled else "Disabled",
|
"Enabled" if compositor.compositor_effects[0].enabled else "Disabled",
|
||||||
"Enabled" if compositor.compositor_effects[1].enabled else "Disabled",
|
"Enabled" if compositor.compositor_effects[1].enabled else "Disabled",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -35,8 +35,13 @@ effect_callback_type = 4
|
|||||||
needs_motion_vectors = false
|
needs_motion_vectors = false
|
||||||
needs_normal_roughness = false
|
needs_normal_roughness = false
|
||||||
script = ExtResource("1_rkpno")
|
script = ExtResource("1_rkpno")
|
||||||
shader_code = " // Invert color.
|
shader_code = "// Unproject
|
||||||
color.rgb = vec3(1.0 - color.r, 1.0 - color.g, 1.0 - color.b);
|
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"]
|
[sub_resource type="Compositor" id="Compositor_xxhi4"]
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/pattern.png-888ea151ee9fa7a079d3252596260765.
|
|||||||
compress/mode=0
|
compress/mode=0
|
||||||
compress/high_quality=false
|
compress/high_quality=false
|
||||||
compress/lossy_quality=0.7
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
compress/hdr_compression=1
|
compress/hdr_compression=1
|
||||||
compress/normal_map=0
|
compress/normal_map=0
|
||||||
compress/channel_pack=0
|
compress/channel_pack=0
|
||||||
@@ -25,6 +27,10 @@ mipmaps/generate=true
|
|||||||
mipmaps/limit=-1
|
mipmaps/limit=-1
|
||||||
roughness/mode=0
|
roughness/mode=0
|
||||||
roughness/src_normal=""
|
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/fix_alpha_border=true
|
||||||
process/premult_alpha=false
|
process/premult_alpha=false
|
||||||
process/normal_map_invert_y=false
|
process/normal_map_invert_y=false
|
||||||
|
|||||||
@@ -2,30 +2,46 @@
|
|||||||
class_name PostProcessShader
|
class_name PostProcessShader
|
||||||
extends CompositorEffect
|
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.
|
// Invocations in the (x, y, z) dimension.
|
||||||
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
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.
|
// Our push constant.
|
||||||
// Must be aligned to 16 bytes, just like the push constant we passed from the script.
|
// Must be aligned to 16 bytes, just like the push constant we passed from the script.
|
||||||
layout(push_constant, std430) uniform Params {
|
layout(push_constant, std430) uniform Params {
|
||||||
vec2 raster_size;
|
vec2 raster_size;
|
||||||
vec2 pad;
|
float view;
|
||||||
|
float pad;
|
||||||
} params;
|
} params;
|
||||||
|
|
||||||
// The code we want to execute in each invocation.
|
// The code we want to execute in each invocation.
|
||||||
void main() {
|
void main() {
|
||||||
ivec2 uv = ivec2(gl_GlobalInvocationID.xy);
|
ivec2 uv = ivec2(gl_GlobalInvocationID.xy);
|
||||||
ivec2 size = ivec2(params.raster_size);
|
ivec2 size = ivec2(params.raster_size);
|
||||||
|
int view = int(params.view);
|
||||||
|
|
||||||
if (uv.x >= size.x || uv.y >= size.y) {
|
if (uv.x >= size.x || uv.y >= size.y) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vec2 uv_norm = vec2(uv) / params.raster_size;
|
||||||
|
|
||||||
vec4 color = imageLoad(color_image, uv);
|
vec4 color = imageLoad(color_image, uv);
|
||||||
|
float depth = texture(depth_texture, uv_norm).r;
|
||||||
|
|
||||||
#COMPUTE_CODE
|
#COMPUTE_CODE
|
||||||
|
|
||||||
@@ -42,9 +58,10 @@ void main() {
|
|||||||
var rd: RenderingDevice
|
var rd: RenderingDevice
|
||||||
var shader: RID
|
var shader: RID
|
||||||
var pipeline: RID
|
var pipeline: RID
|
||||||
|
var nearest_sampler: RID
|
||||||
|
|
||||||
var mutex := Mutex.new()
|
var mutex := Mutex.new()
|
||||||
var shader_is_dirty := true
|
var shader_is_dirty: bool = true
|
||||||
|
|
||||||
|
|
||||||
func _init() -> void:
|
func _init() -> void:
|
||||||
@@ -58,7 +75,9 @@ func _notification(what: int) -> void:
|
|||||||
if what == NOTIFICATION_PREDELETE:
|
if what == NOTIFICATION_PREDELETE:
|
||||||
if shader.is_valid():
|
if shader.is_valid():
|
||||||
# Freeing our shader will also free any dependents such as the pipeline!
|
# 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.
|
#region Code in this region runs on the rendering thread.
|
||||||
@@ -67,7 +86,7 @@ func _check_shader() -> bool:
|
|||||||
if not rd:
|
if not rd:
|
||||||
return false
|
return false
|
||||||
|
|
||||||
var new_shader_code := ""
|
var new_shader_code: String = ""
|
||||||
|
|
||||||
# Check if our shader is dirty.
|
# Check if our shader is dirty.
|
||||||
mutex.lock()
|
mutex.lock()
|
||||||
@@ -81,7 +100,7 @@ func _check_shader() -> bool:
|
|||||||
return pipeline.is_valid()
|
return pipeline.is_valid()
|
||||||
|
|
||||||
# Apply template.
|
# 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.
|
# Out with the old.
|
||||||
if shader.is_valid():
|
if shader.is_valid():
|
||||||
@@ -93,7 +112,7 @@ func _check_shader() -> bool:
|
|||||||
var shader_source := RDShaderSource.new()
|
var shader_source := RDShaderSource.new()
|
||||||
shader_source.language = RenderingDevice.SHADER_LANGUAGE_GLSL
|
shader_source.language = RenderingDevice.SHADER_LANGUAGE_GLSL
|
||||||
shader_source.source_compute = new_shader_code
|
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 != "":
|
if shader_spirv.compile_error_compute != "":
|
||||||
push_error(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():
|
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.
|
# 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.
|
# Note that implementation differs per renderer hence the need for the cast.
|
||||||
var render_scene_buffers := p_render_data.get_render_scene_buffers()
|
var render_scene_buffers: RenderSceneBuffers = p_render_data.get_render_scene_buffers()
|
||||||
if 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!
|
# Get our render size, this is the 3D render resolution!
|
||||||
var size: Vector2i = render_scene_buffers.get_internal_size()
|
var size: Vector2i = render_scene_buffers.get_internal_size()
|
||||||
if size.x == 0 and size.y == 0:
|
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.
|
# We can use a compute shader here.
|
||||||
@warning_ignore("integer_division")
|
@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")
|
@warning_ignore("integer_division")
|
||||||
var y_groups := (size.y - 1) / 8 + 1
|
var y_groups: int = (size.y - 1) / 8 + 1
|
||||||
var z_groups := 1
|
var z_groups: int = 1
|
||||||
|
|
||||||
# Create push constant.
|
# Create push constant.
|
||||||
# Must be aligned to 16 bytes and be in the same order as defined in the shader.
|
# 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,
|
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.
|
# 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()
|
var view_count: int = render_scene_buffers.get_view_count()
|
||||||
for view in 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.
|
# 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.
|
# Create a uniform set, this will be cached, the cache will be cleared if our viewports configuration is changed.
|
||||||
var uniform := RDUniform.new()
|
var scene_data_uniform := RDUniform.new()
|
||||||
uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_IMAGE
|
scene_data_uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_UNIFORM_BUFFER
|
||||||
uniform.binding = 0
|
scene_data_uniform.binding = 0
|
||||||
uniform.add_id(input_image)
|
scene_data_uniform.add_id(scene_data_buffers)
|
||||||
var uniform_set := UniformSetCacheRD.get_cache(shader, 0, [uniform])
|
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.
|
# 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_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_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_dispatch(compute_list, x_groups, y_groups, z_groups)
|
||||||
rd.compute_list_end()
|
rd.compute_list_end()
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ config_version=5
|
|||||||
|
|
||||||
config/name="Compositor Effects (Post-Processing)"
|
config/name="Compositor Effects (Post-Processing)"
|
||||||
run/main_scene="res://main.tscn"
|
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"
|
config/icon="res://icon.svg"
|
||||||
|
|
||||||
[debug]
|
[debug]
|
||||||
@@ -28,12 +28,12 @@ window/stretch/aspect="expand"
|
|||||||
|
|
||||||
toggle_grayscale_effect={
|
toggle_grayscale_effect={
|
||||||
"deadzone": 0.5,
|
"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={
|
toggle_shader_effect={
|
||||||
"deadzone": 0.5,
|
"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)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user