fix(assets): tune fog shader alpha and add zone temperature tint per D-059
Ticket #563. Light fog alpha tuned to 0.25-0.35 range (was 0.25-0.55), deep fog alpha set to 0.55-0.70 with zone temperature tint from zone_tint_tex (bar=warm #2a1f15, hub=cool #1a1f2e, corridor=neutral #1a1a1a). Two Perlin noise cycles: 8-10s light, 15-20s deep. Zone tint texture now populated per-tile from server zone_id in fog_state.gd with preservation across texture resizes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,20 @@ const EXP_UNEXPLORED: int = 0 # Never seen — total darkness
|
||||
const EXP_EXPLORED: int = 128 # Previously seen, now out of LOS — deep fog
|
||||
const EXP_VISIBLE: int = 255 # Currently in LOS — clear (written each frame)
|
||||
|
||||
# Zone temperature tints (D-059 + D-046, Sprint 22) — keyed by zone_id string from server.
|
||||
# Matches audio_manager.gd ZONE_ASSETS zone_id strings for consistent zone semantics.
|
||||
# Colors are dark tints used as the fog overlay in the deep fog zone:
|
||||
# hub/workplace: #1a1f2e (cool blue-dark — terminal, institutional)
|
||||
# bar: #2a1f15 (warm amber-dark — social, inhabited)
|
||||
# corridor: #1a1a1a (neutral dark — transitional, maintenance)
|
||||
const ZONE_TINTS: Dictionary = {
|
||||
"hub": Color(0.102, 0.122, 0.180), # #1a1f2e — cool blue-dark
|
||||
"workplace": Color(0.102, 0.122, 0.180), # same as hub
|
||||
"bar": Color(0.165, 0.122, 0.082), # #2a1f15 — warm amber-dark
|
||||
"corridor": Color(0.102, 0.102, 0.102), # #1a1a1a — neutral dark
|
||||
}
|
||||
const ZONE_TINT_DEFAULT: Color = Color(0.102, 0.102, 0.102) # #1a1a1a neutral
|
||||
|
||||
var map_bounds: Rect2i = Rect2i(0, 0, 1, 1)
|
||||
var visibility_texture: ImageTexture
|
||||
var exploration_texture: ImageTexture
|
||||
@@ -25,6 +39,8 @@ var _exp_bytes: PackedByteArray
|
||||
var _vis_image: Image
|
||||
var _exp_image: Image
|
||||
var _tint_image: Image
|
||||
# Zone tint stored as 3-channel RGB bytes (R, G, B per pixel) for preservation across resizes
|
||||
var _tint_bytes: PackedByteArray
|
||||
var _width: int = 1
|
||||
var _height: int = 1
|
||||
var _prev_visible: Dictionary = {} # Tiles visible last frame (for incremental decay)
|
||||
@@ -37,6 +53,7 @@ func _ready() -> void:
|
||||
func _resize(bounds: Rect2i) -> void:
|
||||
var old_bounds := map_bounds
|
||||
var old_exp := _exp_bytes
|
||||
var old_tint := _tint_bytes
|
||||
var old_w := _width
|
||||
var old_h := _height
|
||||
|
||||
@@ -72,9 +89,35 @@ func _resize(bounds: Rect2i) -> void:
|
||||
_exp_image = Image.create_from_data(_width, _height, false, Image.FORMAT_R8, _exp_bytes)
|
||||
exploration_texture = ImageTexture.create_from_image(_exp_image)
|
||||
|
||||
# Zone tint — neutral dark for Sprint 6 (zone metadata deferred)
|
||||
_tint_image = Image.create(_width, _height, false, Image.FORMAT_RGB8)
|
||||
_tint_image.fill(Color(0.05, 0.05, 0.08))
|
||||
# Zone tint — 3 bytes per pixel (RGB), default neutral dark
|
||||
var tint_sz := sz * 3
|
||||
_tint_bytes = PackedByteArray()
|
||||
_tint_bytes.resize(tint_sz)
|
||||
var default_r := int(ZONE_TINT_DEFAULT.r * 255.0)
|
||||
var default_g := int(ZONE_TINT_DEFAULT.g * 255.0)
|
||||
var default_b := int(ZONE_TINT_DEFAULT.b * 255.0)
|
||||
for i in range(sz):
|
||||
_tint_bytes[i * 3 + 0] = default_r
|
||||
_tint_bytes[i * 3 + 1] = default_g
|
||||
_tint_bytes[i * 3 + 2] = default_b
|
||||
# Preserve zone tint data from old bounds (zone tints are stable — tile zone never changes)
|
||||
if old_tint.size() > 0 and old_w > 0 and old_h > 0:
|
||||
var dx: int = old_bounds.position.x - bounds.position.x
|
||||
var dy: int = old_bounds.position.y - bounds.position.y
|
||||
for oy in range(old_h):
|
||||
var ny: int = oy + dy
|
||||
if ny < 0 or ny >= _height:
|
||||
continue
|
||||
for ox in range(old_w):
|
||||
var nx: int = ox + dx
|
||||
if nx < 0 or nx >= _width:
|
||||
continue
|
||||
var old_idx := (oy * old_w + ox) * 3
|
||||
var new_idx := (ny * _width + nx) * 3
|
||||
_tint_bytes[new_idx + 0] = old_tint[old_idx + 0]
|
||||
_tint_bytes[new_idx + 1] = old_tint[old_idx + 1]
|
||||
_tint_bytes[new_idx + 2] = old_tint[old_idx + 2]
|
||||
_tint_image = Image.create_from_data(_width, _height, false, Image.FORMAT_RGB8, _tint_bytes)
|
||||
zone_tint_texture = ImageTexture.create_from_image(_tint_image)
|
||||
|
||||
_prev_visible.clear()
|
||||
@@ -126,6 +169,35 @@ func update_from_state() -> void:
|
||||
_exp_image.set_data(_width, _height, false, Image.FORMAT_R8, _exp_bytes)
|
||||
exploration_texture.update(_exp_image)
|
||||
|
||||
# 3. Zone tint: write zone temperature color for currently visible tiles.
|
||||
# Zone data is stable (tile zone never changes) so we only write on first sight.
|
||||
# Data persists in _tint_bytes across frames and across resizes.
|
||||
var tint_dirty := false
|
||||
for tile in tiles:
|
||||
if not tile is Dictionary or not tile.has("x") or not tile.has("y"):
|
||||
continue
|
||||
var zone_id: String = str(tile.get("zone_id", ""))
|
||||
if zone_id.is_empty():
|
||||
continue
|
||||
var tint_color: Color = ZONE_TINTS.get(zone_id, ZONE_TINT_DEFAULT)
|
||||
var px: int = int(tile.x) - ox
|
||||
var py: int = int(tile.y) - oy
|
||||
if px < 0 or py < 0 or px >= _width or py >= _height:
|
||||
continue
|
||||
var tint_idx := (py * _width + px) * 3
|
||||
var new_r := int(tint_color.r * 255.0)
|
||||
var new_g := int(tint_color.g * 255.0)
|
||||
var new_b := int(tint_color.b * 255.0)
|
||||
# Only update if different from current (avoid spurious texture uploads)
|
||||
if _tint_bytes[tint_idx] != new_r or _tint_bytes[tint_idx + 1] != new_g or _tint_bytes[tint_idx + 2] != new_b:
|
||||
_tint_bytes[tint_idx + 0] = new_r
|
||||
_tint_bytes[tint_idx + 1] = new_g
|
||||
_tint_bytes[tint_idx + 2] = new_b
|
||||
tint_dirty = true
|
||||
if tint_dirty:
|
||||
_tint_image.set_data(_width, _height, false, Image.FORMAT_RGB8, _tint_bytes)
|
||||
zone_tint_texture.update(_tint_image)
|
||||
|
||||
# Shallow copy — correct for Dictionary<Vector2i, bool/String> values
|
||||
_prev_visible = positions.duplicate()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user