Basic flashlight
This commit is contained in:
73
shaders/fog.fs
Normal file
73
shaders/fog.fs
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user