fix wrong fog colour for a few frames

This commit is contained in:
UnknownShadow200 2018-07-21 04:52:57 +10:00
parent b1ffb93fe5
commit 20c273ef64
3 changed files with 73 additions and 70 deletions

View File

@ -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;
}
}
}

View File

@ -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();
}

View File

@ -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);