Files
settled-reach/client/scripts/rendering/fog_shader.gd
T
2026-04-05 11:09:10 +02:00

86 lines
3.0 KiB
GDScript

extends Node2D
## Fog overlay controller — manages ColorRect + shader uniforms for D-059 fog.
## Reads textures from FogState autoload, positions rect to cover viewport.
## Architecture: docs/architecture/fog-shader-spec.md
signal fog_noise_ready
const TILE_SIZE := float(Constants.TILE_SIZE)
var _noise_ready: bool = false
var _fog_rect: ColorRect
var _shader_mat: ShaderMaterial
func _ready() -> void:
# Create the fog overlay ColorRect — transparent fallback so a shader failure
# doesn't paint solid white over the entire world (z:900 covers everything).
_fog_rect = ColorRect.new()
_fog_rect.name = "FogRect"
_fog_rect.color = Color.TRANSPARENT
add_child(_fog_rect)
# Load shader and create material
var shader := load("res://shaders/fog.gdshader") as Shader
if shader == null:
push_error("FogShader: failed to load res://shaders/fog.gdshader — fog disabled")
return
_shader_mat = ShaderMaterial.new()
_shader_mat.shader = shader
_fog_rect.material = _shader_mat
# Create seamless noise texture for fog animation
var noise := FastNoiseLite.new()
noise.seed = 42
noise.noise_type = FastNoiseLite.TYPE_PERLIN
noise.frequency = 0.03
var noise_tex := NoiseTexture2D.new()
noise_tex.noise = noise
noise_tex.width = 256
noise_tex.height = 256
noise_tex.seamless = true
noise_tex.changed.connect(
func():
_noise_ready = true
fog_noise_ready.emit()
)
_shader_mat.set_shader_parameter("noise_tex", noise_tex)
_shader_mat.set_shader_parameter("tile_size", TILE_SIZE)
print("FogShader: Initialized (D-059 3-state)")
func update_fog() -> void:
if _shader_mat == null:
return # Shader failed to load — fog disabled
# 1. Update FogState textures from GameState
FogState.update_from_state()
# 2. Position ColorRect to cover the current viewport.
# Use the camera's actual position (not player position) so the fog rect
# tracks the smoothed camera and never desynchronizes during smooth pan.
var vp_size := get_viewport().get_visible_rect().size
var cam := get_viewport().get_camera_2d()
var zoom := cam.zoom if cam else Vector2(2.0, 2.0)
var camera_pos := cam.global_position if cam else GameState.player_position * TILE_SIZE
var half_view := vp_size / (2.0 * zoom)
_fog_rect.position = camera_pos - half_view
_fog_rect.size = vp_size / zoom
# 3. Update shader uniforms
_shader_mat.set_shader_parameter("visibility_tex", FogState.visibility_texture)
_shader_mat.set_shader_parameter("exploration_tex", FogState.exploration_texture)
_shader_mat.set_shader_parameter("zone_tint_tex", FogState.zone_tint_texture)
_shader_mat.set_shader_parameter("rect_pos", _fog_rect.position)
_shader_mat.set_shader_parameter("rect_sz", _fog_rect.size)
_shader_mat.set_shader_parameter("map_offset", Vector2(FogState.map_bounds.position))
_shader_mat.set_shader_parameter("map_size", Vector2(FogState.map_bounds.size))
var t: float = (
FogState.override_time if FogState.override_time >= 0.0 else Time.get_ticks_msec() / 1000.0
)
_shader_mat.set_shader_parameter("time", t)
_shader_mat.set_shader_parameter("debug_exploration", FogState.debug_exploration)