diff --git a/ClassicalSharp/Rendering/Env/EnvRenderer.cs b/ClassicalSharp/Rendering/Env/EnvRenderer.cs index 5de6674da..1e6e905eb 100644 --- a/ClassicalSharp/Rendering/Env/EnvRenderer.cs +++ b/ClassicalSharp/Rendering/Env/EnvRenderer.cs @@ -15,7 +15,7 @@ namespace ClassicalSharp.Renderers { World map; Game game; internal bool legacy, minimal; - + double BlendFactor(float x) { //return -0.05 + 0.22 * (0.25 * Math.Log(x)); double blend = -0.13 + 0.28 * (0.25 * Math.Log(x)); @@ -24,7 +24,7 @@ namespace ClassicalSharp.Renderers { return blend; } - void BlockOn(out float fogDensity, out PackedCol fogCol) { + void CalcFog(out float density, out PackedCol col) { Vector3 pos = game.CurrentCameraPos; Vector3I coords = Vector3I.Floor(pos); @@ -34,13 +34,13 @@ namespace ClassicalSharp.Renderers { (Vector3)coords + BlockInfo.MaxBB[block]); if (blockBB.Contains(pos) && BlockInfo.FogDensity[block] != 0) { - fogDensity = BlockInfo.FogDensity[block]; - fogCol = BlockInfo.FogCol[block]; + density = BlockInfo.FogDensity[block]; + col = BlockInfo.FogCol[block]; } else { - fogDensity = 0; + density = 0; // Blend fog and sky together float blend = (float)BlendFactor(game.ViewDistance); - fogCol = PackedCol.Lerp(map.Env.FogCol, map.Env.SkyCol, blend); + col = PackedCol.Lerp(map.Env.FogCol, map.Env.SkyCol, blend); } } @@ -58,12 +58,11 @@ namespace ClassicalSharp.Renderers { } public void Render(double deltaTime) { - if (minimal) { RenderMinimal(deltaTime); return; } - if (skyVb == 0 || cloudsVb == 0) return; + UpdateFog(); + if (minimal || skyVb == 0 || cloudsVb == 0) return; RenderSky(deltaTime); RenderClouds(deltaTime); - UpdateFog(); } void EnvVariableChanged(object sender, EnvVarEventArgs e) { @@ -112,10 +111,7 @@ namespace ClassicalSharp.Renderers { } } - void ResetAllEnv(object sender, EventArgs e) { - UpdateFog(); - ContextRecreated(); - } + void ResetAllEnv(object sender, EventArgs e) { ContextRecreated(); } void IDisposable.Dispose() { game.Graphics.DeleteTexture(ref cloudsTex); @@ -136,33 +132,13 @@ namespace ClassicalSharp.Renderers { void ContextRecreated() { ContextLost(); game.Graphics.Fog = !minimal; + UpdateFog(); if (minimal) return; ResetClouds(); ResetSky(); } - void RenderMinimal(double deltaTime) { - if (!map.HasBlocks) return; - PackedCol fogCol = PackedCol.White; - float fogDensity = 0; - BlockOn(out fogDensity, out fogCol); - game.Graphics.ClearCol(fogCol); - - // TODO: rewrite this to avoid raising the event? want to avoid recreating vbos too many times often - if (fogDensity != 0) { - // Exp fog mode: f = e^(-density*coord) - // Solve coord for f = 0.05 (good approx for fog end) - // i.e. log(0.05) = -density * coord - - const double log005 = -2.99573227355399; - double dist = log005 / -fogDensity; - game.SetViewDistance((int)dist, false); - } else { - game.SetViewDistance(game.UserViewDistance, false); - } - } - void RenderSky(double delta) { if (game.SkyboxRenderer.ShouldRender) return; Vector3 pos = game.CurrentCameraPos; @@ -211,13 +187,23 @@ namespace ClassicalSharp.Renderers { gfx.SetMatrixMode(MatrixType.Modelview); } - void UpdateFog() { - if (!map.HasBlocks || minimal) return; - PackedCol fogCol = PackedCol.White; - float fogDensity = 0; - BlockOn(out fogDensity, out fogCol); + void UpdateFogMinimal(float fogDensity) { + // TODO: rewrite this to avoid raising the event? want to avoid recreating vbos too many times often + if (fogDensity != 0) { + // Exp fog mode: f = e^(-density*coord) + // Solve coord for f = 0.05 (good approx for fog end) + // i.e. log(0.05) = -density * coord + + const double log005 = -2.99573227355399; + double dist = log005 / -fogDensity; + game.SetViewDistance((int)dist, false); + } else { + game.SetViewDistance(game.UserViewDistance, false); + } + } + + void UpdateFogNormal(float fogDensity, PackedCol fogCol) { IGraphicsApi gfx = game.Graphics; - if (fogDensity != 0) { gfx.SetFogMode(Fog.Exp); gfx.SetFogDensity(fogDensity); @@ -237,10 +223,22 @@ namespace ClassicalSharp.Renderers { gfx.SetFogMode(Fog.Linear); gfx.SetFogEnd(game.ViewDistance); } - gfx.ClearCol(fogCol); gfx.SetFogCol(fogCol); } + void UpdateFog() { + float fogDensity; PackedCol fogCol; + CalcFog(out fogDensity, out fogCol); + game.Graphics.ClearCol(fogCol); + + if (!map.HasBlocks) return; + if (minimal) { + UpdateFogMinimal(fogDensity); + } else { + UpdateFogNormal(fogDensity, fogCol); + } + } + void ResetClouds() { if (!map.HasBlocks || game.Graphics.LostContext) return; game.Graphics.DeleteVb(ref cloudsVb); @@ -281,7 +279,7 @@ namespace ClassicalSharp.Renderers { } } - void DrawSkyY(int x1, int z1, int x2, int z2, int y, int axisSize, + void DrawSkyY(int x1, int z1, int x2, int z2, int y, int axisSize, PackedCol col, VertexP3fC4b[] vertices) { int endX = x2, endZ = z2, startZ = z1; int i = 0; @@ -297,14 +295,14 @@ namespace ClassicalSharp.Renderers { if (z2 > endZ) z2 = endZ; v.X = x1; v.Z = z1; vertices[i++] = v; - v.Z = z2; vertices[i++] = v; + v.Z = z2; vertices[i++] = v; v.X = x2; vertices[i++] = v; - v.Z = z1; vertices[i++] = v; + v.Z = z1; vertices[i++] = v; } } } - void DrawCloudsY(int x1, int z1, int x2, int z2, int y, int axisSize, + void DrawCloudsY(int x1, int z1, int x2, int z2, int y, int axisSize, PackedCol col, VertexP3fT2fC4b[] vertices) { int endX = x2, endZ = z2, startZ = z1; // adjust range so that largest negative uv coordinate is shifted to 0 or above. @@ -324,9 +322,9 @@ namespace ClassicalSharp.Renderers { float u1 = x1 / 2048f + offset, u2 = x2 / 2048f + offset; float v1 = z1 / 2048f + offset, v2 = z2 / 2048f + offset; v.X = x1; v.Z = z1; v.U = u1; v.V = v1; vertices[i++] = v; - v.Z = z2; v.V = v2; vertices[i++] = v; + v.Z = z2; v.V = v2; vertices[i++] = v; v.X = x2; v.U = u2; vertices[i++] = v; - v.Z = z1; v.V = v1; vertices[i++] = v; + v.Z = z1; v.V = v1; vertices[i++] = v; } } } diff --git a/src/Client/EnvRenderer.c b/src/Client/EnvRenderer.c index e31165529..d6a4009e1 100644 --- a/src/Client/EnvRenderer.c +++ b/src/Client/EnvRenderer.c @@ -38,6 +38,27 @@ Int32 EnvRenderer_Vertices(Int32 axis1Len, Int32 axis2Len) { /*########################################################################################################################* *------------------------------------------------------------Fog----------------------------------------------------------* *#########################################################################################################################*/ +static void EnvRenderer_CalcFog(Real32* density, PackedCol* col) { + Vector3 pos = Game_CurrentCameraPos; Vector3I coords; + Vector3I_Floor(&coords, &pos); /* coords = floor(pos); */ + Vector3I_ToVector3(&pos, &coords); /* pos = coords; */ + + BlockID block = World_SafeGetBlock_3I(coords); + struct AABB blockBB; + Vector3_Add(&blockBB.Min, &pos, &Block_MinBB[block]); + Vector3_Add(&blockBB.Max, &pos, &Block_MaxBB[block]); + + if (AABB_ContainsPoint(&blockBB, &pos) && Block_FogDensity[block] != 0.0f) { + *density = Block_FogDensity[block]; + *col = Block_FogCol[block]; + } else { + *density = 0.0f; + /* Blend fog and sky together */ + Real32 blend = EnvRenderer_BlendFactor((Real32)Game_ViewDistance); + *col = PackedCol_Lerp(WorldEnv_FogCol, WorldEnv_SkyCol, blend); + } +} + static void EnvRenderer_UpdateFogMinimal(Real32 fogDensity) { /* TODO: rewrite this to avoid raising the event? want to avoid recreating vbos too many times often */ if (fogDensity != 0.0f) { @@ -77,29 +98,11 @@ static void EnvRenderer_UpdateFogNormal(Real32 fogDensity, PackedCol fogCol) { } void EnvRenderer_UpdateFog(void) { - if (World_Blocks == NULL) return; - Vector3 pos = Game_CurrentCameraPos; Vector3I coords; - Vector3I_Floor(&coords, &pos); /* coords = floor(pos); */ - Vector3I_ToVector3(&pos, &coords); /* pos = coords; */ - - BlockID block = World_SafeGetBlock_3I(coords); - struct AABB blockBB; - Vector3_Add(&blockBB.Min, &pos, &Block_MinBB[block]); - Vector3_Add(&blockBB.Max, &pos, &Block_MaxBB[block]); - - PackedCol fogCol; - Real32 fogDensity; - if (AABB_ContainsPoint(&blockBB, &pos) && Block_FogDensity[block] != 0.0f) { - fogDensity = Block_FogDensity[block]; - fogCol = Block_FogCol[block]; - } else { - fogDensity = 0.0f; - /* Blend fog and sky together */ - Real32 blend = EnvRenderer_BlendFactor((Real32)Game_ViewDistance); - fogCol = PackedCol_Lerp(WorldEnv_FogCol, WorldEnv_SkyCol, blend); - } - + Real32 fogDensity; PackedCol fogCol; + EnvRenderer_CalcFog(&fogDensity, &fogCol); Gfx_ClearCol(fogCol); + + if (World_Blocks == NULL) return; if (EnvRenderer_Minimal) { EnvRenderer_UpdateFogMinimal(fogDensity); } else { @@ -740,6 +743,7 @@ static void EnvRenderer_UpdateAll(void) { EnvRenderer_UpdateClouds(); EnvRenderer_UpdateSky(); EnvRenderer_UpdateSkybox(); + EnvRenderer_UpdateFog(); /* TODO: Don't allocate unless used? */ weather_vb = Gfx_CreateDynamicVb(VERTEX_FORMAT_P3FT2FC4B, WEATHER_VERTS_COUNT); @@ -793,6 +797,7 @@ static void EnvRenderer_TexturePackChanged(void* obj) { static void EnvRenderer_TerrainAtlasChanged(void* obj) { EnvRenderer_UpdateBorderTextures(); } + static void EnvRenderer_ViewDistanceChanged(void* obj) { EnvRenderer_UpdateAll(); } diff --git a/src/Client/Game.c b/src/Client/Game.c index 8b56156b9..e5ca6b11f 100644 --- a/src/Client/Game.c +++ b/src/Client/Game.c @@ -582,9 +582,9 @@ static void Game_Render3D(Real64 delta, Real32 t) { Particles_Render(delta, t); Camera_Active->GetPickedBlock(&Game_SelectedPos); /* TODO: only pick when necessary */ + EnvRenderer_UpdateFog(); EnvRenderer_RenderSky(delta); EnvRenderer_RenderClouds(delta); - EnvRenderer_UpdateFog(); ChunkUpdater_Update(delta); MapRenderer_RenderNormal(delta);