Add sunlit shallows site with localized sun shafts
Quality Gate / Quality Gate (pull_request) Successful in 6m55s
Quality Gate / Quality Gate (pull_request) Successful in 6m55s
New visual test site under game/world/sites: flat sandy floor at -40 m, calm surface at 0 m, fixed daytime sun ahead of and above the submarine. Light shafts come from a shadow-only surface occluder whose alpha-scissor ripples open only inside a pool a few tens of metres ahead; a subtractive FogVolume cancels the global volumetric fog above the water, and an unshaded ceiling mesh shows the lit underside of the surface inside that pool. A composed world (sunlit_shallows_world.tscn) mounts the submarine, cockpit and camera rig in it, with the projectors kept out of the fog. Cockpit: the porthole glass moves to its own render layer with a rougher material and the porthole fill light excludes that layer, so interior lamps no longer mirror as hard specular points. Quality gate: new integration suite for the site (42 checks), three glass assertions in the foundation suite, and the Input-access architecture rule now matches both path separators so the gate runs on Windows. project.godot raises the volumetric fog froxel grid to 128 so the shafts stay readable. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
2c1ea50aba
commit
f0072a3e11
14 files changed
+666
-2
No files matched your search
@@ -108,6 +108,10 @@ func practical_light_count() -> int:
|
||||
return 0 if _practical_lighting == null else _practical_lighting.practical_light_count()
|
||||
|
||||
|
||||
func fill_light_ignores_porthole_glass() -> bool:
|
||||
return _practical_lighting != null and _practical_lighting.fill_light_ignores_porthole_glass()
|
||||
|
||||
|
||||
func gauges_are_dashboard_mounted() -> bool:
|
||||
return _analog_gauges != null and _analog_gauges.get_parent() == get_parent().get_node("Dashboard")
|
||||
|
||||
|
||||
@@ -9,6 +9,10 @@ const CockpitMeshFactory = preload(
|
||||
"res://game/presentation/cockpit/cockpit_mesh_factory.gd"
|
||||
)
|
||||
|
||||
const CockpitPressureBulkhead = preload(
|
||||
"res://game/presentation/cockpit/cockpit_pressure_bulkhead.gd"
|
||||
)
|
||||
|
||||
const CAGE_LAMP_SCENE = preload("res://game/presentation/cockpit/assets/models/cage_lamp.glb")
|
||||
|
||||
## Flange centre of the right-hand lamp, on the flat end cap of the pressure
|
||||
@@ -34,6 +38,7 @@ const WARM_LAMP_SHADOW_BIAS := 0.03
|
||||
var _materials: CockpitMaterialPalette
|
||||
var _warm_lights: Array[OmniLight3D] = []
|
||||
var _emergency_light: OmniLight3D
|
||||
var _porthole_fill: OmniLight3D
|
||||
|
||||
|
||||
func _init(materials: CockpitMaterialPalette) -> void:
|
||||
@@ -103,7 +108,20 @@ func _add_fill_light() -> void:
|
||||
porthole_fill.light_energy = 1.0
|
||||
porthole_fill.omni_range = 1.1
|
||||
porthole_fill.shadow_enabled = false
|
||||
# 30 cm behind the glass, it would mirror itself as a hard blue point.
|
||||
porthole_fill.light_cull_mask &= ~CockpitPressureBulkhead.PORTHOLE_GLASS_RENDER_LAYER_BIT
|
||||
add_child(porthole_fill)
|
||||
_porthole_fill = porthole_fill
|
||||
|
||||
|
||||
func fill_light_ignores_porthole_glass() -> bool:
|
||||
return (
|
||||
_porthole_fill != null
|
||||
and (
|
||||
_porthole_fill.light_cull_mask
|
||||
& CockpitPressureBulkhead.PORTHOLE_GLASS_RENDER_LAYER_BIT
|
||||
) == 0
|
||||
)
|
||||
|
||||
|
||||
func _add_emergency_light() -> void:
|
||||
|
||||
@@ -4,6 +4,18 @@ extends Node3D
|
||||
## Imported pressure hull (end cap, knuckle and barrel in one shell) and the
|
||||
## porthole bolted into it. Both models are instanced by `cockpit_interior.tscn`.
|
||||
|
||||
## The porthole glass lives alone on render layer 2 so interior lights that
|
||||
## sit right behind it (the cool porthole fill) can leave it out of their cull
|
||||
## mask instead of mirroring themselves as a hard specular point.
|
||||
const PORTHOLE_GLASS_RENDER_LAYER_BIT := 1 << 1
|
||||
## Imported glass is near-mirror smooth; a little roughness turns the remaining
|
||||
## lamp reflections into soft smears rather than pinpoints.
|
||||
const PORTHOLE_GLASS_ROUGHNESS := 0.45
|
||||
|
||||
const CockpitMeshFactory = preload(
|
||||
"res://game/presentation/cockpit/cockpit_mesh_factory.gd"
|
||||
)
|
||||
|
||||
const WHITEBOX_NAMES: Array[String] = [
|
||||
"LeftBulkhead",
|
||||
"RightBulkhead",
|
||||
@@ -26,6 +38,21 @@ func _ready() -> void:
|
||||
push_error("Pressure hull or porthole model is missing a node")
|
||||
return
|
||||
_porthole_glass.cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_OFF
|
||||
_porthole_glass.layers = PORTHOLE_GLASS_RENDER_LAYER_BIT
|
||||
var glass_material := CockpitMeshFactory.own_surface_material(_porthole_glass)
|
||||
if glass_material != null:
|
||||
glass_material.roughness = PORTHOLE_GLASS_ROUGHNESS
|
||||
|
||||
|
||||
func glass_is_on_dedicated_layer() -> bool:
|
||||
return _porthole_glass != null and _porthole_glass.layers == PORTHOLE_GLASS_RENDER_LAYER_BIT
|
||||
|
||||
|
||||
func glass_roughness() -> float:
|
||||
if _porthole_glass == null:
|
||||
return 0.0
|
||||
var material := _porthole_glass.get_active_material(0) as BaseMaterial3D
|
||||
return 0.0 if material == null else material.roughness
|
||||
|
||||
|
||||
func panel_count() -> int:
|
||||
|
||||
Reference in new issue
Block a user