This document outlines the current visual state of Candy World and provides a roadmap for advancing from the current quality level to the next tier of visual fidelity. The focus is on enhancing the weather system integration with day/night cycles, improving material quality, and ensuring aesthetic consistency across all visual elements.
Implemented Features:
- ✅ Three weather states: Clear, Rain, Storm
- ✅ Audio-reactive weather transitions
- ✅ Particle systems: Percussion Rain (fat droplets) and Melodic Mist (fine spray)
- ✅ Lightning effects during storms
- ✅ Wind system with directional influence
- ✅ Fog density adjustment based on weather
- ✅ Berry charging and plant growth mechanics
Weather-Cycle Integration:
- ✅ Basic weather states exist independently of day/night cycle
⚠️ Weather does NOT automatically vary by time of day⚠️ No dawn mist, afternoon thunderstorms, or night drizzle variations⚠️ Weather is purely audio-driven, not time-synchronized
Implemented Features:
- ✅ 16-minute cycle: Sunrise (1m) → Day (7m) → Sunset (1m) → Night (7m)
- ✅ Sky gradient using TSL (Three.js Shading Language)
- ✅ Color palette transitions: Sunrise, Day, Sunset, Night
- ✅ Sun arc animation across sky
- ✅ Deep Night phase with fireflies
- ✅ Fog density changes (thicker at night)
- ✅ Star visibility toggle
Lighting Quality:
- ✅ Hemisphere light for ambient (sky/ground colors)
- ✅ Directional sun with shadows (1024x1024 shadow maps)
- ✅ Sun glow plane (billboard) for bloom source
- ✅ Point lights on glowing flowers and mushrooms
⚠️ No volumetric fog or god rays⚠️ No atmospheric scattering simulation
Technique:
- ✅ Sphere geometry (1000 units radius, 16x8 segments)
- ✅ TSL gradient shader (positionWorld → height-based color mix)
- ✅ Smooth color transitions via uniforms (
uSkyTopColor,uSkyBottomColor) - ✅ Dynamic palette per cycle phase
Quality Assessment:
⚠️ Low-poly sphere (128 total segments) - visible facets at horizon⚠️ Simple 2-color gradient - lacks cloud layer detail⚠️ No atmospheric perspective or haze simulation⚠️ Stars are simple point sprites with uniform pulse
Material Types:
-
Clay Materials - Matte, organic look (roughness 0.8)
- Used for: Ground, grass, flower petals, mushrooms
- Technique: Noise texture bump map (256x256)
- Quality: Basic but consistent
-
Glossy Candy Materials - Physical materials with clearcoat
- Used for: Berries (SSS transmission), some flowers
- Technique: MeshPhysicalMaterial with transmission, thickness
- Quality: Good for candy aesthetic
-
Emissive Reactive Materials - Audio-reactive glow
- Used for: Night flowers, mushrooms, willow tips
- Technique: Dynamic emissive color/intensity updates
- Quality: Effective but limited palette
-
Gradient Materials - TSL node-based color mixing
- Used for: Tree trunks (dark base → light top)
- Technique: positionLocal.y lerp
- Quality: Smooth transitions
Texture Assessment:
⚠️ Single shared noise texture (256x256) - repetitive⚠️ No PBR texture maps (normal, roughness, metallic)⚠️ No detail maps or surface imperfections⚠️ Procedural geometry only - no UV-mapped textures
Strengths:
- ✅ Consistent pastel color palette
- ✅ Unified clay/candy aesthetic throughout
- ✅ Smooth, rounded organic shapes
- ✅ Good use of SSS for berries (translucent glow)
Weaknesses:
⚠️ Weather feels disconnected from time of day⚠️ Sky is too uniform - lacks cloud detail⚠️ Materials don't respond to weather state (no wet/dry variation)⚠️ Lighting doesn't reflect storm intensity (except lightning flashes)⚠️ No environmental storytelling through weather patterns
Objective: Make weather feel natural and time-synchronized
Implementation Tasks:
-
Time-of-Day Weather Patterns
- Morning mist during sunrise (DURATION_SUNRISE phase)
- Afternoon storms (mid-DAY phase, weighted probability)
- Evening drizzle (SUNSET → DUSK transition)
- Clear nights with star visibility
-
Weather State Transitions
- Gradual weather state changes (not instant)
- Cloud formation animation (particle systems)
- Wind speed tied to weather intensity
- Fog density gradients (thick at edges, thin at center)
-
Visual Feedback
- Sky color shifts during storms (darker, more saturated)
- Sun dimming effect during rain
- Lightning illuminates clouds from within
- Rain droplets reflect ambient light color
Technical Approach:
// In main.js animate() loop:
function getWeatherForTimeOfDay(cyclePos, CYCLE_DURATION) {
const SUNRISE = 60, DAY = 420, SUNSET = 60;
// Morning mist
if (cyclePos < SUNRISE + 60) {
return { state: WeatherState.RAIN, intensity: 0.3, type: 'mist' };
}
// Afternoon storm chance (20% during mid-day)
else if (cyclePos > SUNRISE + 120 && cyclePos < SUNRISE + DAY - 60) {
if (Math.random() < 0.002) { // Per-frame chance
return { state: WeatherState.STORM, intensity: 0.8, type: 'thunderstorm' };
}
}
// Evening drizzle
else if (cyclePos > SUNRISE + DAY && cyclePos < SUNRISE + DAY + SUNSET + 60) {
return { state: WeatherState.RAIN, intensity: 0.4, type: 'drizzle' };
}
return { state: WeatherState.CLEAR, intensity: 0, type: 'clear' };
}Objective: Add depth and detail to sky without breaking aesthetic
Implementation Tasks:
-
Procedural Cloud Layer
- Add mid-altitude cloud geometry (500-700 units)
- Use noise function for cloud density (fbm from WASM)
- Animate clouds with wind direction
- Clouds cast shadows on ground (secondary shadow map)
-
Atmospheric Scattering (Simplified)
- Rayleigh scattering approximation (blue sky)
- Mie scattering for sun glow
- Horizon haze using depth-based fog color lerp
- Sun color temperature shift at sunrise/sunset
-
Star Field Enhancement
- Increase star density (current: basic)
- Add star twinkle animation (varying sizes)
- Milky Way band using particle ribbon
- Moon object with phase cycle
Technical Approach:
// Enhanced sky shader with atmospheric approximation
const atmosphereNode = (() => {
const viewDir = positionWorld.normalize();
const sunDir = uniform(vec3(0, 1, 0)); // Updated per frame
const dotProduct = viewDir.dot(sunDir).max(0.0);
// Rayleigh (blue sky)
const rayleigh = color(0x4A7BB7).mul(float(1.0).sub(dotProduct.pow(0.5)));
// Mie (sun glow)
const mie = color(0xFFFAF0).mul(dotProduct.pow(10.0));
// Mix with base gradient
return mix(baseGradient, rayleigh.add(mie), float(0.6));
})();Objective: Add surface detail without losing candy aesthetic
Implementation Tasks:
-
Wet Surface Simulation
- During rain: reduce roughness, increase metalness slightly
- Add specular highlights to simulate water droplets
- Darken albedo color (wet = darker)
- Restore dry state gradually after rain stops
-
Enhanced Noise Textures
- Generate 3-channel noise (R=fine, G=medium, B=coarse)
- Use for detail normal map (per-material scale)
- Add slight color variation (not grayscale)
- Tile seamlessly using domain warping
-
Subsurface Scattering Improvements
- Berries: increase transmission during day (backlit)
- Flowers: add thin-film interference (petals)
- Mushrooms: gradient SSS (cap = translucent, stem = opaque)
-
Audio-Reactive Material Enhancements
- Pulse emissive color based on frequency spectrum
- Iridescent shift (HSL rotation) on music channels
- Smooth transitions (not jarring flashes)
Technical Approach:
// Wet material transition
function applyWetEffect(material, wetAmount) {
const dryRoughness = material.userData.dryRoughness || material.roughness;
const dryMetalness = material.userData.dryMetalness || material.metalness;
material.roughness = THREE.MathUtils.lerp(dryRoughness, 0.2, wetAmount);
material.metalness = THREE.MathUtils.lerp(dryMetalness, 0.3, wetAmount);
// Darken color
material.color.lerp(new THREE.Color(0x000000), wetAmount * 0.3);
}Objective: More dramatic and responsive lighting
Implementation Tasks:
-
Shadow Quality
- Increase shadow map size to 2048x2048 for sun (performance budget)
- Add soft shadows using PCF filtering
- Dynamic shadow distance (closer at night for detail)
- Self-shadowing on plants (receiveShadow on petals)
-
Storm Lighting
- Ambient light intensity drops during storms
- Lightning should illuminate entire scene (flash ambient)
- Thunder sound sync with lightning (audio system)
- Clouds glow from within during lightning
-
Volumetric Effects (Fake)
- Sun shaft sprites (billboards along sun ray)
- Fog particles in front of camera (depth-sorted)
- Glow around moon and sun (additive blend)
- Light bleeding from glowing objects (bloom pass)
Technical Approach:
// Storm lighting pulse
if (weatherSystem.state === WeatherState.STORM && lightningActive) {
const flashIntensity = lightningLight.intensity / 5.0; // 0-2
ambientLight.intensity += flashIntensity * 0.5;
sunLight.intensity += flashIntensity * 0.3;
// Flash fog color
scene.fog.color.lerp(new THREE.Color(0xFFFFFF), flashIntensity * 0.2);
}Objective: Maintain 60 FPS with enhanced visuals
Implementation Tasks:
-
LOD System for Foliage
- High detail: < 20 units from camera
- Medium detail: 20-50 units
- Low detail: > 50 units (instanced billboards)
- Culling: > 100 units (don't render)
-
Shader Optimization
- Avoid per-fragment noise (pre-bake to texture)
- Use uniforms for constant values
- Minimize branching in shaders
- Group materials to reduce state changes
-
Smart Particle Systems
- Pool rain droplets (reuse, don't recreate)
- Reduce particle count at distance
- Use GPU-based particle animation (TSL)
- Cull particles outside frustum
-
Texture Compression
- Use KTX2 compressed textures (Basis Universal)
- Generate mipmaps for all textures
- Reduce texture size for distant objects
- Share textures across similar materials
Tasks:
- Add
getWeatherForTimeOfDay()function to main.js - Modify
weatherSystem.update()to accept cycle phase - Implement weather state transition smoothing
- Add sky color modulation during storms
- Test and balance weather probabilities
Success Criteria:
- Weather feels natural throughout day/night cycle
- Storms occur during afternoon (player expectation)
- Morning mist creates atmosphere
- No jarring transitions
Tasks:
- Create procedural cloud layer (new file:
clouds.js) - Implement atmospheric scattering approximation
- Enhance star field with twinkle and density
- Add moon object with phase cycle
- Optimize sky sphere geometry (32x16 segments)
Success Criteria:
- Sky has visual depth and interest
- Clouds move naturally with wind
- Sunrise/sunset more dramatic
- Night sky is beautiful
Tasks:
- Implement wet surface simulation
- Generate enhanced noise textures (3-channel)
- Improve SSS on berries and flowers
- Add audio-reactive color shifting
- Test performance impact
Success Criteria:
- Materials respond to weather state
- Surfaces have tactile detail
- Candy aesthetic preserved
- 60 FPS maintained
Tasks:
- Increase shadow map resolution
- Implement storm lighting pulse
- Add fake volumetric effects (sun shafts)
- Optimize shadow distance
- Add bloom post-processing (optional)
Success Criteria:
- Lighting is more dramatic
- Storms feel intense
- Performance impact minimized
- Visual consistency maintained
Tasks:
- Implement LOD system for foliage
- Profile and optimize shaders
- Pool particle systems
- Add texture compression
- Final balancing and tuning
Success Criteria:
- 60 FPS on target hardware
- No visual regressions
- Code is maintainable
- Documentation updated
- Browser: Chrome 113+, Edge 113+ (WebGPU required)
- Hardware: Integrated GPU (Intel UHD 620 or equivalent)
- Resolution: 1920x1080
- Frame Rate: 60 FPS sustained
- Draw Calls: < 200
- Triangles: < 500k
- Texture Memory: < 256 MB
- Shader Complexity: < 200 instructions per material
- Particle Count: < 10k total
- Shadow Resolution: 2048x2048 (sun only)
- Texture Resolution: 512x512 (base), 256x256 (detail)
- Fog Range: 20-100 units (dynamic)
- Animation Frame Rate: 60 FPS (no jank)
Current: Pastel candy colors (limited)
Next Level: Add color harmonies and contrasts
Storm Palette:
- Sky: Dark purples and deep blues (#1A1A2E, #2E3A59)
- Lightning: Bright cyan-white (#E0FFFF, #FFFFFF)
- Rain: Cool grays with blue tint (#A0B5C8)
Sunset Palette Enhancement:
- Horizon: Orange-pink gradients (#FF6B35, #FF006E)
- Clouds: Purple and gold (#7209B7, #FFD700)
- Ambient: Warm amber (#FFBE0B)
Night Palette Enhancement:
- Sky: Deep midnight blue with purple tint (#0A0E27, #1E1E3F)
- Stars: White to pale blue (#FFFFFF, #CAE9FF)
- Fireflies: Yellow-green (#88FF00)
Dry State:
- Matte finish (roughness 0.8)
- Subtle color variation
- Soft shadows
Wet State:
- Semi-glossy (roughness 0.3)
- Darker, saturated colors
- Sharp specular highlights
Glowing State (Night):
- Emissive colors match audio spectrum
- Soft light falloff
- Subtle pulsing
- Weather transitions feel natural and gradual
- Sky has depth and interest at all times of day
- Materials respond appropriately to weather
- Lighting creates mood and atmosphere
- Performance remains stable at 60 FPS
- No visual artifacts or glitches
- Color palette remains consistent
- Audio-reactivity is smooth, not jarring
- Immersion: Player feels weather is "real" not scripted
- Clarity: Weather state is immediately obvious
- Surprise: Occasional storms create memorable moments
- Beauty: Every phase of day/night is photogenic
- Performance: No frame drops or stuttering
- Real-time global illumination (WebGPU compute shaders)
- Volumetric clouds (ray-marched)
- Water surfaces with reflections and caustics
- Advanced weather: snow, fog layers, aurora
- Seasonal changes (spring blooms, autumn leaves)
- Dynamic weather system (pressure fronts, wind patterns)
- Refactor foliage.js (currently 2100+ lines)
- Separate material system into its own module
- Add TypeScript type definitions
- Implement scene graph optimization
- Add debug visualization tools
Vertex Buffer Limits: We are staying under the 8 maximum vertex buffers to support GPUs like the GTX 1060, but not demanding above that. This ensures broad compatibility across hardware while maintaining complex shader pipelines for candy aesthetics.
This plan provides a clear path from the current baseline quality to the next level of visual fidelity. By focusing on weather-cycle integration, enhanced sky rendering, material quality, and lighting improvements, Candy World will achieve a more cohesive and immersive visual experience while maintaining its unique candy aesthetic and 60 FPS performance target.
Key Principle: Every enhancement should serve the core aesthetic and never compromise the playful, organic, candy-colored vision of the world.