feat: cel-shaded look — toon shader, ink outlines, stylized environment
- toon.gdshader: banded diffuse with cool-tinted shadows (3 tones), stepped specular, rim light, and an optional world-triplanar albedo path so level geometry keeps the 0.5 m grid with no UVs - toon_outline.gdshader: inverted-hull ink outline, applied via material_overlay so it works on skinned (deforming) meshes - LevelMaterials: tinted() now returns toon grid materials; toonify()/ apply_toon_recursive() convert imported character/prop materials in place - SkinnedPlayerModel: characters get toon shading + outline on load - LevelEnvironment: shared stylized environment for all maps — saturated anime sky, linear tonemap (filmic/ACES crush cel bands), bloom for emissives, saturation+contrast grade, light depth haze; test level and dust2 now use it and the procedural arena (which had NO environment) gets it plus runtime toonification of its baked geometry Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Fable 5
parent
2c7b5a1aca
commit
37c15bed1a
@@ -0,0 +1,84 @@
|
||||
extends Object
|
||||
class_name LevelEnvironment
|
||||
|
||||
## Shared stylized environment for every level: saturated anime-sky gradient,
|
||||
## bloom for emissives (tracers, plasma), and a color grade that pushes the
|
||||
## cel-shaded look (high saturation, slight contrast lift). Builders call
|
||||
## add_to(level) instead of hand-rolling WorldEnvironment + sun.
|
||||
|
||||
|
||||
## Creates and adds a WorldEnvironment + key sun + cool fill light.
|
||||
## Returns the WorldEnvironment node.
|
||||
static func add_to(level: Node, sky_variant: String = "day") -> WorldEnvironment:
|
||||
var env := WorldEnvironment.new()
|
||||
env.name = "WorldEnvironment"
|
||||
env.environment = make_environment(sky_variant)
|
||||
level.add_child(env)
|
||||
|
||||
if not level.has_node("Sun"):
|
||||
var sun := DirectionalLight3D.new()
|
||||
sun.name = "Sun"
|
||||
sun.rotation_degrees = Vector3(-52, 38, 0)
|
||||
sun.light_color = Color(1.0, 0.97, 0.88)
|
||||
sun.light_energy = 1.4
|
||||
sun.shadow_enabled = true
|
||||
sun.directional_shadow_mode = DirectionalLight3D.SHADOW_PARALLEL_4_SPLITS
|
||||
sun.directional_shadow_max_distance = 120.0
|
||||
level.add_child(sun)
|
||||
|
||||
var fill := DirectionalLight3D.new()
|
||||
fill.name = "FillLight"
|
||||
fill.rotation_degrees = Vector3(-30, -142, 0)
|
||||
fill.light_color = Color(0.6, 0.7, 1.0)
|
||||
fill.light_energy = 0.25
|
||||
fill.shadow_enabled = false
|
||||
level.add_child(fill)
|
||||
return env
|
||||
|
||||
|
||||
static func make_environment(sky_variant: String = "day") -> Environment:
|
||||
var environment := Environment.new()
|
||||
environment.background_mode = Environment.BG_SKY
|
||||
var sky := Sky.new()
|
||||
var sky_mat := ProceduralSkyMaterial.new()
|
||||
match sky_variant:
|
||||
"sunset":
|
||||
sky_mat.sky_top_color = Color(0.25, 0.2, 0.5)
|
||||
sky_mat.sky_horizon_color = Color(0.95, 0.6, 0.45)
|
||||
sky_mat.ground_bottom_color = Color(0.18, 0.12, 0.2)
|
||||
sky_mat.ground_horizon_color = Color(0.85, 0.55, 0.45)
|
||||
sky_mat.sun_curve = 0.12
|
||||
_:
|
||||
# Bold anime day sky: deep saturated blue up top, bright cyan horizon.
|
||||
sky_mat.sky_top_color = Color(0.18, 0.4, 0.85)
|
||||
sky_mat.sky_horizon_color = Color(0.72, 0.88, 0.98)
|
||||
sky_mat.ground_bottom_color = Color(0.22, 0.2, 0.24)
|
||||
sky_mat.ground_horizon_color = Color(0.62, 0.7, 0.75)
|
||||
sky_mat.sun_curve = 0.1
|
||||
sky_mat.sun_angle_max = 20.0
|
||||
sky.sky_material = sky_mat
|
||||
environment.sky = sky
|
||||
|
||||
# Flat-ish ambient keeps toon shadow bands readable (sun does the shaping).
|
||||
environment.ambient_light_source = Environment.AMBIENT_SOURCE_SKY
|
||||
environment.ambient_light_energy = 0.55
|
||||
|
||||
# Filmic crushes the cel bands; linear-ish keeps them crisp.
|
||||
environment.tonemap_mode = Environment.TONE_MAPPER_LINEAR
|
||||
|
||||
# Bloom sells emissives (tracers, plasma, rim highlights).
|
||||
environment.glow_enabled = true
|
||||
environment.glow_intensity = 0.5
|
||||
environment.glow_bloom = 0.05
|
||||
environment.glow_hdr_threshold = 1.1
|
||||
|
||||
# Cel color grade: punchy saturation, hint of contrast.
|
||||
environment.adjustment_enabled = true
|
||||
environment.adjustment_saturation = 1.22
|
||||
environment.adjustment_contrast = 1.05
|
||||
|
||||
# A touch of depth haze for scale; far enough to not gray the arena.
|
||||
environment.fog_enabled = true
|
||||
environment.fog_light_color = Color(0.65, 0.75, 0.9)
|
||||
environment.fog_density = 0.0012
|
||||
return environment
|
||||
Reference in New Issue
Block a user