Basic flashlight

This commit is contained in:
2025-08-31 22:08:18 -05:00
parent a1fede92f3
commit d7363921ad
6 changed files with 113 additions and 39 deletions

47
main.c
View File

@@ -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.71.5 to taste
float beamSpread = 0.00f; // try 0.150.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);

View File

@@ -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);
}

73
shaders/fog.fs Normal file
View File

@@ -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);
}