diff --git a/tests/world_weather_validation.gd b/tests/world_weather_validation.gd index 9a53eff..1f46adf 100644 --- a/tests/world_weather_validation.gd +++ b/tests/world_weather_validation.gd @@ -524,6 +524,15 @@ func _validate_weather_presentation() -> void: assert(rain.emitting) assert(rain.amount_ratio > 0.99) assert(rain.amount == WorldTimeVisualControllerType.RAIN_PARTICLE_AMOUNT) + assert( + WorldTimeVisualControllerType.RAIN_EMITTER_OFFSET.y + >= WorldTimeVisualControllerType.RAIN_SUPPORTED_CANOPY_HEIGHT + + WorldTimeVisualControllerType.RAIN_CANOPY_CLEARANCE + ) + assert(is_equal_approx( + rain.lifetime, + WorldTimeVisualControllerType.RAIN_LIFETIME_SECONDS, + )) assert(rain.visibility_aabb == ( WorldTimeVisualControllerType.RAIN_VISIBILITY_AABB )) @@ -548,6 +557,9 @@ func _validate_weather_presentation() -> void: rain_material.initial_velocity_max, WorldTimeVisualControllerType.RAIN_VELOCITY_MAX, )) + assert(rain_material.gravity.is_equal_approx( + WorldTimeVisualControllerType.RAIN_GRAVITY + )) var rain_mesh := rain.draw_pass_1 as BoxMesh assert(rain_mesh != null) assert(rain_mesh.size.is_equal_approx( @@ -569,6 +581,11 @@ func _validate_weather_presentation() -> void: assert(rain_collision.size.is_equal_approx( WorldTimeVisualControllerType.RAIN_COLLISION_SIZE )) + assert( + rain_collision.size.y * 0.5 + > WorldTimeVisualControllerType.RAIN_EMITTER_OFFSET.y + + WorldTimeVisualControllerType.RAIN_EMISSION_EXTENTS.y + ) assert( rain_collision.heightfield_mask == PrecipitationOcclusionType.RENDER_LAYER_MASK diff --git a/world/world_time_visual_controller.gd b/world/world_time_visual_controller.gd index 5328c54..ec67e85 100644 --- a/world/world_time_visual_controller.gd +++ b/world/world_time_visual_controller.gd @@ -5,20 +5,31 @@ const UPDATE_INTERVAL_SECONDS: float = 0.1 const LIGHT_UPDATE_INTERVAL_SECONDS: float = 0.25 const SUN_YAW_DEGREES: float = -32.0 const WEATHER_TRANSITION_SECONDS: float = 10.0 -const RAIN_EMITTER_OFFSET := Vector3(0.0, 7.0, 0.0) +# Large generated trees reach nearly 22 m at their maximum authored scale. +# Keep the rain source above those canopies so drops cannot be born underneath +# the height-field surface that is meant to hide them. +const RAIN_SUPPORTED_CANOPY_HEIGHT: float = 22.0 +const RAIN_CANOPY_CLEARANCE: float = 4.0 +const RAIN_EMITTER_OFFSET := Vector3( + 0.0, + RAIN_SUPPORTED_CANOPY_HEIGHT + RAIN_CANOPY_CLEARANCE, + 0.0, +) const RAIN_EMISSION_EXTENTS := Vector3(13.0, 1.0, 13.0) const RAIN_VISIBILITY_AABB := AABB( - Vector3(-13.5, -9.0, -13.5), - Vector3(27.0, 12.0, 27.0), + Vector3(-13.5, -36.0, -13.5), + Vector3(27.0, 40.0, 27.0), ) const RAIN_PARTICLE_AMOUNT: int = 2240 const LIGHT_RAIN_PARTICLE_AMOUNT: int = 48 const LIGHT_RAIN_FIXED_FPS: int = 8 -const RAIN_VELOCITY_MIN: float = 16.0 -const RAIN_VELOCITY_MAX: float = 20.0 +const RAIN_LIFETIME_SECONDS: float = 1.4 +const RAIN_VELOCITY_MIN: float = 20.0 +const RAIN_VELOCITY_MAX: float = 24.0 +const RAIN_GRAVITY := Vector3(0.0, -2.0, 0.0) const RAIN_DROP_SIZE := Vector3(0.014, 0.34, 0.014) const RAIN_COLLISION_BASE_SIZE: float = 0.08 -const RAIN_COLLISION_SIZE := Vector3(28.0, 24.0, 28.0) +const RAIN_COLLISION_SIZE := Vector3(28.0, 64.0, 28.0) const FOG_DAYLIGHT_SCENE_BRIGHTNESS: float = 0.42 const FOG_DAYLIGHT_FOG_LIGHT_BRIGHTNESS: float = 0.42 const FOG_DAYLIGHT_WATER_BRIGHTNESS: float = 0.42 @@ -212,7 +223,7 @@ func _prepare_rain() -> void: else RAIN_PARTICLE_AMOUNT ) _rain.amount_ratio = 0.0 - _rain.lifetime = 1.25 + _rain.lifetime = RAIN_LIFETIME_SECONDS _rain.fixed_fps = ( LIGHT_RAIN_FIXED_FPS if _light_performance_profile else 30 ) @@ -228,7 +239,7 @@ func _prepare_rain() -> void: process_material.spread = 5.0 process_material.initial_velocity_min = RAIN_VELOCITY_MIN process_material.initial_velocity_max = RAIN_VELOCITY_MAX - process_material.gravity = Vector3(0.0, -2.0, 0.0) + process_material.gravity = RAIN_GRAVITY process_material.collision_mode = ( ParticleProcessMaterial.COLLISION_HIDE_ON_CONTACT )