From c12ca7ba31f13738b3ca44270ebb0960ca6a85f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torjus=20H=C3=A5kestad?= Date: Tue, 19 Aug 2025 06:26:50 +0200 Subject: [PATCH] game: water shader experiments --- assets/shaders/vis_water.tres | 91 ++++++++++++++++++++++++++++++ assets/shaders/water.gdshader | 36 ++++++++++++ assets/shaders/water.gdshader.uid | 1 + assets/shaders/water2.gdshader | 27 +++++++++ assets/shaders/water2.gdshader.uid | 1 + assets/sprites/3xwater.png | 3 + assets/sprites/3xwater.png.import | 35 ++++++++++++ assets/sprites/water_texture.tres | 3 + scenes/tiles/tileset.tres | 32 ++++++++++- 9 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 assets/shaders/vis_water.tres create mode 100644 assets/shaders/water.gdshader create mode 100644 assets/shaders/water.gdshader.uid create mode 100644 assets/shaders/water2.gdshader create mode 100644 assets/shaders/water2.gdshader.uid create mode 100644 assets/sprites/3xwater.png create mode 100644 assets/sprites/3xwater.png.import create mode 100644 assets/sprites/water_texture.tres diff --git a/assets/shaders/vis_water.tres b/assets/shaders/vis_water.tres new file mode 100644 index 0000000..8e48dc7 --- /dev/null +++ b/assets/shaders/vis_water.tres @@ -0,0 +1,91 @@ +[gd_resource type="VisualShader" load_steps=9 format=3 uid="uid://fcm46siaht3c"] + +[ext_resource type="Texture2D" uid="uid://cqjhrbw36g1hf" path="res://assets/sprites/3xwater.png" id="1_s0q3e"] + +[sub_resource type="VisualShaderNodeTexture" id="VisualShaderNodeTexture_wu54b"] +output_port_for_preview = 0 +texture = ExtResource("1_s0q3e") + +[sub_resource type="VisualShaderNodeInput" id="VisualShaderNodeInput_s0q3e"] +output_port_for_preview = 0 +input_name = "uv2" + +[sub_resource type="VisualShaderNodeInput" id="VisualShaderNodeInput_wu54b"] +input_name = "uv" + +[sub_resource type="VisualShaderNodeTexture" id="VisualShaderNodeTexture_2m85h"] +texture = ExtResource("1_s0q3e") + +[sub_resource type="VisualShaderNodeInput" id="VisualShaderNodeInput_nkbt4"] +expanded_output_ports = [0] +input_name = "vertex" + +[sub_resource type="VisualShaderNodeVectorOp" id="VisualShaderNodeVectorOp_88kc6"] +default_input_values = [0, Vector2(0, 0), 1, Vector2(50, 50)] +op_type = 0 + +[sub_resource type="VisualShaderNodeIf" id="VisualShaderNodeIf_kx7fy"] +default_input_values = [0, 0.0, 1, 0.0, 2, 1e-05, 3, Vector3(0, 0, 0), 4, Vector3(0, 0, 0), 5, Vector3(100, 0, 0)] + +[resource] +code = "shader_type spatial; +render_mode blend_mix, depth_draw_opaque, cull_back, diffuse_lambert, specular_schlick_ggx; + + + + +void vertex() { +// Input:3 + vec3 n_out3p0 = VERTEX; + float n_out3p2 = n_out3p0.g; + + + vec3 n_out5p0; +// If:5 + float n_in5p1 = 0.00000; + float n_in5p2 = 0.00001; + vec3 n_in5p3 = vec3(0.00000, 0.00000, 0.00000); + vec3 n_in5p4 = vec3(0.00000, 0.00000, 0.00000); + vec3 n_in5p5 = vec3(100.00000, 0.00000, 0.00000); + if(abs(n_out3p2 - n_in5p1) < n_in5p2) + { + n_out5p0 = n_in5p3; + } + else if(n_out3p2 < n_in5p1) + { + n_out5p0 = n_in5p5; + } + else + { + n_out5p0 = n_in5p4; + } + + +// VectorOp:4 + vec2 n_out4p0 = vec2(n_out3p0.xy) + vec2(n_out5p0.xy); + + +// Output:0 + VERTEX = vec3(n_out4p0, 0.0); + + +} +" +graph_offset = Vector2(-22.2715, 18.9148) +nodes/vertex/0/position = Vector2(1160, 240) +nodes/vertex/2/node = SubResource("VisualShaderNodeTexture_2m85h") +nodes/vertex/2/position = Vector2(40, 280) +nodes/vertex/3/node = SubResource("VisualShaderNodeInput_nkbt4") +nodes/vertex/3/position = Vector2(300, 140) +nodes/vertex/4/node = SubResource("VisualShaderNodeVectorOp_88kc6") +nodes/vertex/4/position = Vector2(860, 120) +nodes/vertex/5/node = SubResource("VisualShaderNodeIf_kx7fy") +nodes/vertex/5/position = Vector2(640, 340) +nodes/vertex/connections = PackedInt32Array(3, 0, 4, 0, 3, 2, 5, 0, 5, 0, 4, 1, 4, 0, 0, 0) +nodes/fragment/0/position = Vector2(840, 100) +nodes/fragment/2/node = SubResource("VisualShaderNodeTexture_wu54b") +nodes/fragment/2/position = Vector2(260, 180) +nodes/fragment/3/node = SubResource("VisualShaderNodeInput_s0q3e") +nodes/fragment/3/position = Vector2(-140, 200) +nodes/fragment/4/node = SubResource("VisualShaderNodeInput_wu54b") +nodes/fragment/4/position = Vector2(540, 220) diff --git a/assets/shaders/water.gdshader b/assets/shaders/water.gdshader new file mode 100644 index 0000000..4ba15b8 --- /dev/null +++ b/assets/shaders/water.gdshader @@ -0,0 +1,36 @@ +shader_type canvas_item; + +// Parameters +uniform sampler2D water_texture; // Your 3x3 water texture +uniform vec4 water_color : source_color = vec4(0.0, 0.0, 1.0, 1.0); +uniform float speed : hint_range(0.0, 10.0) = 1.0; +uniform float strength : hint_range(0.0, 0.2) = 0.05; +uniform float tile_repeat : hint_range(1.0, 10.0) = 3.0; +uniform vec2 pan_speed = vec2(0.2, 0.1); // how fast the water texture moves + +void fragment() { + vec2 uv = UV; + + // Sample the base tile texture + vec4 base_tex = texture(TEXTURE, uv); + + // Compute mask for water pixels only + float is_water = step(0.8, 1.0 - distance(base_tex.rgb, water_color.rgb)); + + // Tile the water texture + vec2 water_uv = uv * tile_repeat; + water_uv = fract(water_uv); + + // Apply panning / movement + water_uv += pan_speed * TIME; + + // Add wave distortion on top of the moving texture + water_uv.y += sin(water_uv.x * 2.0 + TIME * speed) * strength * is_water; + water_uv.x += cos(water_uv.y * 2.0 + TIME * speed * 0.5) * strength * is_water; + + // Sample the animated water texture + vec4 water_sample = texture(water_texture, water_uv); + + // Combine: water animates, other pixels stay the same + COLOR = mix(base_tex, water_sample, is_water); +} \ No newline at end of file diff --git a/assets/shaders/water.gdshader.uid b/assets/shaders/water.gdshader.uid new file mode 100644 index 0000000..75adda1 --- /dev/null +++ b/assets/shaders/water.gdshader.uid @@ -0,0 +1 @@ +uid://dxlfb81ouff0w diff --git a/assets/shaders/water2.gdshader b/assets/shaders/water2.gdshader new file mode 100644 index 0000000..387ef51 --- /dev/null +++ b/assets/shaders/water2.gdshader @@ -0,0 +1,27 @@ +shader_type canvas_item; +uniform vec4 water_color : source_color = vec4(0.0, 0.0, 1.0, 1.0); +uniform sampler2D noise_tex; // noise texture +uniform vec2 noise_speed = vec2(0.05, 0.01); +uniform float noise_strength = 0.2; // how much to lighten/darken + +void fragment() { + vec2 uv = UV; + vec4 base_tex = texture(TEXTURE, uv); + float is_water = step(0.8, 1.0 - distance(base_tex.rgb, water_color.rgb)); + + // Scroll UVs for noise animation + vec2 noise_uv = SCREEN_UV + noise_speed * TIME; + vec4 noise_sample = texture(noise_tex, fract(noise_uv)); + + // Use noise (0..1) to brighten/darken the water color + float brightness = (noise_sample.r - 0.5) * 2.0 * noise_strength; + vec4 animated_water = water_color + vec4(vec3(brightness), 0.0); + + + COLOR = mix(base_tex, animated_water, is_water); +} + +//void light() { +// // Called for every pixel for every light affecting the material. +// // Uncomment to replace the default light processing function with this one. +//} diff --git a/assets/shaders/water2.gdshader.uid b/assets/shaders/water2.gdshader.uid new file mode 100644 index 0000000..102dc5b --- /dev/null +++ b/assets/shaders/water2.gdshader.uid @@ -0,0 +1 @@ +uid://clpp23h7fpamt diff --git a/assets/sprites/3xwater.png b/assets/sprites/3xwater.png new file mode 100644 index 0000000..a6a90a8 --- /dev/null +++ b/assets/sprites/3xwater.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6c8a742567873b0bc0e364f74fdf46e54deba4d2fb47582ccb972182b9e15680 +size 331 diff --git a/assets/sprites/3xwater.png.import b/assets/sprites/3xwater.png.import new file mode 100644 index 0000000..588ee5a --- /dev/null +++ b/assets/sprites/3xwater.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cqjhrbw36g1hf" +path.s3tc="res://.godot/imported/3xwater.png-bfe2954a002ead9d6959c0ddfb1ffb13.s3tc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} + +[deps] + +source_file="res://assets/sprites/3xwater.png" +dest_files=["res://.godot/imported/3xwater.png-bfe2954a002ead9d6959c0ddfb1ffb13.s3tc.ctex"] + +[params] + +compress/mode=2 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +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 diff --git a/assets/sprites/water_texture.tres b/assets/sprites/water_texture.tres new file mode 100644 index 0000000..d30dfb4 --- /dev/null +++ b/assets/sprites/water_texture.tres @@ -0,0 +1,3 @@ +[gd_resource type="ImageTexture" format=3 uid="uid://de02afow3ilxd"] + +[resource] diff --git a/scenes/tiles/tileset.tres b/scenes/tiles/tileset.tres index 9e7966f..26496d4 100644 --- a/scenes/tiles/tileset.tres +++ b/scenes/tiles/tileset.tres @@ -1,10 +1,31 @@ -[gd_resource type="TileSet" load_steps=4 format=3 uid="uid://c3clgitssvdlg"] +[gd_resource type="TileSet" load_steps=8 format=3 uid="uid://c3clgitssvdlg"] [ext_resource type="Texture2D" uid="uid://2xgqhe7u6lfq" path="res://assets/sprites/roguelikeSheet_transparent.png" id="1_kkifh"] +[ext_resource type="Shader" uid="uid://clpp23h7fpamt" path="res://assets/shaders/water2.gdshader" id="1_n3s2j"] [sub_resource type="TileMapPattern" id="TileMapPattern_beh8d"] tile_data = PackedInt32Array(0, 655360, 7, 65536, 655360, 8, 131072, 655360, 9, 1, 720896, 7, 65537, 720896, 8, 131073, 720896, 9, 2, 786432, 7, 65538, 786432, 8, 131074, 786432, 9) +[sub_resource type="FastNoiseLite" id="FastNoiseLite_n3s2j"] +seed = 3 +frequency = 0.0066 +fractal_type = 2 +fractal_gain = 0.435 +fractal_weighted_strength = 1.0 + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_m3ddo"] +width = 2048 +height = 2048 +seamless = true +noise = SubResource("FastNoiseLite_n3s2j") + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_n3s2j"] +shader = ExtResource("1_n3s2j") +shader_parameter/water_color = Color(0.388235, 0.772549, 0.811765, 1) +shader_parameter/noise_tex = SubResource("NoiseTexture2D_m3ddo") +shader_parameter/noise_speed = Vector2(0.03, 0.01) +shader_parameter/noise_strength = 0.05 + [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_s7nh2"] texture = ExtResource("1_kkifh") separation = Vector2i(1, 1) @@ -13,6 +34,7 @@ separation = Vector2i(1, 1) 1:0/0 = 0 1:0/0/terrain_set = 0 2:0/0 = 0 +2:0/0/material = SubResource("ShaderMaterial_n3s2j") 2:0/0/terrain_set = 0 2:0/0/terrain = 1 2:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(8, -6.02527, 8, 8, -5.84541, 8, -3.95689, -2.96767) @@ -25,6 +47,7 @@ separation = Vector2i(1, 1) 2:0/0/terrains_peering_bit/top_side = 0 2:0/0/terrains_peering_bit/top_right_corner = 0 3:0/0 = 0 +3:0/0/material = SubResource("ShaderMaterial_n3s2j") 3:0/0/terrain_set = 0 3:0/0/terrain = 1 3:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(8, 8, -8, 8, -8, -5.84541, 8, -5.75548) @@ -37,6 +60,7 @@ separation = Vector2i(1, 1) 3:0/0/terrains_peering_bit/top_side = 0 3:0/0/terrains_peering_bit/top_right_corner = 0 4:0/0 = 0 +4:0/0/material = SubResource("ShaderMaterial_n3s2j") 4:0/0/terrain_set = 0 4:0/0/terrain = 1 4:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(6.02527, 8, -8, 8, -8, -5.84541, 2.96767, -3.95689) @@ -124,6 +148,7 @@ separation = Vector2i(1, 1) 1:1/0/terrains_peering_bit/top_side = 1 1:1/0/terrains_peering_bit/top_right_corner = 1 2:1/0 = 0 +2:1/0/material = SubResource("ShaderMaterial_n3s2j") 2:1/0/terrain_set = 0 2:1/0/terrain = 1 2:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(8, -8, 8, 8, -5.84541, 8, -5.75548, -8) @@ -136,6 +161,7 @@ separation = Vector2i(1, 1) 2:1/0/terrains_peering_bit/top_side = 1 2:1/0/terrains_peering_bit/top_right_corner = 1 3:1/0 = 0 +3:1/0/material = SubResource("ShaderMaterial_n3s2j") 3:1/0/terrain_set = 0 3:1/0/terrain = 1 3:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, 8, -8, -8, 8, -8, 8, 8) @@ -148,6 +174,7 @@ separation = Vector2i(1, 1) 3:1/0/terrains_peering_bit/top_side = 1 3:1/0/terrains_peering_bit/top_right_corner = 1 4:1/0 = 0 +4:1/0/material = SubResource("ShaderMaterial_n3s2j") 4:1/0/terrain_set = 0 4:1/0/terrain = 1 4:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, 8, -8, -8, 5.84541, -8, 5.75548, 8) @@ -245,6 +272,7 @@ separation = Vector2i(1, 1) 1:2/0/terrains_peering_bit/top_side = 1 1:2/0/terrains_peering_bit/top_right_corner = 1 2:2/0 = 0 +2:2/0/material = SubResource("ShaderMaterial_n3s2j") 2:2/0/terrain_set = 0 2:2/0/terrain = 1 2:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-6.02527, -8, 8, -8, 8, 5.84541, -2.96767, 3.95689) @@ -257,6 +285,7 @@ separation = Vector2i(1, 1) 2:2/0/terrains_peering_bit/top_side = 1 2:2/0/terrains_peering_bit/top_right_corner = 1 3:2/0 = 0 +3:2/0/material = SubResource("ShaderMaterial_n3s2j") 3:2/0/terrain_set = 0 3:2/0/terrain = 1 3:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 5.84541, -8, 5.75548) @@ -269,6 +298,7 @@ separation = Vector2i(1, 1) 3:2/0/terrains_peering_bit/top_side = 1 3:2/0/terrains_peering_bit/top_right_corner = 1 4:2/0 = 0 +4:2/0/material = SubResource("ShaderMaterial_n3s2j") 4:2/0/terrain_set = 0 4:2/0/terrain = 1 4:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, 6.02527, -8, -8, 5.84541, -8, 3.95689, 2.96767)