-
-
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
Closed
BastiaanOlij
wants to merge
2
commits into
godotengine:master
from
BastiaanOlij:add_rendering_effects
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# Godot 4+ specific ignores | ||
.godot/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
||
 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
@tool | ||
extends CompositorEffect | ||
class_name CompositorEffectGrayScale | ||
|
||
# This is a very simple effects demo that takes our color values and writes | ||
# back gray scale values. | ||
|
||
func _init() -> void: | ||
effect_callback_type = CompositorEffect.EFFECT_CALLBACK_TYPE_POST_TRANSPARENT | ||
RenderingServer.call_on_render_thread(_initialize_compute) | ||
|
||
|
||
func _notification(what: int) -> void: | ||
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) | ||
|
||
############################################################################### | ||
# Everything after this point is designed to run on our rendering thread | ||
|
||
var rd: RenderingDevice | ||
|
||
var shader: RID | ||
var pipeline: RID | ||
|
||
func _initialize_compute() -> void: | ||
rd = RenderingServer.get_rendering_device() | ||
if not rd: | ||
OS.alert("RenderingDevice is not available, aborting.\nCompositor effects require RenderingDevice to be available, which means you have to use the Forward+ or Mobile rendering method.") | ||
return | ||
|
||
# Create our shader. | ||
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: int, p_render_data: RenderData) -> void: | ||
if rd and p_effect_callback_type == CompositorEffect.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 (which can be affected by the | ||
# `scaling_3d_scale` property), not the window size. | ||
var size := render_scene_buffers.get_internal_size() | ||
if size.x <= 0 and size.y <= 0: | ||
push_error("Render size is too small.") | ||
return | ||
|
||
# We can use a compute shader here. | ||
@warning_ignore("integer_division") | ||
var x_groups := (size.x - 1) / 8 + 1 | ||
@warning_ignore("integer_division") | ||
var y_groups := (size.y - 1) / 8 + 1 | ||
|
||
# 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 view_count: | ||
# 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) | ||
|
||
# Create a uniform set. This will be cached: the cache will be cleared if our viewport's 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 ]) | ||
|
||
# Run our compute shader. | ||
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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] | ||
|
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
extends Node3D | ||
|
||
var create_depth_mips_effect: CompositorEffectCreateDepthMips | ||
var apply_sssr_effect: CompositorEffectApplySSSR | ||
var gray_scale_effect: CompositorEffectGrayScale | ||
|
||
var camera_x := 0.0 | ||
var camera_y := 0.0 | ||
|
||
@onready var sssr_button: Button = $UI/MarginContainer/VBoxContainer/SSSR | ||
@onready var gray_scale_button: Button = $UI/MarginContainer/VBoxContainer/GrayScaleBtn | ||
|
||
func _ready() -> void: | ||
var compositor: Compositor = $WorldEnvironment.compositor | ||
for effect in compositor.compositor_effects: | ||
if effect.get_script() == CompositorEffectCreateDepthMips: | ||
create_depth_mips_effect = effect | ||
elif effect.get_script() == CompositorEffectApplySSSR: | ||
apply_sssr_effect = effect | ||
elif effect.get_script() == CompositorEffectGrayScale: | ||
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 | ||
|
||
|
||
func _input(event: InputEvent) -> void: | ||
if event is InputEventMouseMotion: | ||
var mouse_event: InputEventMouseMotion = event | ||
|
||
if mouse_event.button_mask & MOUSE_BUTTON_MASK_LEFT: | ||
camera_x = clamp(camera_x + mouse_event.screen_relative.y * 0.01, -PI * 0.1, PI * 0.25) | ||
camera_y -= mouse_event.screen_relative.x * 0.01 | ||
|
||
var b1 := Basis(Vector3.UP, camera_y) | ||
var b2 := Basis(Vector3.LEFT, camera_x) | ||
|
||
$Pivot.transform.basis = b1 * b2 | ||
|
||
|
||
func _on_simple_ssr_toggled(toggled_on: bool) -> void: | ||
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: bool) -> void: | ||
if gray_scale_effect: | ||
gray_scale_effect.enabled = toggled_on |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
[gd_scene load_steps=24 format=3 uid="uid://hay7hbv1cp62"] | ||
|
||
[ext_resource type="Script" path="res://main.gd" id="1_ekxfu"] | ||
[ext_resource type="Script" path="res://simple_ssr/create_depth_mips.gd" id="2_0tpoa"] | ||
[ext_resource type="Texture2D" uid="uid://bshdn70nudsun" path="res://pattern.png" id="2_d1qxb"] | ||
[ext_resource type="Script" path="res://simple_ssr/apply_sssr.gd" id="3_gyc5w"] | ||
[ext_resource type="Script" path="res://gray_scale/gray_scale.gd" id="4_6ukm1"] | ||
[ext_resource type="Texture2D" uid="uid://d0e66wb8yplkw" path="res://uv.jpg" id="5_ybioc"] | ||
|
||
[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 | ||
|
||
[sub_resource type="CompositorEffect" id="CompositorEffect_7wi85"] | ||
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_0tpoa") | ||
|
||
[sub_resource type="CompositorEffect" id="CompositorEffect_57gju"] | ||
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_gyc5w") | ||
max_distance = 1.0 | ||
max_steps = 32 | ||
|
||
[sub_resource type="CompositorEffect" id="CompositorEffect_jq1iy"] | ||
resource_local_to_scene = false | ||
resource_name = "" | ||
enabled = true | ||
effect_callback_type = 4 | ||
needs_motion_vectors = false | ||
needs_normal_roughness = false | ||
script = ExtResource("4_6ukm1") | ||
|
||
[sub_resource type="Compositor" id="Compositor_2i651"] | ||
compositor_effects = Array[CompositorEffect]([SubResource("CompositorEffect_7wi85"), SubResource("CompositorEffect_57gju"), SubResource("CompositorEffect_jq1iy")]) | ||
|
||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_tvupy"] | ||
albedo_texture = ExtResource("5_ybioc") | ||
metallic = 0.5 | ||
roughness = 0.75 | ||
uv1_scale = Vector3(5, 5, 5) | ||
texture_filter = 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 | ||
texture_filter = 5 | ||
|
||
[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 | ||
texture_filter = 5 | ||
|
||
[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 | ||
texture_filter = 5 | ||
|
||
[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 | ||
texture_filter = 5 | ||
|
||
[node name="Main" type="Node3D"] | ||
script = ExtResource("1_ekxfu") | ||
|
||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."] | ||
environment = SubResource("Environment_kx13e") | ||
compositor = SubResource("Compositor_2i651") | ||
|
||
[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 | ||
directional_shadow_mode = 0 | ||
directional_shadow_fade_start = 1.0 | ||
directional_shadow_max_distance = 15.0 | ||
|
||
[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 = 20 | ||
theme_override_constants/margin_top = 20 | ||
theme_override_constants/margin_right = 20 | ||
theme_override_constants/margin_bottom = 20 | ||
|
||
[node name="VBoxContainer" type="VBoxContainer" parent="UI/MarginContainer"] | ||
layout_mode = 2 | ||
|
||
[node name="SSSR" type="CheckBox" parent="UI/MarginContainer/VBoxContainer"] | ||
layout_mode = 2 | ||
button_pressed = true | ||
text = "Stochastic Screen-Space Reflections" | ||
|
||
[node name="GrayScaleBtn" type="CheckBox" parent="UI/MarginContainer/VBoxContainer"] | ||
layout_mode = 2 | ||
button_pressed = true | ||
text = "Grayscale" | ||
|
||
[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"] |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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
pipeline
RID is not being freed here.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.
When you free a shader, all dependencies of the shader will be freed, including all pipelines related to that shader.