feat(rendering): distance fog and config-derived far plane
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
in vec2 vUv;
|
in vec2 vUv;
|
||||||
in float vShade;
|
in float vShade;
|
||||||
in float vWorldY;
|
in float vWorldY;
|
||||||
|
in vec3 vWorldPos;
|
||||||
|
|
||||||
out vec4 FragColor;
|
out vec4 FragColor;
|
||||||
|
|
||||||
@@ -10,11 +11,25 @@ uniform float u_caveDarkStartY;
|
|||||||
uniform float u_caveDarkEndY;
|
uniform float u_caveDarkEndY;
|
||||||
uniform float u_caveMinBrightness;
|
uniform float u_caveMinBrightness;
|
||||||
|
|
||||||
|
uniform vec3 u_cameraPos;
|
||||||
|
uniform float u_fogStart;
|
||||||
|
uniform float u_fogEnd;
|
||||||
|
uniform vec3 u_skyColor;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec4 texel = texture(atlas, vUv);
|
vec4 texel = texture(atlas, vUv);
|
||||||
|
|
||||||
|
// Y-based cave darkness.
|
||||||
float t = clamp((u_caveDarkStartY - vWorldY) /
|
float t = clamp((u_caveDarkStartY - vWorldY) /
|
||||||
(u_caveDarkStartY - u_caveDarkEndY), 0.0, 1.0);
|
(u_caveDarkStartY - u_caveDarkEndY), 0.0, 1.0);
|
||||||
float brightness = mix(1.0, u_caveMinBrightness, t);
|
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 vec2 vUv;
|
||||||
out float vShade;
|
out float vShade;
|
||||||
out float vWorldY;
|
out float vWorldY;
|
||||||
|
out vec3 vWorldPos;
|
||||||
|
|
||||||
uniform mat4 model;
|
uniform mat4 model;
|
||||||
uniform mat4 view;
|
uniform mat4 view;
|
||||||
@@ -17,6 +18,7 @@ void main()
|
|||||||
vShade = aShade;
|
vShade = aShade;
|
||||||
// World-space position uses row-vector convention (matches gl_Position below).
|
// World-space position uses row-vector convention (matches gl_Position below).
|
||||||
vec4 worldPos = vec4(aPos, 1.0) * model;
|
vec4 worldPos = vec4(aPos, 1.0) * model;
|
||||||
|
vWorldPos = worldPos.xyz;
|
||||||
vWorldY = worldPos.y;
|
vWorldY = worldPos.y;
|
||||||
gl_Position = worldPos * view * projection;
|
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}",
|
Log.Information("Game starting with seed={Seed} renderDistanceH={H} renderDistanceV={V}",
|
||||||
this._cfg.Seed, this._cfg.RenderDistanceHorizontal, this._cfg.RenderDistanceVertical);
|
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.DepthTest);
|
||||||
GL.Enable(EnableCap.CullFace);
|
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_caveDarkStartY", this._cfg.CaveDarkStartY);
|
||||||
this._shader.SetFloat("u_caveDarkEndY", this._cfg.CaveDarkEndY);
|
this._shader.SetFloat("u_caveDarkEndY", this._cfg.CaveDarkEndY);
|
||||||
this._shader.SetFloat("u_caveMinBrightness", this._cfg.CaveMinBrightness);
|
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._texture.Use(TextureUnit.Texture0);
|
||||||
|
|
||||||
this._streamer.DrawAll((pos, renderer) =>
|
this._streamer.DrawAll((pos, renderer) =>
|
||||||
|
|||||||
@@ -29,7 +29,11 @@ public sealed class Player
|
|||||||
public Player(Configuration cfg, Vector3 spawnPosition, float aspectRatio)
|
public Player(Configuration cfg, Vector3 spawnPosition, float aspectRatio)
|
||||||
{
|
{
|
||||||
this._cfg = cfg;
|
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);
|
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 Yaw { get; private set; } = -90f; // degrees; -90 looks down -Z
|
||||||
public float Pitch { get; private set; } // degrees
|
public float Pitch { get; private set; } // degrees
|
||||||
public float Fov { get; set; } = 60f; // degrees
|
public float Fov { get; set; } = 60f; // degrees
|
||||||
|
public float FarPlane { get; set; } = 100f; // world units
|
||||||
public float AspectRatio { get; set; }
|
public float AspectRatio { get; set; }
|
||||||
|
|
||||||
public Vector3 Front { get; private set; } = -Vector3.UnitZ;
|
public Vector3 Front { get; private set; } = -Vector3.UnitZ;
|
||||||
@@ -36,7 +37,7 @@ public sealed class Camera
|
|||||||
|
|
||||||
public Matrix4 GetProjectionMatrix() =>
|
public Matrix4 GetProjectionMatrix() =>
|
||||||
Matrix4.CreatePerspectiveFieldOfView(
|
Matrix4.CreatePerspectiveFieldOfView(
|
||||||
MathHelper.DegreesToRadians(this.Fov), this.AspectRatio, 0.1f, 100f);
|
MathHelper.DegreesToRadians(this.Fov), this.AspectRatio, 0.1f, this.FarPlane);
|
||||||
|
|
||||||
private void UpdateVectors()
|
private void UpdateVectors()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -39,6 +39,9 @@ public sealed class Shader : IDisposable
|
|||||||
public void SetFloat(string name, float value) =>
|
public void SetFloat(string name, float value) =>
|
||||||
GL.Uniform1(this.Location(name), 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)
|
private int Location(string name)
|
||||||
{
|
{
|
||||||
if (this._uniforms.TryGetValue(name, out int location)) return location;
|
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);
|
var camera = new Camera(Vector3.Zero, 1.5f);
|
||||||
Assert.NotEqual(Matrix4.Identity, camera.GetProjectionMatrix());
|
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