From bc2d9eefab73632f3e6a3f066fcc588ff6541b1a Mon Sep 17 00:00:00 2001 From: Sky Johnson Date: Tue, 9 Sep 2025 18:26:31 -0500 Subject: [PATCH] significant work on procedural sky --- client/shaders/sky.fs | 86 +++++++++++++++++++++++++++++++++++++------ client/sky/Sky.cpp | 73 +++++++++++++++++++++++++++++++++++- client/sky/Sky.hpp | 16 ++++++++ 3 files changed, 163 insertions(+), 12 deletions(-) diff --git a/client/shaders/sky.fs b/client/shaders/sky.fs index 2485a84..e6cda6a 100644 --- a/client/shaders/sky.fs +++ b/client/shaders/sky.fs @@ -17,10 +17,20 @@ uniform vec3 zenithColor; uniform vec3 sunDirection; uniform vec3 sunColor; uniform float sunIntensity; +uniform vec3 moonDirection; +uniform vec3 moonColor; +uniform float moonIntensity; +uniform float moonPhase; +uniform float starsIntensity; // Output fragment color out vec4 finalColor; +// Simple hash function for stars +float hash(vec2 p) { + return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453); +} + void main() { // Normalize the world position to get direction from center @@ -32,18 +42,46 @@ void main() // Interpolate between horizon and zenith colors vec3 skyColor = mix(horizonColor, zenithColor, gradientFactor); + // Add stars (only visible at night) + if (starsIntensity > 0.01 && direction.y > -0.1) { // Don't render stars below horizon + // Create a simple star field using noise + vec2 starCoord = direction.xz * 30.0; // Less dense grid + + // Two layers of stars for depth (reduced from 3) + for (int i = 0; i < 2; i++) { + vec2 gridPos = floor(starCoord * (1.0 + float(i) * 0.3)); + vec2 gridFract = fract(starCoord * (1.0 + float(i) * 0.3)); + + float starRandom = hash(gridPos + vec2(float(i) * 13.0, float(i) * 17.0)); + + // Much fewer stars (higher threshold) + if (starRandom > 0.985 + float(i) * 0.005) { + float starBrightness = hash(gridPos + vec2(37.0, 73.0)); + + // Circular star points + vec2 starCenter = vec2(0.5); + float dist = length(gridFract - starCenter); + + if (dist < 0.05) { // Slightly larger star points + float starAlpha = pow(1.0 - dist / 0.05, 1.5) * starsIntensity; + starAlpha *= (0.4 + starBrightness * 0.6); // Vary brightness + skyColor = mix(skyColor, vec3(0.95, 0.95, 1.0), starAlpha); + } + } + } + } + + vec3 color = skyColor; + // Calculate sun contribution vec3 sunDir = normalize(sunDirection); float sunDot = dot(direction, sunDir); - // Sun rendering - vec3 color = skyColor; - // Only render sun if it's above horizon and has intensity if (sunDir.y > 0.0 && sunIntensity > 0.1) { - // Sun disc with soft edges - float sunSize = 0.99; // Smaller value = larger sun - float sunEdge = 0.98; + // Sun disc with soft edges - much smaller + float sunSize = 0.9985; // Much smaller sun (closer to 1.0 = smaller) + float sunEdge = 0.997; if (sunDot > sunSize) { // Bright sun core @@ -51,13 +89,39 @@ void main() } else if (sunDot > sunEdge) { // Soft edge float edge = smoothstep(sunEdge, sunSize, sunDot); - color = mix(skyColor, sunColor, edge); + color = mix(color, sunColor, edge); } - // Sun glow - if (sunDot > 0.85) { - float glow = pow(max(0.0, (sunDot - 0.85) / 0.15), 2.0) * sunIntensity; - color = mix(color, sunColor, glow * 0.5); + // Sun glow - tighter radius + if (sunDot > 0.94) { + float glow = pow(max(0.0, (sunDot - 0.94) / 0.06), 2.0) * sunIntensity; + color = mix(color, sunColor, glow * 0.4); + } + } + + // Calculate moon contribution + vec3 moonDir = normalize(moonDirection); + float moonDot = dot(direction, moonDir); + + // Only render moon if it's above horizon + if (moonDir.y > 0.0 && moonIntensity > 0.1) { + // Moon disc - 15% smaller than before + float moonSize = 0.9992; // Much smaller than sun (sun is 0.9985) + float moonEdge = 0.999; + + if (moonDot > moonSize) { + // Simple moon disc (simplified for smaller size) + color = mix(color, moonColor, moonIntensity); + } else if (moonDot > moonEdge) { + // Soft moon edge + float edge = smoothstep(moonEdge, moonSize, moonDot); + color = mix(color, moonColor * 0.8, edge * moonIntensity); + } + + // Subtle moon glow - even tighter for smaller moon + if (moonDot > 0.98) { + float glow = pow(max(0.0, (moonDot - 0.98) / 0.02), 2.0) * moonIntensity; + color = mix(color, moonColor, glow * 0.1); } } diff --git a/client/sky/Sky.cpp b/client/sky/Sky.cpp index b6748e3..b18e4fd 100644 --- a/client/sky/Sky.cpp +++ b/client/sky/Sky.cpp @@ -12,6 +12,10 @@ Sky::Sky() sun.intensity = 1.0f; sun.angle = 0.0f; + moon.intensity = 1.0f; + moon.phase = 0.5f; // Start with full moon + moon.color = {230, 230, 255, 255}; // Pale blue-white + createSkyDome(); updateColors(); @@ -28,6 +32,11 @@ Sky::Sky() sunDirectionLoc = GetShaderLocation(skyShader, "sunDirection"); sunColorLoc = GetShaderLocation(skyShader, "sunColor"); sunIntensityLoc = GetShaderLocation(skyShader, "sunIntensity"); + moonDirectionLoc = GetShaderLocation(skyShader, "moonDirection"); + moonColorLoc = GetShaderLocation(skyShader, "moonColor"); + moonIntensityLoc = GetShaderLocation(skyShader, "moonIntensity"); + moonPhaseLoc = GetShaderLocation(skyShader, "moonPhase"); + starsIntensityLoc = GetShaderLocation(skyShader, "starsIntensity"); // Assign shader to sky model skyModel.materials[0].shader = skyShader; @@ -62,6 +71,7 @@ void Sky::update(float) { updateColors(); sun.updatePosition(timeOfDay); + moon.updatePosition(timeOfDay); } void Sky::Sun::updatePosition(float timeOfDay) { @@ -90,6 +100,40 @@ void Sky::Sun::updatePosition(float timeOfDay) { direction = Vector3Normalize(Vector3Scale(position, -1.0f)); } +void Sky::Moon::updatePosition(float timeOfDay) { + // Moon follows opposite schedule to sun + // Visible from 6 PM (0.75) to 6 AM (0.25) + // At midnight (0.0), moon is overhead + + float adjustedTime = timeOfDay + 0.25f; // Shift so moon is overhead at midnight + if (adjustedTime > 1.0f) adjustedTime -= 1.0f; + + // Only show moon during nighttime (6pm to 6am) + if (timeOfDay < 0.25f || timeOfDay > 0.75f) { + float nightProgress; + if (timeOfDay > 0.75f) { + nightProgress = (timeOfDay - 0.75f) / 0.5f; // 0 to 0.5 for evening + } else { + nightProgress = (timeOfDay + 0.25f) / 0.5f; // 0.5 to 1 for morning + } + + float angle = nightProgress * PI; // 0 to PI (moonrise to moonset) + + // Calculate moon position in an arc (same as sun but at night) + float moonX = cosf(angle) * 150.0f; // East to West + float moonY = sinf(angle) * 100.0f + 20.0f; // Height arc, minimum 20 units up + float moonZ = 0.0f; + + position = {moonX, moonY, moonZ}; + } else { + // Moon is below horizon during day + position = {0.0f, -100.0f, 0.0f}; + } + + // Direction is from moon to origin + direction = Vector3Normalize(Vector3Scale(position, -1.0f)); +} + void Sky::updateColors() { float t = timeOfDay; @@ -185,8 +229,9 @@ void Sky::renderSkybox(const Camera3D& camera) { rlTranslatef(camera.position.x, camera.position.y, camera.position.z); if (shaderLoaded) { - // First make sure sun position is updated + // First make sure sun and moon positions are updated sun.updatePosition(timeOfDay); + moon.updatePosition(timeOfDay); // Update shader uniforms Vector3 horizonColorVec = { @@ -204,6 +249,11 @@ void Sky::renderSkybox(const Camera3D& camera) { sun.color.g / 255.0f, sun.color.b / 255.0f }; + Vector3 moonColorVec = { + moon.color.r / 255.0f, + moon.color.g / 255.0f, + moon.color.b / 255.0f + }; // Normalize sun direction (make sure it's valid) Vector3 sunDir = {0, 1, 0}; // Default up if sun position is invalid @@ -211,6 +261,22 @@ void Sky::renderSkybox(const Camera3D& camera) { sunDir = Vector3Normalize(sun.position); } + // Normalize moon direction + Vector3 moonDir = {0, -1, 0}; // Default down if moon position is invalid + if (Vector3Length(moon.position) > 0.001f) { + moonDir = Vector3Normalize(moon.position); + } + + // Calculate stars intensity based on time of day (visible at night) + float starsIntensity = 0.0f; + if (timeOfDay < 0.2f || timeOfDay > 0.8f) { + // Full intensity at midnight + if (timeOfDay > 0.5f) { + starsIntensity = (timeOfDay - 0.8f) / 0.2f; + } else { + starsIntensity = 1.0f - (timeOfDay / 0.2f); + } + } // Set shader uniforms SetShaderValue(skyShader, horizonColorLoc, &horizonColorVec, SHADER_UNIFORM_VEC3); @@ -218,6 +284,11 @@ void Sky::renderSkybox(const Camera3D& camera) { SetShaderValue(skyShader, sunDirectionLoc, &sunDir, SHADER_UNIFORM_VEC3); SetShaderValue(skyShader, sunColorLoc, &sunColorVec, SHADER_UNIFORM_VEC3); SetShaderValue(skyShader, sunIntensityLoc, &sun.intensity, SHADER_UNIFORM_FLOAT); + SetShaderValue(skyShader, moonDirectionLoc, &moonDir, SHADER_UNIFORM_VEC3); + SetShaderValue(skyShader, moonColorLoc, &moonColorVec, SHADER_UNIFORM_VEC3); + SetShaderValue(skyShader, moonIntensityLoc, &moon.intensity, SHADER_UNIFORM_FLOAT); + SetShaderValue(skyShader, moonPhaseLoc, &moon.phase, SHADER_UNIFORM_FLOAT); + SetShaderValue(skyShader, starsIntensityLoc, &starsIntensity, SHADER_UNIFORM_FLOAT); // Draw the sky dome with shader DrawModel(skyModel, {0, 0, 0}, 1.0f, WHITE); diff --git a/client/sky/Sky.hpp b/client/sky/Sky.hpp index a5c450b..344bf72 100644 --- a/client/sky/Sky.hpp +++ b/client/sky/Sky.hpp @@ -16,7 +16,18 @@ private: Vector3 getLightDirection() const { return direction; } }; + struct Moon { + Vector3 position; + Vector3 direction; + Color color; + float intensity; + float phase; // 0 = new moon, 0.5 = full moon, 1 = new moon + + void updatePosition(float timeOfDay); + }; + Sun sun; + Moon moon; Color horizonColor; Color zenithColor; Color fogColor; @@ -34,6 +45,11 @@ private: int sunDirectionLoc; int sunColorLoc; int sunIntensityLoc; + int moonDirectionLoc; + int moonColorLoc; + int moonIntensityLoc; + int moonPhaseLoc; + int starsIntensityLoc; public: Sky();