feat(rendering): distance fog and config-derived far plane
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
in vec2 vUv;
|
||||
in float vShade;
|
||||
in float vWorldY;
|
||||
in vec3 vWorldPos;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
@@ -10,11 +11,25 @@ uniform float u_caveDarkStartY;
|
||||
uniform float u_caveDarkEndY;
|
||||
uniform float u_caveMinBrightness;
|
||||
|
||||
uniform vec3 u_cameraPos;
|
||||
uniform float u_fogStart;
|
||||
uniform float u_fogEnd;
|
||||
uniform vec3 u_skyColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 texel = texture(atlas, vUv);
|
||||
|
||||
// Y-based cave darkness.
|
||||
float t = clamp((u_caveDarkStartY - vWorldY) /
|
||||
(u_caveDarkStartY - u_caveDarkEndY), 0.0, 1.0);
|
||||
float brightness = mix(1.0, u_caveMinBrightness, t);
|
||||
FragColor = vec4(texel.rgb * vShade * brightness, 1.0);
|
||||
vec3 color = texel.rgb * vShade * brightness;
|
||||
|
||||
// Distance fog to the sky color, applied after cave darkness.
|
||||
float dist = length(vWorldPos - u_cameraPos);
|
||||
float fog = clamp((dist - u_fogStart) / (u_fogEnd - u_fogStart), 0.0, 1.0);
|
||||
color = mix(color, u_skyColor, fog);
|
||||
|
||||
FragColor = vec4(color, 1.0);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ layout(location = 2) in float aShade;
|
||||
out vec2 vUv;
|
||||
out float vShade;
|
||||
out float vWorldY;
|
||||
out vec3 vWorldPos;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
@@ -17,6 +18,7 @@ void main()
|
||||
vShade = aShade;
|
||||
// World-space position uses row-vector convention (matches gl_Position below).
|
||||
vec4 worldPos = vec4(aPos, 1.0) * model;
|
||||
vWorldPos = worldPos.xyz;
|
||||
vWorldY = worldPos.y;
|
||||
gl_Position = worldPos * view * projection;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ public sealed class Game : GameWindow
|
||||
Log.Information("Game starting with seed={Seed} renderDistanceH={H} renderDistanceV={V}",
|
||||
this._cfg.Seed, this._cfg.RenderDistanceHorizontal, this._cfg.RenderDistanceVertical);
|
||||
|
||||
GL.ClearColor(0.45f, 0.65f, 0.95f, 1.0f);
|
||||
GL.ClearColor(this._cfg.SkyColor.X, this._cfg.SkyColor.Y, this._cfg.SkyColor.Z, 1.0f);
|
||||
GL.Enable(EnableCap.DepthTest);
|
||||
GL.Enable(EnableCap.CullFace);
|
||||
|
||||
@@ -119,6 +119,11 @@ public sealed class Game : GameWindow
|
||||
this._shader.SetFloat("u_caveDarkStartY", this._cfg.CaveDarkStartY);
|
||||
this._shader.SetFloat("u_caveDarkEndY", this._cfg.CaveDarkEndY);
|
||||
this._shader.SetFloat("u_caveMinBrightness", this._cfg.CaveMinBrightness);
|
||||
float fogEnd = this._cfg.RenderDistanceHorizontal * Chunk.Size;
|
||||
this._shader.SetFloat("u_fogEnd", fogEnd);
|
||||
this._shader.SetFloat("u_fogStart", fogEnd * this._cfg.FogStartFraction);
|
||||
this._shader.SetVector3("u_cameraPos", this._player.Camera.Position);
|
||||
this._shader.SetVector3("u_skyColor", this._cfg.SkyColor);
|
||||
this._texture.Use(TextureUnit.Texture0);
|
||||
|
||||
this._streamer.DrawAll((pos, renderer) =>
|
||||
|
||||
@@ -29,7 +29,11 @@ public sealed class Player
|
||||
public Player(Configuration cfg, Vector3 spawnPosition, float aspectRatio)
|
||||
{
|
||||
this._cfg = cfg;
|
||||
this.Camera = new Camera(spawnPosition, aspectRatio) { Fov = cfg.Fov };
|
||||
this.Camera = new Camera(spawnPosition, aspectRatio)
|
||||
{
|
||||
Fov = cfg.Fov,
|
||||
FarPlane = (cfg.RenderDistanceHorizontal + 1) * VoxelChunk.Size,
|
||||
};
|
||||
}
|
||||
|
||||
public void Move(Vector3 delta) => this.Camera.Move(delta);
|
||||
|
||||
@@ -10,6 +10,7 @@ public sealed class Camera
|
||||
public float Yaw { get; private set; } = -90f; // degrees; -90 looks down -Z
|
||||
public float Pitch { get; private set; } // degrees
|
||||
public float Fov { get; set; } = 60f; // degrees
|
||||
public float FarPlane { get; set; } = 100f; // world units
|
||||
public float AspectRatio { get; set; }
|
||||
|
||||
public Vector3 Front { get; private set; } = -Vector3.UnitZ;
|
||||
@@ -36,7 +37,7 @@ public sealed class Camera
|
||||
|
||||
public Matrix4 GetProjectionMatrix() =>
|
||||
Matrix4.CreatePerspectiveFieldOfView(
|
||||
MathHelper.DegreesToRadians(this.Fov), this.AspectRatio, 0.1f, 100f);
|
||||
MathHelper.DegreesToRadians(this.Fov), this.AspectRatio, 0.1f, this.FarPlane);
|
||||
|
||||
private void UpdateVectors()
|
||||
{
|
||||
|
||||
@@ -39,6 +39,9 @@ public sealed class Shader : IDisposable
|
||||
public void SetFloat(string name, float value) =>
|
||||
GL.Uniform1(this.Location(name), value);
|
||||
|
||||
public void SetVector3(string name, Vector3 value) =>
|
||||
GL.Uniform3(this.Location(name), value.X, value.Y, value.Z);
|
||||
|
||||
private int Location(string name)
|
||||
{
|
||||
if (this._uniforms.TryGetValue(name, out int location)) return location;
|
||||
|
||||
@@ -40,4 +40,12 @@ public class CameraTests
|
||||
var camera = new Camera(Vector3.Zero, 1.5f);
|
||||
Assert.NotEqual(Matrix4.Identity, camera.GetProjectionMatrix());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FarPlane_ChangesProjection()
|
||||
{
|
||||
var near = new Camera(Vector3.Zero, 1f) { FarPlane = 100f };
|
||||
var far = new Camera(Vector3.Zero, 1f) { FarPlane = 200f };
|
||||
Assert.NotEqual(near.GetProjectionMatrix(), far.GetProjectionMatrix());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user