Variable fog of war

This commit is contained in:
2025-08-31 18:00:03 -05:00
parent bef5ff8916
commit b580a34999
3 changed files with 117 additions and 6 deletions

71
main.c
View File

@@ -252,7 +252,43 @@ int main(void)
SetShaderValue(skyboxShader, GetShaderLocation(skyboxShader, "vflipped"), &vflipped, SHADER_UNIFORM_INT); SetShaderValue(skyboxShader, GetShaderLocation(skyboxShader, "vflipped"), &vflipped, SHADER_UNIFORM_INT);
SetShaderValue(skyboxShader, GetShaderLocation(skyboxShader, "doGamma"), &doGamma, SHADER_UNIFORM_INT); SetShaderValue(skyboxShader, GetShaderLocation(skyboxShader, "doGamma"), &doGamma, SHADER_UNIFORM_INT);
// Done now you can draw it // Load the fog-of-war shader
Shader fog = LoadShader(
"resources/shaders/fog.vs",
"resources/shaders/fog.fs"
);
// Grab uniform locations (cache them)
int locPlayer = GetShaderLocation(fog, "u_playerPos");
int locRadius = GetShaderLocation(fog, "u_fogRadius");
int locFeather = GetShaderLocation(fog, "u_fogFeather");
int locFogColor = GetShaderLocation(fog, "u_fogColor");
int locCutoff_fog = GetShaderLocation(fog, "u_alphaCutoff");
int locInner = GetShaderLocation(fog, "u_inner");
int locOuter = GetShaderLocation(fog, "u_outer");
int locMinShadow = GetShaderLocation(fog, "u_minShadow");
// Optional if you added the sharpness curve in the shader
int locSharpness = GetShaderLocation(fog, "u_sharpness");
// 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");
fog.locs[SHADER_LOC_MATRIX_PROJECTION] = GetShaderLocation(fog, "matProjection");
// --- Apply shader to your ground tile model ---
mdlTile.materials[0].shader = fog; // same shader also works for opaque
// (texture0 already set on mdlTile)
// Defaults for opaque geometry (no alpha cut)
float cutoffOpaque = 0.0f;
SetShaderValue(fog, locCutoff_fog, &cutoffOpaque, SHADER_UNIFORM_FLOAT);
// Youll reuse the *same* shader for trees (alpha cut).
// We wont assign it to a Model because billboards arent models;
// instead well render trees inside BeginShaderMode(fog) so they use it.
@@ -376,30 +412,57 @@ int main(void)
{ {
ClearBackground(BLACK); ClearBackground(BLACK);
// Fog/vignette tuning
float inner = 0.0f; // start radius (center under player)
float outer = 45.0f; // how far until full fog
float minShadow = 0.40f; // 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};
SetShaderValue(fog, locPlayer, &g.player.position, SHADER_UNIFORM_VEC3);
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);
// Only if you added sharpness
SetShaderValue(fog, locSharpness, &sharpness, SHADER_UNIFORM_FLOAT);
BeginMode3D(g.player.camera); BeginMode3D(g.player.camera);
rlDisableBackfaceCulling(); rlDisableBackfaceCulling();
rlDisableDepthMask(); rlDisableDepthMask();
// keep it centered on the camera // keep it centered on the camera
skybox.transform = MatrixTranslate( skybox.transform = MatrixTranslate(
g.player.camera.position.x, g.player.camera.position.x,
g.player.camera.position.y, g.player.camera.position.y,
g.player.camera.position.z g.player.camera.position.z
); );
DrawModel(skybox, (Vector3){0}, 1.0f, WHITE); DrawModel(skybox, (Vector3){0}, 1.0f, WHITE);
rlEnableDepthMask(); rlEnableDepthMask();
rlEnableBackfaceCulling(); rlEnableBackfaceCulling();
DrawLevel(mdlTile); DrawLevel(mdlTile);
/*
BeginShaderMode(shAlphaClip); BeginShaderMode(shAlphaClip);
{ {
RenderTrees(&g, tree, treepos, treeSize); RenderTrees(&g, tree, treepos, treeSize);
} }
EndShaderMode(); EndShaderMode();
*/
// --- Trees use same fog shader but with alpha-cut enabled ---
float cutoffAlpha = 0.3f;
SetShaderValue(fog, locCutoff_fog, &cutoffAlpha, SHADER_UNIFORM_FLOAT);
BeginShaderMode(fog);
RenderTrees(&g, tree, treepos, treeSize);
EndShaderMode();
// Restore opaque cutoff for anything else you draw with that material later
SetShaderValue(fog, locCutoff_fog, &cutoffOpaque, SHADER_UNIFORM_FLOAT);
//DrawBillboard(g.player.camera, sign, bbPos, bbSize, WHITE); //This was the texture chasing you. //DrawBillboard(g.player.camera, sign, bbPos, bbSize, WHITE); //This was the texture chasing you.
EndMode3D(); EndMode3D();

32
resources/shaders/fog.fs Normal file
View File

@@ -0,0 +1,32 @@
#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);
}

16
resources/shaders/fog.vs Normal file
View File

@@ -0,0 +1,16 @@
#version 330
in vec3 vertexPosition;
in vec2 vertexTexCoord;
uniform mat4 matModel, matView, matProjection;
out vec3 vWorldPos;
out vec2 vTexCoord;
void main()
{
vec4 world = matModel * vec4(vertexPosition, 1.0);
vWorldPos = world.xyz;
vTexCoord = vertexTexCoord;
gl_Position = matProjection * matView * world;
}