Start dynamic sky
This commit is contained in:
283
dynamic-sky/README.md
Normal file
283
dynamic-sky/README.md
Normal file
@@ -0,0 +1,283 @@
|
||||
# Dynamic Sky System for Godot 4.6
|
||||
|
||||
A stylized dynamic sky system with day/night cycles, weather, clouds, and VFX.
|
||||
|
||||
## Setup Instructions
|
||||
|
||||
### Step 1: Open Project in Godot
|
||||
1. Open your Godot 4.6 project
|
||||
2. Wait for the editor to import all scripts (check the bottom progress bar)
|
||||
3. If you see script errors, click **Project > Reload Current Project**
|
||||
|
||||
### Step 2: Add to Your Scene
|
||||
1. Open the scene where you want the sky system
|
||||
2. Drag `dynamic-sky/dynamic_sky.tscn` into your scene tree
|
||||
3. Or right-click in the scene tree → **Instance Child Scene** → select `dynamic_sky.tscn`
|
||||
|
||||
### Step 3: Configure the Environment
|
||||
The DynamicSky node auto-creates required children. To link an existing environment:
|
||||
|
||||
1. Select the **DynamicSky** node
|
||||
2. In the Inspector, under **Environment**:
|
||||
- Assign your existing `WorldEnvironment` node (or leave empty to auto-create)
|
||||
- Assign existing `DirectionalLight3D` for sun/moon (or leave empty)
|
||||
|
||||
### Step 4: Generate Cloud Textures
|
||||
Clouds need textures. Use the procedural generator:
|
||||
|
||||
```gdscript
|
||||
# In a tool script or _ready():
|
||||
var cloud_tex = ProceduralCloudTexture.create_default_cloud_texture(1)
|
||||
$DynamicSky/CloudSystem.layer_configs[0].texture = cloud_tex
|
||||
```
|
||||
|
||||
Or assign existing cloud textures to each `CloudLayerConfig` in the Inspector.
|
||||
|
||||
### Step 5: Configure Shadow Texture
|
||||
```gdscript
|
||||
var shadow_tex = ProceduralCloudTexture.create_shadow_texture()
|
||||
$DynamicSky/ShadowProxySystem.shadow_texture = shadow_tex
|
||||
```
|
||||
|
||||
## Testing the System
|
||||
|
||||
### Test 1: Basic Scene Test
|
||||
1. Create a new 3D scene with a `Camera3D` and a `MeshInstance3D` (e.g., plane for ground)
|
||||
2. Instance `dynamic_sky.tscn`
|
||||
3. Run the scene (F5)
|
||||
4. You should see a gradient sky with sun light
|
||||
|
||||
### Test 2: Time of Day
|
||||
Add this script to test time changes:
|
||||
|
||||
```gdscript
|
||||
extends Node
|
||||
|
||||
@onready var sky = $DynamicSky
|
||||
|
||||
func _ready():
|
||||
# Start at morning
|
||||
sky.set_time_of_day(0.25)
|
||||
|
||||
func _process(delta):
|
||||
# Press keys to change time
|
||||
if Input.is_action_just_pressed("ui_right"):
|
||||
sky.set_time_of_day(sky.get_time_of_day() + 0.05)
|
||||
if Input.is_action_just_pressed("ui_left"):
|
||||
sky.set_time_of_day(sky.get_time_of_day() - 0.05)
|
||||
|
||||
# Print current time
|
||||
if Input.is_action_just_pressed("ui_accept"):
|
||||
print("Time: ", sky.get_time_of_day())
|
||||
```
|
||||
|
||||
### Test 3: Weather System
|
||||
```gdscript
|
||||
func _input(event):
|
||||
if event.is_action_pressed("ui_up"):
|
||||
$DynamicSky.set_weather(WeatherProfile.WeatherState.RAIN)
|
||||
if event.is_action_pressed("ui_down"):
|
||||
$DynamicSky.set_weather(WeatherProfile.WeatherState.CLEAR)
|
||||
```
|
||||
|
||||
### Test 4: Debug Panel
|
||||
1. Add a `CanvasLayer` to your scene
|
||||
2. Add a `Control` node as child
|
||||
3. Attach the `sky_debug_panel.gd` script
|
||||
4. In Inspector, assign the `DynamicSky` node to the `dynamic_sky` property
|
||||
5. Run and use the UI controls
|
||||
|
||||
### Test 5: Meteor Shower
|
||||
```gdscript
|
||||
func _ready():
|
||||
# Ensure it's night for visibility
|
||||
$DynamicSky.set_time_of_day(0.0)
|
||||
# Wait a moment then trigger
|
||||
await get_tree().create_timer(1.0).timeout
|
||||
$DynamicSky.trigger_meteor_shower(30.0)
|
||||
```
|
||||
|
||||
### Test 6: Kill Volumes
|
||||
1. Add an `Area3D` to your scene
|
||||
2. Attach `weather_kill_volume.gd` script
|
||||
3. Configure the shape and size in Inspector
|
||||
4. Precipitation will be blocked inside this volume
|
||||
|
||||
## Complete Test Scene Example
|
||||
|
||||
Create a new scene with this structure:
|
||||
|
||||
```
|
||||
TestScene (Node3D)
|
||||
├── DynamicSky (instance of dynamic_sky.tscn)
|
||||
├── Camera3D
|
||||
├── Ground (MeshInstance3D with PlaneMesh)
|
||||
├── CanvasLayer
|
||||
│ └── DebugPanel (Control with sky_debug_panel.gd)
|
||||
└── TestScript (Node with test script below)
|
||||
```
|
||||
|
||||
Test script:
|
||||
```gdscript
|
||||
extends Node
|
||||
|
||||
@onready var sky = $"../DynamicSky"
|
||||
|
||||
func _ready():
|
||||
# Generate cloud textures
|
||||
_setup_clouds()
|
||||
|
||||
# Start at mid-morning
|
||||
sky.set_time_of_day(0.35)
|
||||
|
||||
print("Dynamic Sky Test Ready!")
|
||||
print("Arrow keys: Change time")
|
||||
print("1-6: Change weather")
|
||||
print("M: Meteor shower")
|
||||
print("P: Pause/Resume time")
|
||||
|
||||
func _setup_clouds():
|
||||
var cloud_system = sky.cloud_system
|
||||
if cloud_system:
|
||||
for i in cloud_system.layer_configs.size():
|
||||
var tex = ProceduralCloudTexture.create_default_cloud_texture(i)
|
||||
cloud_system.layer_configs[i].texture = tex
|
||||
cloud_system.rebuild_layers()
|
||||
|
||||
var shadow_system = sky.shadow_proxy_system
|
||||
if shadow_system:
|
||||
shadow_system.shadow_texture = ProceduralCloudTexture.create_shadow_texture()
|
||||
|
||||
func _input(event):
|
||||
if event is InputEventKey and event.pressed:
|
||||
match event.keycode:
|
||||
KEY_RIGHT:
|
||||
sky.set_time_of_day(wrapf(sky.get_time_of_day() + 0.02, 0, 1))
|
||||
KEY_LEFT:
|
||||
sky.set_time_of_day(wrapf(sky.get_time_of_day() - 0.02, 0, 1))
|
||||
KEY_1:
|
||||
sky.set_weather(WeatherProfile.WeatherState.CLEAR)
|
||||
KEY_2:
|
||||
sky.set_weather(WeatherProfile.WeatherState.CLOUDY)
|
||||
KEY_3:
|
||||
sky.set_weather(WeatherProfile.WeatherState.OVERCAST)
|
||||
KEY_4:
|
||||
sky.set_weather(WeatherProfile.WeatherState.RAIN)
|
||||
KEY_5:
|
||||
sky.set_weather(WeatherProfile.WeatherState.STORM)
|
||||
KEY_6:
|
||||
sky.set_weather(WeatherProfile.WeatherState.SNOW)
|
||||
KEY_M:
|
||||
sky.trigger_meteor_shower(30.0)
|
||||
KEY_P:
|
||||
if sky.day_night_controller.paused:
|
||||
sky.resume_time()
|
||||
else:
|
||||
sky.pause_time()
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Issue | Solution |
|
||||
|-------|----------|
|
||||
| Script errors on load | Reload project: Project → Reload Current Project |
|
||||
| No sky visible | Ensure camera is looking up; check WorldEnvironment exists |
|
||||
| Clouds not visible | Assign textures to CloudLayerConfig or generate procedurally |
|
||||
| Shadows not visible | Assign shadow_texture to ShadowProxySystem |
|
||||
| Stars not visible | Set time to night (0.0 or 0.9+); check stars_visibility curve |
|
||||
| Time not advancing | Check `paused` is false on DayNightController |
|
||||
| Weather not changing | Check WeatherController has profiles; look at transition progress |
|
||||
|
||||
## Features
|
||||
|
||||
### Preset Skybox Nodes
|
||||
- 6 presets: Clear Day, Sunset, Night, Overcast, Storm, Dawn
|
||||
- Runtime preset switching with smooth transitions
|
||||
- Non-destructive overrides
|
||||
|
||||
### Day/Night Cycle
|
||||
- Configurable day length (1-1440 minutes)
|
||||
- Sun/moon arc movement
|
||||
- Color/intensity curves for sun, moon, ambient, fog
|
||||
- Star visibility at night
|
||||
- Time events (sunrise, sunset, noon)
|
||||
|
||||
### Weather System
|
||||
- States: Clear, Cloudy, Overcast, Rain, Storm, Snow
|
||||
- Smooth transitions between states
|
||||
- Per-state cloud, wind, and VFX settings
|
||||
- Random or scripted weather timelines
|
||||
|
||||
### 2D Cloudscapes
|
||||
- 4 independent layers (low, mid, high, wisps)
|
||||
- Per-layer texture, tiling, opacity, color
|
||||
- Flow animation with wind influence
|
||||
- Evolution/morphing over time
|
||||
- Reactive to sun/moon lighting
|
||||
|
||||
### Post-Processing
|
||||
- Sky gradient shading
|
||||
- Height and distance fog
|
||||
- Sun glow halo
|
||||
- Dawn/dusk enhancement
|
||||
- Procedural stars
|
||||
|
||||
### VFX
|
||||
- Shooting stars (randomized)
|
||||
- Meteor showers (event-triggered)
|
||||
- Configurable appearance
|
||||
|
||||
### Cloud Shadows
|
||||
- Projected shadow overlay
|
||||
- Syncs with cloud movement
|
||||
- Blur and opacity controls
|
||||
|
||||
### Kill Volumes
|
||||
- Block precipitation in indoor areas
|
||||
- Box, sphere, cylinder shapes
|
||||
- Fade-out margins
|
||||
|
||||
## Quick Start
|
||||
|
||||
1. Add `dynamic_sky.tscn` to your scene
|
||||
2. Reference the DynamicSky node in your scripts
|
||||
3. Use the API:
|
||||
|
||||
```gdscript
|
||||
# Get reference
|
||||
@onready var sky = $DynamicSky
|
||||
|
||||
# Set time (0.0-1.0, where 0.5 = noon)
|
||||
sky.set_time_of_day(0.5)
|
||||
|
||||
# Change weather
|
||||
sky.set_weather(WeatherProfile.WeatherState.RAIN)
|
||||
|
||||
# Apply preset
|
||||
sky.apply_preset("Sunset")
|
||||
|
||||
# Trigger meteor shower
|
||||
sky.trigger_meteor_shower(60.0)
|
||||
```
|
||||
|
||||
## Debug Panel
|
||||
|
||||
Add `SkyDebugPanel` to your UI and assign the DynamicSky reference to see:
|
||||
- Current time and weather
|
||||
- Cloud coverage
|
||||
- Controls for testing
|
||||
|
||||
## Resources
|
||||
|
||||
- `SkyConfig`: Global sky parameters
|
||||
- `SkyPreset`: Complete preset configuration
|
||||
- `WeatherProfile`: Per-weather-state settings
|
||||
- `CloudLayerConfig`: Per-layer cloud settings
|
||||
- `PostProcessProfile`: Post-processing parameters
|
||||
|
||||
## Performance
|
||||
|
||||
- Disable unused cloud layers
|
||||
- Reduce cloud texture resolution
|
||||
- Lower VFX update rates
|
||||
- Disable shadow blur on low-end hardware
|
||||
Reference in New Issue
Block a user