From ddde409dbf4a5711b1cc71e0f226a3cd6a7ef4f1 Mon Sep 17 00:00:00 2001 From: MaddoScientisto Date: Sun, 1 Mar 2026 18:00:54 +0100 Subject: [PATCH] Lava and water shaders --- .../EntityScripts/Solid/acidarea.gd | 4 -- Shaders/Acid.gdshader | 34 +++++--------- Shaders/Water.gdshader | 44 +++++++++++++++++++ Shaders/Water.gdshader.uid | 1 + 4 files changed, 57 insertions(+), 26 deletions(-) create mode 100644 Shaders/Water.gdshader create mode 100644 Shaders/Water.gdshader.uid diff --git a/3D/TrenchBroom/EntityScripts/Solid/acidarea.gd b/3D/TrenchBroom/EntityScripts/Solid/acidarea.gd index e4c898e2..edbc50ed 100644 --- a/3D/TrenchBroom/EntityScripts/Solid/acidarea.gd +++ b/3D/TrenchBroom/EntityScripts/Solid/acidarea.gd @@ -3,8 +3,6 @@ class_name AcidArea extends Area3D const _ACID_SHADER := preload("res://Shaders/Acid.gdshader") -# Replace this path with your actual noise texture resource once you have one saved on disk. -# A NoiseTexture2D saved as a .tres file works well here. const _NOISE_TEX_PATH := "res://Shaders/acid_noise.tres" func _init() -> void: @@ -24,12 +22,10 @@ func _apply_shader_to_mesh(mesh_instance: MeshInstance3D, noise_tex: NoiseTextur if surface_count == 0 and mesh_instance.mesh != null: surface_count = mesh_instance.mesh.get_surface_count() for i in range(surface_count): - # Grab the texture func_godot baked into the surface before we replace the material var existing_tex: Texture2D = null var existing_mat := mesh_instance.mesh.surface_get_material(i) as BaseMaterial3D if existing_mat != null: existing_tex = existing_mat.albedo_texture - var mat := ShaderMaterial.new() mat.shader = _ACID_SHADER if existing_tex != null: diff --git a/Shaders/Acid.gdshader b/Shaders/Acid.gdshader index 0bd0185b..104293f9 100644 --- a/Shaders/Acid.gdshader +++ b/Shaders/Acid.gdshader @@ -1,44 +1,34 @@ shader_type spatial; -// unshaded matches the pixel-art look of the rest of the game. -// Opaque render mode guarantees the floor draws before any transparent Sprite3D / -// AnimatedSprite3D, which are always sorted into the transparent queue after opaque geo. render_mode unshaded, depth_draw_opaque, cull_back; -// Texture carried over from the TrenchBroom surface material by acidarea.gd. -// hint_default_white means a flat white is used if nothing is assigned, so -// acid_color alone still produces a visible result. uniform sampler2D albedo_tex : source_color, filter_nearest, repeat_enable, hint_default_white; -// Grayscale noise for UV distortion and bubble pulse. Falls back to white (no distortion). uniform sampler2D noise_tex : hint_default_white, filter_linear_mipmap, repeat_enable; uniform vec4 acid_color : source_color = vec4(0.2, 0.85, 0.1, 1.0); -uniform vec2 flow_direction = vec2(0.3, 0.15); -// How strongly the noise warps the UV coords uniform float distortion_strength = 0.04; -// Additive glow tint strength (0 = no glow) uniform float emission_energy = 0.4; +// How fast the goo undulates — lower = lazier/thicker +uniform float speed = 0.4; void fragment() { vec2 uv = UV; - float t = TIME; + float t = TIME * speed; - // Sample noise at two offsets to build a swirling distortion field - vec2 noise_uv_a = uv * 0.5 + vec2(t * 0.05, t * 0.03); - vec2 noise_uv_b = uv * 0.5 + vec2(-t * 0.04, t * 0.06); + // Two noise layers scrolling in opposite diagonal directions. + // They fight each other so there's no net flow, just churning. + vec2 noise_uv_a = uv * 0.5 + vec2( t * 0.6, t * 0.4); + vec2 noise_uv_b = uv * 0.5 + vec2(-t * 0.5, -t * 0.7); float noise_a = texture(noise_tex, noise_uv_a).r; float noise_b = texture(noise_tex, noise_uv_b).r; - vec2 distortion = vec2(noise_a, noise_b) * 2.0 - 1.0; + vec2 distortion = vec2(noise_a - 0.5, noise_b - 0.5) * distortion_strength; - vec2 scrolled_uv = uv + flow_direction * t + distortion * distortion_strength; - - vec4 tex_color = texture(albedo_tex, scrolled_uv); + vec4 tex_color = texture(albedo_tex, uv + distortion); vec3 final_color = tex_color.rgb * acid_color.rgb; - // Subtle additive glow pulsing with noise so the surface looks alive - float bubble_pulse = texture(noise_tex, uv * 0.3 + vec2(t * 0.1)).r; - final_color += final_color * emission_energy * (0.7 + 0.3 * bubble_pulse); + // Slow breathing glow from a third noise layer + float breathe = texture(noise_tex, uv * 0.3 + vec2(t * 0.3, t * 0.2)).r; + final_color += final_color * emission_energy * (0.6 + 0.4 * breathe); ALBEDO = final_color; } - diff --git a/Shaders/Water.gdshader b/Shaders/Water.gdshader new file mode 100644 index 00000000..0bd0185b --- /dev/null +++ b/Shaders/Water.gdshader @@ -0,0 +1,44 @@ +shader_type spatial; + +// unshaded matches the pixel-art look of the rest of the game. +// Opaque render mode guarantees the floor draws before any transparent Sprite3D / +// AnimatedSprite3D, which are always sorted into the transparent queue after opaque geo. +render_mode unshaded, depth_draw_opaque, cull_back; + +// Texture carried over from the TrenchBroom surface material by acidarea.gd. +// hint_default_white means a flat white is used if nothing is assigned, so +// acid_color alone still produces a visible result. +uniform sampler2D albedo_tex : source_color, filter_nearest, repeat_enable, hint_default_white; +// Grayscale noise for UV distortion and bubble pulse. Falls back to white (no distortion). +uniform sampler2D noise_tex : hint_default_white, filter_linear_mipmap, repeat_enable; + +uniform vec4 acid_color : source_color = vec4(0.2, 0.85, 0.1, 1.0); +uniform vec2 flow_direction = vec2(0.3, 0.15); +// How strongly the noise warps the UV coords +uniform float distortion_strength = 0.04; +// Additive glow tint strength (0 = no glow) +uniform float emission_energy = 0.4; + +void fragment() { + vec2 uv = UV; + float t = TIME; + + // Sample noise at two offsets to build a swirling distortion field + vec2 noise_uv_a = uv * 0.5 + vec2(t * 0.05, t * 0.03); + vec2 noise_uv_b = uv * 0.5 + vec2(-t * 0.04, t * 0.06); + float noise_a = texture(noise_tex, noise_uv_a).r; + float noise_b = texture(noise_tex, noise_uv_b).r; + vec2 distortion = vec2(noise_a, noise_b) * 2.0 - 1.0; + + vec2 scrolled_uv = uv + flow_direction * t + distortion * distortion_strength; + + vec4 tex_color = texture(albedo_tex, scrolled_uv); + vec3 final_color = tex_color.rgb * acid_color.rgb; + + // Subtle additive glow pulsing with noise so the surface looks alive + float bubble_pulse = texture(noise_tex, uv * 0.3 + vec2(t * 0.1)).r; + final_color += final_color * emission_energy * (0.7 + 0.3 * bubble_pulse); + + ALBEDO = final_color; +} + diff --git a/Shaders/Water.gdshader.uid b/Shaders/Water.gdshader.uid new file mode 100644 index 00000000..250e97dc --- /dev/null +++ b/Shaders/Water.gdshader.uid @@ -0,0 +1 @@ +uid://bcvnkf60t6yam