-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add demo showing the use of RenderingEffects to do post processing #942
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# Normalize EOL for all files that Git considers text files. | ||
* text=auto eol=lf |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# Godot 4+ specific ignores | ||
.godot/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Post effects | ||
|
||
This demo shows how to implement post effects using the new RenderingEffect class. | ||
|
||
Renderer: Forward Plus | ||
|
||
> Note: this demo requires Godot 4.2 or later | ||
|
||
## Screenshots | ||
|
||
![Screenshot](screenshots/compute_texture.webp) |
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,74 @@ | ||||||||
@tool | ||||||||
extends RenderingEffect | ||||||||
class_name RenderingEffectGrayScale | ||||||||
|
||||||||
# This is a very simple effects demo that takes our color values and writes | ||||||||
# back gray scale values. | ||||||||
|
||||||||
func _init(): | ||||||||
effect_callback_type = RenderingEffect.EFFECT_CALLBACK_TYPE_POST_TRANSPARENT | ||||||||
RenderingServer.call_on_render_thread(_initialize_compute) | ||||||||
|
||||||||
func _notification(what): | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
if what == NOTIFICATION_PREDELETE: | ||||||||
# When this is called it should be safe to clean up our shader. | ||||||||
# If not we'll crash anyway because we can no longer call our _render_callback. | ||||||||
if shader.is_valid(): | ||||||||
rd.free_rid(shader) | ||||||||
Comment on lines
+17
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When you free a shader, all dependencies of the shader will be freed, including all pipelines related to that shader. |
||||||||
|
||||||||
############################################################################### | ||||||||
# Everything after this point is designed to run on our rendering thread | ||||||||
|
||||||||
var rd : RenderingDevice | ||||||||
|
||||||||
var shader : RID | ||||||||
var pipeline : RID | ||||||||
|
||||||||
func _initialize_compute(): | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
rd = RenderingServer.get_rendering_device() | ||||||||
if !rd: | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
return | ||||||||
|
||||||||
# Create our shader | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
var shader_file = load("res://gray_scale/gray_scale.glsl") | ||||||||
var shader_spirv: RDShaderSPIRV = shader_file.get_spirv() | ||||||||
shader = rd.shader_create_from_spirv(shader_spirv) | ||||||||
pipeline = rd.compute_pipeline_create(shader) | ||||||||
|
||||||||
func _render_callback(p_effect_callback_type, p_render_data): | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
if rd and p_effect_callback_type == RenderingEffect.EFFECT_CALLBACK_TYPE_POST_TRANSPARENT: | ||||||||
# 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 : RenderSceneBuffersRD = p_render_data.get_render_scene_buffers() | ||||||||
if render_scene_buffers: | ||||||||
# Get our render size, this is the 3D render resolution! | ||||||||
var size = render_scene_buffers.get_internal_size() | ||||||||
if size.x == 0 and size.y == 0: | ||||||||
return | ||||||||
|
||||||||
# We can use a compute shader here | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
var x_groups = (size.x - 1) / 8 + 1 | ||||||||
var y_groups = (size.y - 1) / 8 + 1 | ||||||||
|
||||||||
# Barrier | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
rd.barrier(RenderingDevice.BARRIER_MASK_ALL_BARRIERS, RenderingDevice.BARRIER_MASK_COMPUTE) | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Manual barriers are deprecated and should be removed, should be changed in multiple files. |
||||||||
|
||||||||
# Loop through views just in case we're doing stereo rendering. No extra cost if this is mono. | ||||||||
var view_count = render_scene_buffers.get_view_count() | ||||||||
for view in range(view_count): | ||||||||
# Get the RID for our color image, we will be reading from and writing to it. | ||||||||
var input_image = render_scene_buffers.get_color_layer(view) | ||||||||
|
||||||||
# Create a uniform set, this will be cached, the cache will be cleared if our viewports configuration is changed | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
var uniform : RDUniform = 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 ]) | ||||||||
|
||||||||
# Run our compute shader | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
var compute_list := 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_dispatch(compute_list, x_groups, y_groups, 1) | ||||||||
rd.compute_list_end() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#[compute] | ||
#version 450 | ||
|
||
// 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; | ||
|
||
// The code we want to execute in each invocation | ||
void main() { | ||
ivec2 uv = ivec2(gl_GlobalInvocationID.xy); | ||
|
||
vec4 color = imageLoad(color_image, uv); | ||
float gray = color.r * 0.2125 + color.g * 0.7154 + color.b * 0.0721; | ||
color.rgb = vec3(gray); | ||
|
||
imageStore(color_image, uv, color); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
[remap] | ||
|
||
importer="glsl" | ||
type="RDShaderFile" | ||
uid="uid://cycdb7vyg3b6g" | ||
path="res://.godot/imported/gray_scale.glsl-cdec27ad421b3dcac596053515285dc6.res" | ||
|
||
[deps] | ||
|
||
source_file="res://gray_scale/gray_scale.glsl" | ||
dest_files=["res://.godot/imported/gray_scale.glsl-cdec27ad421b3dcac596053515285dc6.res"] | ||
|
||
[params] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
[remap] | ||
|
||
importer="texture" | ||
type="CompressedTexture2D" | ||
uid="uid://cm88hfhyutq2d" | ||
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" | ||
metadata={ | ||
"vram_texture": false | ||
} | ||
|
||
[deps] | ||
|
||
source_file="res://icon.svg" | ||
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] | ||
|
||
[params] | ||
|
||
compress/mode=0 | ||
compress/high_quality=false | ||
compress/lossy_quality=0.7 | ||
compress/hdr_compression=1 | ||
compress/normal_map=0 | ||
compress/channel_pack=0 | ||
mipmaps/generate=false | ||
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=1 | ||
svg/scale=1.0 | ||
editor/scale_with_editor_scale=false | ||
editor/convert_colors_with_editor_theme=false |
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,52 @@ | ||||||||
extends Node3D | ||||||||
|
||||||||
@onready var sssr_button = $UI/MarginContainer/VBoxContainer/SSSR | ||||||||
@onready var gray_scale_button = $UI/MarginContainer/VBoxContainer/GrayScaleBtn | ||||||||
|
||||||||
var create_depth_mips_effect : RenderingEffectCreateDepthMips | ||||||||
var apply_sssr_effect : RenderingEffectApplySSSR | ||||||||
var gray_scale_effect : RenderingEffectGrayScale | ||||||||
|
||||||||
# Called when the node enters the scene tree for the first time. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
func _ready(): | ||||||||
var environment : Environment = $WorldEnvironment.environment | ||||||||
for effect in environment.rendering_effects: | ||||||||
if effect.get_script() == RenderingEffectCreateDepthMips: | ||||||||
create_depth_mips_effect = effect | ||||||||
elif effect.get_script() == RenderingEffectApplySSSR: | ||||||||
apply_sssr_effect = effect | ||||||||
elif effect.get_script() == RenderingEffectGrayScale: | ||||||||
gray_scale_effect = effect | ||||||||
|
||||||||
if create_depth_mips_effect and apply_sssr_effect: | ||||||||
sssr_button.button_pressed = create_depth_mips_effect.enabled | ||||||||
|
||||||||
if gray_scale_effect: | ||||||||
gray_scale_button.button_pressed = gray_scale_effect.enabled | ||||||||
|
||||||||
var cam_x = 0.0 | ||||||||
var cam_y = 0.0 | ||||||||
|
||||||||
func _input(event): | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
if event is InputEventMouseMotion: | ||||||||
var mouse_event : InputEventMouseMotion = event | ||||||||
|
||||||||
if mouse_event.button_mask & MOUSE_BUTTON_MASK_LEFT: | ||||||||
cam_x = clamp(cam_x + mouse_event.relative.y * 0.01, -PI * 0.1, PI * 0.25) | ||||||||
cam_y -= mouse_event.relative.x * 0.01 | ||||||||
|
||||||||
var b1 : Basis = Basis(Vector3.UP, cam_y) | ||||||||
var b2 : Basis = Basis(Vector3.LEFT, cam_x) | ||||||||
|
||||||||
$Pivot.transform.basis = b1 * b2 | ||||||||
|
||||||||
func _on_simple_ssr_toggled(toggled_on): | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
if create_depth_mips_effect and apply_sssr_effect: | ||||||||
create_depth_mips_effect.enabled = toggled_on | ||||||||
apply_sssr_effect.enabled = toggled_on | ||||||||
|
||||||||
func _on_gray_scale_btn_toggled(toggled_on): | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
if gray_scale_effect: | ||||||||
gray_scale_effect.enabled = toggled_on | ||||||||
|
||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
[gd_scene load_steps=23 format=3 uid="uid://hay7hbv1cp62"] | ||
|
||
[ext_resource type="Script" path="res://gray_scale/gray_scale.gd" id="1_di38g"] | ||
[ext_resource type="Script" path="res://main.gd" id="1_ekxfu"] | ||
[ext_resource type="Texture2D" uid="uid://bshdn70nudsun" path="res://pattern.png" id="2_d1qxb"] | ||
[ext_resource type="Script" path="res://simple_ssr/create_depth_mips.gd" id="2_lv16x"] | ||
[ext_resource type="Script" path="res://simple_ssr/apply_sssr.gd" id="3_ygheb"] | ||
[ext_resource type="Texture2D" uid="uid://d0e66wb8yplkw" path="res://uv.jpg" id="5_ybioc"] | ||
|
||
[sub_resource type="RenderingEffect" id="RenderingEffect_rprpc"] | ||
resource_local_to_scene = false | ||
resource_name = "" | ||
enabled = true | ||
effect_callback_type = 0 | ||
access_resolved_color = false | ||
access_resolved_depth = true | ||
needs_motion_vectors = false | ||
needs_normal_roughness = false | ||
script = ExtResource("2_lv16x") | ||
|
||
[sub_resource type="RenderingEffect" id="RenderingEffect_sm2nk"] | ||
resource_local_to_scene = false | ||
resource_name = "" | ||
enabled = true | ||
effect_callback_type = 2 | ||
access_resolved_color = false | ||
access_resolved_depth = false | ||
needs_motion_vectors = false | ||
needs_normal_roughness = true | ||
needs_separate_specular = true | ||
script = ExtResource("3_ygheb") | ||
max_distance = 1.0 | ||
max_steps = 32 | ||
|
||
[sub_resource type="RenderingEffect" id="RenderingEffect_jcxua"] | ||
resource_local_to_scene = false | ||
resource_name = "" | ||
enabled = true | ||
effect_callback_type = 4 | ||
needs_motion_vectors = false | ||
needs_normal_roughness = false | ||
script = ExtResource("1_di38g") | ||
|
||
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_ptioq"] | ||
sky_horizon_color = Color(0.64625, 0.65575, 0.67075, 1) | ||
ground_horizon_color = Color(0.64625, 0.65575, 0.67075, 1) | ||
|
||
[sub_resource type="Sky" id="Sky_gkygq"] | ||
sky_material = SubResource("ProceduralSkyMaterial_ptioq") | ||
|
||
[sub_resource type="Environment" id="Environment_kx13e"] | ||
background_mode = 2 | ||
sky = SubResource("Sky_gkygq") | ||
tonemap_mode = 2 | ||
ssr_depth_tolerance = 3.41 | ||
glow_enabled = true | ||
rendering_effects = Array[RenderingEffect]([SubResource("RenderingEffect_rprpc"), SubResource("RenderingEffect_sm2nk"), SubResource("RenderingEffect_jcxua")]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Must use the new Compositor API. |
||
|
||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_tvupy"] | ||
albedo_texture = ExtResource("5_ybioc") | ||
metallic = 0.5 | ||
roughness = 0.75 | ||
uv1_scale = Vector3(5, 5, 5) | ||
|
||
[sub_resource type="PlaneMesh" id="PlaneMesh_fbrjs"] | ||
size = Vector2(20, 20) | ||
|
||
[sub_resource type="SphereMesh" id="SphereMesh_nqw7b"] | ||
|
||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_mwci7"] | ||
albedo_texture = ExtResource("2_d1qxb") | ||
metallic = 0.78 | ||
roughness = 0.24 | ||
|
||
[sub_resource type="SphereMesh" id="SphereMesh_lau6s"] | ||
|
||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_qdjdj"] | ||
albedo_color = Color(1, 0.298039, 0.247059, 1) | ||
albedo_texture = ExtResource("2_d1qxb") | ||
metallic = 0.26 | ||
roughness = 0.59 | ||
|
||
[sub_resource type="CylinderMesh" id="CylinderMesh_jepk0"] | ||
|
||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_xkdqw"] | ||
albedo_color = Color(0.580392, 0.658824, 1, 1) | ||
albedo_texture = ExtResource("2_d1qxb") | ||
metallic = 0.86 | ||
roughness = 0.29 | ||
|
||
[sub_resource type="BoxMesh" id="BoxMesh_syokj"] | ||
|
||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_chobt"] | ||
albedo_color = Color(0.588235, 0.282353, 0.443137, 1) | ||
albedo_texture = ExtResource("2_d1qxb") | ||
metallic = 0.52 | ||
roughness = 0.42 | ||
|
||
[node name="Main" type="Node3D"] | ||
script = ExtResource("1_ekxfu") | ||
|
||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."] | ||
environment = SubResource("Environment_kx13e") | ||
|
||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] | ||
transform = Transform3D(0.959131, 0.245052, -0.141481, -0.0849703, 0.726354, 0.682048, 0.269902, -0.642152, 0.717491, 0, 1.94732, 0) | ||
shadow_enabled = true | ||
|
||
[node name="Pivot" type="Node3D" parent="."] | ||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.553607, 0.779114, 0) | ||
|
||
[node name="Camera3D" type="Camera3D" parent="Pivot"] | ||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 3) | ||
|
||
[node name="Floor" type="MeshInstance3D" parent="."] | ||
material_override = SubResource("StandardMaterial3D_tvupy") | ||
mesh = SubResource("PlaneMesh_fbrjs") | ||
|
||
[node name="MetalSphere" type="MeshInstance3D" parent="."] | ||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.721009, 0) | ||
mesh = SubResource("SphereMesh_nqw7b") | ||
surface_material_override/0 = SubResource("StandardMaterial3D_mwci7") | ||
|
||
[node name="RedSphere" type="MeshInstance3D" parent="."] | ||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.17882, 0.628256, -0.532507) | ||
mesh = SubResource("SphereMesh_lau6s") | ||
surface_material_override/0 = SubResource("StandardMaterial3D_qdjdj") | ||
|
||
[node name="Cylinder" type="MeshInstance3D" parent="."] | ||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.29466, 0, 0.409778) | ||
mesh = SubResource("CylinderMesh_jepk0") | ||
surface_material_override/0 = SubResource("StandardMaterial3D_xkdqw") | ||
|
||
[node name="Box" type="MeshInstance3D" parent="."] | ||
transform = Transform3D(0.682049, -0.297997, -0.667837, -1.49012e-08, 0.913212, -0.407486, 0.731306, 0.277925, 0.622855, 2.41454, 0.500351, 0.0996274) | ||
mesh = SubResource("BoxMesh_syokj") | ||
surface_material_override/0 = SubResource("StandardMaterial3D_chobt") | ||
|
||
[node name="UI" type="CanvasLayer" parent="."] | ||
|
||
[node name="MarginContainer" type="MarginContainer" parent="UI"] | ||
offset_right = 40.0 | ||
offset_bottom = 40.0 | ||
theme_override_constants/margin_left = 5 | ||
theme_override_constants/margin_top = 5 | ||
theme_override_constants/margin_right = 5 | ||
theme_override_constants/margin_bottom = 5 | ||
|
||
[node name="VBoxContainer" type="VBoxContainer" parent="UI/MarginContainer"] | ||
layout_mode = 2 | ||
|
||
[node name="SSSR" type="CheckBox" parent="UI/MarginContainer/VBoxContainer"] | ||
layout_mode = 2 | ||
text = "SSSR" | ||
|
||
[node name="GrayScaleBtn" type="CheckBox" parent="UI/MarginContainer/VBoxContainer"] | ||
layout_mode = 2 | ||
text = "Gray scale" | ||
|
||
[connection signal="toggled" from="UI/MarginContainer/VBoxContainer/SSSR" to="." method="_on_simple_ssr_toggled"] | ||
[connection signal="toggled" from="UI/MarginContainer/VBoxContainer/GrayScaleBtn" to="." method="_on_gray_scale_btn_toggled"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The API renamed to CompositorEffect, should be changed in multiple files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, I need to revisit this