-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f7e3ceb
commit b720b33
Showing
15 changed files
with
563 additions
and
0 deletions.
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,38 @@ | ||
# Compute texture | ||
|
||
This demo shows how to use compute shaders to populate a texture that is used as an input for a material shader. | ||
|
||
When the mouse cursor isn't hovering above the plane random "drops" of water are added that drive the ripple effect. | ||
When the mouse cursor is above the plane you can "draw" on the plane to drive the ripple effect. | ||
|
||
Language: GDScript | ||
|
||
Renderer: Forward Plus | ||
|
||
> Note: this demo requires Godot 4.2 or later | ||
## Screenshots | ||
|
||
![Screenshot](screenshots/compute_texture.webp) | ||
|
||
## Technical description | ||
|
||
The texture populated by the compute shader contains height data that is used in the material shader to create a rain drops/water ripple effect. It's a well known technique that has been around since the mid 90ies, adapted to a compute shader. | ||
|
||
Three textures are created directly on the rendering device: | ||
- One texture is used to write the heightmap to and used in the material shader. | ||
- One texture is read from and contains the previous frames data. | ||
- One texture is read from and contains data from the frame before that. | ||
|
||
Instead of copying data from texture to texture to create this history, we simply cycle the RIDs. | ||
|
||
Note that in this demo we are using the main rendering device to ensure we execute our compute shader before our normal rendering. | ||
|
||
To use the texture with the latest height data we use a `Texture2DRD` resource, this is a special texture resource node that is able to use a texture directly created on the rendering device and expose it to material shaders. | ||
|
||
The material shader uses a standard gradient approach by sampling the height map and calculating tangent and bi-normal vectors and adjust the normal accordingly. | ||
|
||
## Licenses | ||
|
||
Files in the `polyhaven/` folder are downloaded from <https://polyhaven.com/a/industrial_sunset_puresky> | ||
and are licensed under CC0 1.0 Universal. |
Binary file not shown.
34 changes: 34 additions & 0 deletions
34
compute/texture/assets/polyhaven/industrial_sunset_puresky_2k.hdr.import
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,34 @@ | ||
[remap] | ||
|
||
importer="texture" | ||
type="CompressedTexture2D" | ||
uid="uid://d051ugdf65it1" | ||
path="res://.godot/imported/industrial_sunset_puresky_2k.hdr-2273dddf6859dd4da64c4a85b4589512.ctex" | ||
metadata={ | ||
"vram_texture": false | ||
} | ||
|
||
[deps] | ||
|
||
source_file="res://assets/polyhaven/industrial_sunset_puresky_2k.hdr" | ||
dest_files=["res://.godot/imported/industrial_sunset_puresky_2k.hdr-2273dddf6859dd4da64c4a85b4589512.ctex"] | ||
|
||
[params] | ||
|
||
compress/mode=3 | ||
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=0 |
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://bonkdv3wikslq" | ||
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,27 @@ | ||
extends Node3D | ||
|
||
# Note, the code here just adds some control to our effects. | ||
# Check res://water_plane/water_plane.gd for the real implementation | ||
|
||
var y = 0.0 | ||
|
||
@onready var water_plane = $WaterPlane | ||
|
||
func _ready(): | ||
$Container/RainSize/HSlider.value = $WaterPlane.rain_size | ||
$Container/MouseSize/HSlider.value = $WaterPlane.mouse_size | ||
|
||
|
||
# Called every frame. 'delta' is the elapsed time since the previous frame. | ||
func _process(delta): | ||
if $Container/Rotate.button_pressed: | ||
y += delta | ||
water_plane.basis = Basis(Vector3.UP, y) | ||
|
||
|
||
func _on_rain_size_changed(value): | ||
$WaterPlane.rain_size = value | ||
|
||
|
||
func _on_mouse_size_changed(value): | ||
$WaterPlane.mouse_size = value |
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,76 @@ | ||
[gd_scene load_steps=7 format=3 uid="uid://c7nfvt1chslyh"] | ||
|
||
[ext_resource type="Script" path="res://main.gd" id="1_yvrvl"] | ||
[ext_resource type="Texture2D" uid="uid://d051ugdf65it1" path="res://assets/polyhaven/industrial_sunset_puresky_2k.hdr" id="2_g2q6b"] | ||
[ext_resource type="PackedScene" uid="uid://b2a5bjsxw63wr" path="res://water_plane/water_plane.tscn" id="2_k1nfp"] | ||
|
||
[sub_resource type="PanoramaSkyMaterial" id="PanoramaSkyMaterial_obhcg"] | ||
panorama = ExtResource("2_g2q6b") | ||
|
||
[sub_resource type="Sky" id="Sky_s1sgk"] | ||
sky_material = SubResource("PanoramaSkyMaterial_obhcg") | ||
|
||
[sub_resource type="Environment" id="Environment_5dv8s"] | ||
background_mode = 2 | ||
sky = SubResource("Sky_s1sgk") | ||
tonemap_mode = 2 | ||
tonemap_white = 4.56 | ||
|
||
[node name="Main" type="Node3D"] | ||
script = ExtResource("1_yvrvl") | ||
|
||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] | ||
transform = Transform3D(0.5, -0.75, 0.433013, 2.78059e-08, 0.5, 0.866026, -0.866025, -0.433013, 0.25, 0, 1, 0) | ||
shadow_enabled = true | ||
|
||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."] | ||
environment = SubResource("Environment_5dv8s") | ||
|
||
[node name="WaterPlane" parent="." instance=ExtResource("2_k1nfp")] | ||
|
||
[node name="Camera3D" type="Camera3D" parent="."] | ||
transform = Transform3D(0.900266, -0.142464, 0.41137, -0.113954, 0.834877, 0.538512, -0.420162, -0.531681, 0.735377, 1.55343, 1.1434, 2.431) | ||
|
||
[node name="Container" type="VBoxContainer" parent="."] | ||
offset_right = 40.0 | ||
offset_bottom = 40.0 | ||
|
||
[node name="Rotate" type="CheckBox" parent="Container"] | ||
layout_mode = 2 | ||
theme_override_colors/font_color = Color(0, 0, 0, 1) | ||
text = "Rotate" | ||
|
||
[node name="RainSize" type="HBoxContainer" parent="Container"] | ||
layout_mode = 2 | ||
|
||
[node name="HSlider" type="HSlider" parent="Container/RainSize"] | ||
custom_minimum_size = Vector2(250, 0) | ||
layout_mode = 2 | ||
min_value = 1.0 | ||
max_value = 10.0 | ||
step = 0.1 | ||
value = 1.0 | ||
|
||
[node name="Label" type="Label" parent="Container/RainSize"] | ||
layout_mode = 2 | ||
theme_override_colors/font_color = Color(0, 0, 0, 1) | ||
text = "Rain size" | ||
|
||
[node name="MouseSize" type="HBoxContainer" parent="Container"] | ||
layout_mode = 2 | ||
|
||
[node name="HSlider" type="HSlider" parent="Container/MouseSize"] | ||
custom_minimum_size = Vector2(250, 0) | ||
layout_mode = 2 | ||
min_value = 1.0 | ||
max_value = 10.0 | ||
step = 0.1 | ||
value = 1.0 | ||
|
||
[node name="Label" type="Label" parent="Container/MouseSize"] | ||
layout_mode = 2 | ||
theme_override_colors/font_color = Color(0, 0, 0, 1) | ||
text = "Mouse size" | ||
|
||
[connection signal="value_changed" from="Container/RainSize/HSlider" to="." method="_on_rain_size_changed"] | ||
[connection signal="value_changed" from="Container/MouseSize/HSlider" to="." method="_on_mouse_size_changed"] |
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,16 @@ | ||
; Engine configuration file. | ||
; It's best edited using the editor UI and not directly, | ||
; since the parameters that go here are not all obvious. | ||
; | ||
; Format: | ||
; [section] ; section goes between [] | ||
; param=value ; assign values to parameters | ||
|
||
config_version=5 | ||
|
||
[application] | ||
|
||
config/name="TestCustomTextures" | ||
run/main_scene="res://main.tscn" | ||
config/features=PackedStringArray("4.2", "Forward Plus") | ||
config/icon="res://icon.svg" |
Empty file.
Binary file not shown.
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,47 @@ | ||
#[compute] | ||
#version 450 | ||
|
||
// Invocations in the (x, y, z) dimension | ||
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; | ||
|
||
// Our textures | ||
layout(r32f, set = 0, binding = 0) uniform restrict readonly image2D current_image; | ||
layout(r32f, set = 1, binding = 0) uniform restrict readonly image2D previous_image; | ||
layout(r32f, set = 2, binding = 0) uniform restrict writeonly image2D output_image; | ||
|
||
// Our push PushConstant | ||
layout(push_constant, std430) uniform Params { | ||
vec4 add_wave_point; | ||
vec2 texture_size; | ||
float damp; | ||
float res2; | ||
} params; | ||
|
||
// The code we want to execute in each invocation | ||
void main() { | ||
ivec2 tl = ivec2(0, 0); | ||
ivec2 size = ivec2(params.texture_size.x - 1, params.texture_size.y - 1); | ||
|
||
ivec2 uv = ivec2(gl_GlobalInvocationID.xy); | ||
|
||
float current_v = imageLoad(current_image, uv).r; | ||
float up_v = imageLoad(current_image, clamp(uv - ivec2(0, 1), tl, size)).r; | ||
float down_v = imageLoad(current_image, clamp(uv + ivec2(0, 1), tl, size)).r; | ||
float left_v = imageLoad(current_image, clamp(uv - ivec2(1, 0), tl, size)).r; | ||
float right_v = imageLoad(current_image, clamp(uv + ivec2(1, 0), tl, size)).r; | ||
float previous_v = imageLoad(previous_image, uv).r; | ||
|
||
float new_v = 2.0 * current_v - previous_v + 0.25 * (up_v + down_v + left_v + right_v - 4.0 * current_v); | ||
new_v = new_v - (params.damp * new_v * 0.001); | ||
|
||
if (params.add_wave_point.z > 0.0 && uv.x == floor(params.add_wave_point.x) && uv.y == floor(params.add_wave_point.y)) { | ||
new_v = params.add_wave_point.z; | ||
} | ||
|
||
if (new_v < 0.0) { | ||
new_v = 0.0; | ||
} | ||
vec4 result = vec4(new_v, new_v, new_v, 1.0); | ||
|
||
imageStore(output_image, uv, result); | ||
} |
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://b6pdquh2n2jvn" | ||
path="res://.godot/imported/water_compute.glsl-c7fe8f11197ba28412c4cdf6f7a9a21b.res" | ||
|
||
[deps] | ||
|
||
source_file="res://water_plane/water_compute.glsl" | ||
dest_files=["res://.godot/imported/water_compute.glsl-c7fe8f11197ba28412c4cdf6f7a9a21b.res"] | ||
|
||
[params] | ||
|
Oops, something went wrong.