From d7363921add3fa9b2800d7170e49b29911146bb3 Mon Sep 17 00:00:00 2001 From: cwj3rcb Date: Sun, 31 Aug 2025 22:08:18 -0500 Subject: [PATCH] Basic flashlight --- main.c | 47 ++++++++++++--- resources/shaders/fog.fs | 32 ----------- shaders/fog.fs | 73 ++++++++++++++++++++++++ {resources/shaders => shaders}/fog.vs | 0 {resources/shaders => shaders}/skybox.fs | 0 {resources/shaders => shaders}/skybox.vs | 0 6 files changed, 113 insertions(+), 39 deletions(-) delete mode 100644 resources/shaders/fog.fs create mode 100644 shaders/fog.fs rename {resources/shaders => shaders}/fog.vs (100%) rename {resources/shaders => shaders}/skybox.fs (100%) rename {resources/shaders => shaders}/skybox.vs (100%) diff --git a/main.c b/main.c index 4dd6ba5..86aaaa3 100644 --- a/main.c +++ b/main.c @@ -200,8 +200,8 @@ int main(void) // Load skybox shader Shader skyboxShader = LoadShader( - "resources/shaders/skybox.vs", - "resources/shaders/skybox.fs" + "shaders/skybox.vs", + "shaders/skybox.fs" ); // Attach shader to skybox @@ -221,7 +221,7 @@ int main(void) SetShaderValue(skyboxShader, GetShaderLocation(skyboxShader, "doGamma"), &doGamma, SHADER_UNIFORM_INT); // Load the fog-of-war shader - Shader fog = LoadShader("resources/shaders/fog.vs", "resources/shaders/fog.fs"); + Shader fog = LoadShader("shaders/fog.vs", "shaders/fog.fs"); // Grab uniform locations (cache them) int locPlayer = GetShaderLocation(fog, "u_playerPos"); @@ -236,6 +236,16 @@ int main(void) // Optional if you added the sharpness curve in the shader int locSharpness = GetShaderLocation(fog, "u_sharpness"); + //Flashlight + int locSpotDir = GetShaderLocation(fog, "u_spotDir"); + int locSpotCos = GetShaderLocation(fog, "u_spotCos"); + int locSpotSoft = GetShaderLocation(fog, "u_spotSoft"); + int locLightRange = GetShaderLocation(fog, "u_lightRange"); + int locLightFade = GetShaderLocation(fog, "u_lightFade"); + int locIntensity = GetShaderLocation(fog, "u_intensity"); + int locBeamSpread = GetShaderLocation(fog, "u_beamSpread"); + + // Let raylib know which matrices the shader expects fog.locs[SHADER_LOC_MATRIX_MODEL] = GetShaderLocation(fog, "matModel"); fog.locs[SHADER_LOC_MATRIX_VIEW] = GetShaderLocation(fog, "matView"); @@ -250,17 +260,33 @@ int main(void) // Fog/vignette tuning float inner = 0.0f; // start radius (center under player) - float outer = 45.0f; // how far until full fog - float minShadow = 0.45f; // baseline darkness at the center (0 = none, 1 = pitch black) + float outer = 20.0f; // how far until full fog + float minShadow = 0.9f; // baseline darkness at the center (0 = none, 1 = pitch black) float sharpness = 2.0f; // steeper edge (optional if shader uses it) Vector4 fogColor = {0.0f, 0.0f, 0.0f, 1.0f}; - + + // Flashligh tuning + float spotAngleDeg = 35.0f; //cone angle + float spotCos = cosf(DEG2RAD * (spotAngleDeg * 0.5f)); + float spotSoft = 0.05f; + float lightRange = 150.0f; + float lightFade = 10.0f; + float intensity = 0.25f; // try 0.7–1.5 to taste + float beamSpread = 0.00f; // try 0.15–0.35; higher = less “laser” at distance + + SetShaderValue(fog, locIntensity, &intensity, SHADER_UNIFORM_FLOAT); + SetShaderValue(fog, locBeamSpread, &beamSpread, SHADER_UNIFORM_FLOAT); + SetShaderValue(fog, locSpotCos, &spotCos, SHADER_UNIFORM_FLOAT); + SetShaderValue(fog, locSpotSoft, &spotSoft, SHADER_UNIFORM_FLOAT); + SetShaderValue(fog, locLightRange, &lightRange, SHADER_UNIFORM_FLOAT); + SetShaderValue(fog, locLightFade, &lightFade, SHADER_UNIFORM_FLOAT); SetShaderValue(fog, locInner, &inner, SHADER_UNIFORM_FLOAT); SetShaderValue(fog, locOuter, &outer, SHADER_UNIFORM_FLOAT); SetShaderValue(fog, locMinShadow, &minShadow, SHADER_UNIFORM_FLOAT); SetShaderValue(fog, locFogColor, &fogColor, SHADER_UNIFORM_VEC4); SetShaderValue(fog, locSharpness, &sharpness, SHADER_UNIFORM_FLOAT); + //-------------------------------------------------------------------------------------- // Main game loop @@ -367,8 +393,15 @@ int main(void) case STATE_GAME: { ClearBackground(BLACK); + + Vector3 camPos = g.player.camera.position; + Vector3 camFwd = Vector3Normalize(Vector3Subtract(g.player.camera.target, camPos)); - SetShaderValue(fog, locPlayer, &g.player.position, SHADER_UNIFORM_VEC3); + // Camera forward (normalize target - position) + Vector3 forward = Vector3Normalize(Vector3Subtract(g.player.camera.target, g.player.camera.position)); + + SetShaderValue(fog, locPlayer, &camPos, SHADER_UNIFORM_VEC3); + SetShaderValue(fog, locSpotDir, &camFwd, SHADER_UNIFORM_VEC3); BeginMode3D(g.player.camera); diff --git a/resources/shaders/fog.fs b/resources/shaders/fog.fs deleted file mode 100644 index 44318d7..0000000 --- a/resources/shaders/fog.fs +++ /dev/null @@ -1,32 +0,0 @@ -#version 330 - -in vec3 vWorldPos; -in vec2 vTexCoord; - -uniform sampler2D texture0; -uniform vec3 u_playerPos; // player world pos -uniform float u_inner; // start of vignette (m) -uniform float u_outer; // end of vignette (m) u_outer > u_inner -uniform float u_minShadow; // baseline darkness at center [0..1], e.g. 0.15 -uniform vec4 u_fogColor; // usually vec4(0,0,0,1) -uniform float u_alphaCutoff; // for trees/billboards too - -out vec4 finalColor; - -void main() -{ - vec4 texel = texture(texture0, vTexCoord); - if (texel.a < u_alphaCutoff) discard; - - // distance on the ground plane - float distXZ = length(vWorldPos.xz - u_playerPos.xz); - - // 0 at u_inner, 1 at u_outer - float t = smoothstep(u_inner, u_outer, distXZ); - - // add baseline shadow so center is not fully bright - t = u_minShadow + (1.0 - u_minShadow) * t; - - vec3 rgb = mix(texel.rgb, u_fogColor.rgb, t); - finalColor = vec4(rgb, texel.a); -} diff --git a/shaders/fog.fs b/shaders/fog.fs new file mode 100644 index 0000000..7c3f3ce --- /dev/null +++ b/shaders/fog.fs @@ -0,0 +1,73 @@ +#version 330 core + +in vec2 vTexCoord; +in vec3 vWorldPos; + +uniform sampler2D texture0; + +// --- Soft bubble (kept) --- +uniform vec3 u_playerPos; +uniform float u_inner; +uniform float u_outer; +uniform float u_minShadow; + +// --- Flashlight cone + distance --- +uniform vec3 u_spotDir; // normalized camera forward +uniform float u_spotCos; // cos(half-angle) +uniform float u_spotSoft; // base penumbra width in cos-space +uniform float u_lightRange; // bright zone distance (>0) +uniform float u_lightFade; // fade width beyond range + +// --- NEW: decouple brightness + widen with distance --- +uniform float u_intensity; // flashlight peak brightness (independent of range) +uniform float u_beamSpread; // additional penumbra growth per unit distance (0..~0.5) + +// Alpha cut (trees, grass) +uniform float u_alphaCutoff; + +out vec4 finalColor; + +// Helpers +float remap01(float x, float a, float b) { + return clamp((x - a) / max(b - a, 1e-5), 0.0, 1.0); +} +float invsq(float d, float r) { + float s = d / max(r, 1e-4); + return 1.0 / (1.0 + s*s); +} + +void main() { + vec4 texel = texture(texture0, vTexCoord); + if (texel.a < u_alphaCutoff) discard; + + float dist = length(vWorldPos - u_playerPos); + + // (A) Soft ambient bubble around the player (unchanged) + float bubble = 1.0 - remap01(dist, u_inner, u_outer); // 1 near, 0 far + float ambient = mix(1.0 - clamp(u_minShadow,0.0,1.0), 0.0, 1.0 - bubble); + + // (B) Flashlight cone with penumbra + distance drop + widening + vec3 L = normalize(vWorldPos - u_playerPos); + float cosTheta = dot(normalize(u_spotDir), L); + + // Widen penumbra with distance so long ranges don't look like a laser + float distNorm = dist / max(u_lightRange, 1e-4); + float softWide = clamp(u_spotSoft + u_beamSpread * distNorm, 0.0, 0.8); + + float innerEdge = u_spotCos; + float outerEdge = clamp(u_spotCos - softWide, -1.0, 1.0); + + float spotA = smoothstep(outerEdge, innerEdge, cosTheta); + spotA *= spotA; // mild hotspot + + // Distance attenuation: inverse-square * soft fade band + float band = 1.0 - remap01(dist, u_lightRange, u_lightRange + u_lightFade); + float lightD = invsq(dist, u_lightRange) * band; + + // Decoupled brightness + float flashlight = u_intensity * spotA * lightD; + + // Compose + float light = clamp(ambient + flashlight, 0.0, 1.0); + finalColor = vec4(texel.rgb * light, texel.a); +} diff --git a/resources/shaders/fog.vs b/shaders/fog.vs similarity index 100% rename from resources/shaders/fog.vs rename to shaders/fog.vs diff --git a/resources/shaders/skybox.fs b/shaders/skybox.fs similarity index 100% rename from resources/shaders/skybox.fs rename to shaders/skybox.fs diff --git a/resources/shaders/skybox.vs b/shaders/skybox.vs similarity index 100% rename from resources/shaders/skybox.vs rename to shaders/skybox.vs