Clean up Fog, remove Fast fog, close issue #77 (near-far incorrect center)

This commit is contained in:
James Seibel
2021-11-26 21:13:54 -06:00
parent 58d4bc7f0f
commit fbf5dfaa9d
10 changed files with 137 additions and 296 deletions
@@ -154,7 +154,7 @@ public class ClientApi
// CONFIG.client().graphics().advancedGraphics().setGpuUploadMethod(GpuUploadMethod.BUFFER_STORAGE);
// CONFIG.client().graphics().quality().setLodChunkRenderDistance(128);
// CONFIG.client().graphics().fogQuality().setFogDrawOverride(FogDrawOverride.FANCY);
// CONFIG.client().graphics().fogQuality().setFogDrawMode(FogDrawMode.FOG_ENABLED);
// CONFIG.client().graphics().fogQuality().setFogDistance(FogDistance.FAR);
// CONFIG.client().advanced().buffers().setRebuildTimes(BufferRebuildTimes.FREQUENT);
@@ -23,16 +23,11 @@ package com.seibel.lod.core.enums.rendering;
* NEAR, FAR, or NEAR_AND_FAR.
*
* @author James Seibel
* @version 02-14-2021
* @version 11-26-2021
*/
public enum FogDistance
{
/** good for fast or fancy fog qualities. */
NEAR,
/** good for fast or fancy fog qualities. */
FAR,
/** only looks good if the fog quality is set to Fancy. */
NEAR_AND_FAR
}
@@ -21,27 +21,20 @@ package com.seibel.lod.core.enums.rendering;
/**
* USE_OPTIFINE_FOG_SETTING, <br>
* NEVER_DRAW_FOG, <br>
* ALWAYS_DRAW_FOG_FAST, <br>
* ALWAYS_DRAW_FOG_FANCY <br>
* FOG_ENABLED, <br>
* FOG_DISABLED <br>
*
* @author James Seibel
* @version 7-3-2021
* @version 11-26-2021
*/
public enum FogDrawOverride
public enum FogDrawMode
{
/**
* Use whatever Fog setting optifine is using.
* If optifine isn't installed this defaults to ALWAYS_DRAW_FOG.
*/
OPTIFINE_SETTING,
USE_OPTIFINE_SETTING,
/** Never draw fog on the LODs */
NO_FOG,
/** Always draw fast fog on the LODs */
FAST,
/** Always draw fancy fog on the LODs */
FANCY
FOG_ENABLED,
FOG_DISABLED
}
@@ -19,7 +19,7 @@
package com.seibel.lod.core.handlers;
import com.seibel.lod.core.enums.rendering.FogQuality;
import com.seibel.lod.core.enums.rendering.FogDrawMode;
import com.seibel.lod.core.objects.math.Mat4f;
/**
@@ -35,12 +35,12 @@ import com.seibel.lod.core.objects.math.Mat4f;
* different MC versions.
*
* @author James Seibel
* @version 11-20-2021
* @version 11-26-2021
*/
public interface IReflectionHandler
{
/** @returns the type of fog optifine is currently set to render. */
public FogQuality getFogQuality();
/** @returns Whether Optifine is set to render fog or not. */
public FogDrawMode getFogDrawMode();
/** @returns if Vivecraft is present. Attempts to find the "VRRenderer" class. */
public boolean vivecraftPresent();
@@ -25,7 +25,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.enums.rendering.FogQuality;
import com.seibel.lod.core.enums.rendering.FogDrawMode;
import com.seibel.lod.core.objects.math.Mat4f;
/**
@@ -35,7 +35,7 @@ import com.seibel.lod.core.objects.math.Mat4f;
* presence/absence of other mods.
*
* @author James Seibel
* @version 11-20-2021
* @version 11-26-2021
*/
public class ReflectionHandler implements IReflectionHandler
{
@@ -100,14 +100,14 @@ public class ReflectionHandler implements IReflectionHandler
* @return the fog quality
*/
@Override
public FogQuality getFogQuality()
public FogDrawMode getFogDrawMode()
{
if (ofFogField == null)
{
// either optifine isn't installed,
// the variable name was changed, or
// the setup method wasn't called yet.
return FogQuality.FANCY;
return FogDrawMode.FOG_ENABLED;
}
int returnNum = 0;
@@ -129,12 +129,11 @@ public class ReflectionHandler implements IReflectionHandler
// it should never be called in this case
// normal options
case 1:
return FogQuality.FAST;
case 2:
return FogQuality.FANCY;
case 3:
return FogQuality.OFF;
case 1: // fast
case 2: // fancy
return FogDrawMode.FOG_ENABLED;
case 3: // off
return FogDrawMode.FOG_DISABLED;
}
}
@@ -17,17 +17,27 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.lod.core.enums.rendering;
package com.seibel.lod.core.objects.rending;
import com.seibel.lod.core.enums.rendering.FogDistance;
import com.seibel.lod.core.enums.rendering.FogDrawMode;
/**
* fast, fancy, or off
* This object is just a replacement for an array
* to make things easier to understand in the LodRenderer.
*
* @author James Seibel
* @version 02-14-2021
* @version 11-26-2021
*/
public enum FogQuality
public class LodFogConfig
{
FAST,
FANCY,
OFF
public FogDrawMode fogDrawMode;
public FogDistance fogDistance;
public float nearFogStart = 0;
public float nearFogEnd = 0;
public float farFogStart = 0;
public float farFogEnd = 0;
}
@@ -1,70 +0,0 @@
/*
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
* licensed under the GNU GPL v3 License.
*
* Copyright (C) 2020 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.lod.core.objects.rending;
import com.seibel.lod.core.enums.rendering.FogDistance;
import com.seibel.lod.core.enums.rendering.FogQuality;
/**
* This object is just a replacement for an array
* to make things easier to understand in the LodRenderer.
*
* @author James Seibel
* @version 11-26-2021
*/
public class LodFogConfigContainer
{
public LodFogConfig near = new LodFogConfig(FogDistance.NEAR);
public LodFogConfig far = new LodFogConfig(FogDistance.FAR);
/**
* If true that means Minecraft is
* rendering fog
*/
public boolean vanillaIsRenderingFog = true;
public FogQuality fogQuality;
public LodFogConfigContainer()
{
}
/**
* This holds all relevant data to rendering fog at either
* near or far distances.
*/
public static class LodFogConfig
{
public FogQuality quality = FogQuality.FANCY;
public FogDistance distance;
public float fogStart = 0;
public float fogEnd = 0;
public LodFogConfig(FogDistance newFogDistance)
{
distance = newFogDistance;
}
}
}
@@ -32,8 +32,7 @@ import com.seibel.lod.core.builders.bufferBuilding.LodBufferBuilderFactory.Verte
import com.seibel.lod.core.enums.config.GpuUploadMethod;
import com.seibel.lod.core.enums.rendering.DebugMode;
import com.seibel.lod.core.enums.rendering.FogDistance;
import com.seibel.lod.core.enums.rendering.FogDrawOverride;
import com.seibel.lod.core.enums.rendering.FogQuality;
import com.seibel.lod.core.enums.rendering.FogDrawMode;
import com.seibel.lod.core.handlers.IReflectionHandler;
import com.seibel.lod.core.objects.lod.LodDimension;
import com.seibel.lod.core.objects.lod.RegionPos;
@@ -41,7 +40,7 @@ import com.seibel.lod.core.objects.math.Mat4f;
import com.seibel.lod.core.objects.math.Vec3d;
import com.seibel.lod.core.objects.math.Vec3f;
import com.seibel.lod.core.objects.opengl.LodVertexBuffer;
import com.seibel.lod.core.objects.rending.LodFogConfigContainer;
import com.seibel.lod.core.objects.rending.LodFogConfig;
import com.seibel.lod.core.render.shader.LodShaderProgram;
import com.seibel.lod.core.util.DetailDistanceUtil;
import com.seibel.lod.core.util.LevelPosUtil;
@@ -255,7 +254,7 @@ public class LodRenderer
Mat4f projectionMatrix = createProjectionMatrix(mcProjectionMatrix, vanillaBlockRenderedDistance, partialTicks);
LodFogConfigContainer fogSettings = generateFogConfigContainer();
LodFogConfig fogSettings = determineFogConfig();
@@ -269,7 +268,7 @@ public class LodRenderer
//==============//
// can be used when testing shaders
// glProxy.createShaderProgram();
glProxy.createShaderProgram();
LodShaderProgram shaderProgram = glProxy.lodShaderProgram;
@@ -283,7 +282,7 @@ public class LodRenderer
shaderProgram.enableVertexAttribute(colAttrib);
// upload the required uniforms
// global uniforms
int mvmUniform = shaderProgram.getUniformLocation("modelViewMatrix");
shaderProgram.setUniform(mvmUniform, modelViewMatrix);
int projUniform = shaderProgram.getUniformLocation("projectionMatrix");
@@ -295,10 +294,17 @@ public class LodRenderer
GL20.glUniform4f(fogColorUniform, fogColor.getRed() / 256.0f, fogColor.getGreen() / 256.0f, fogColor.getBlue() / 256.0f, fogColor.getAlpha() / 256.0f);
int nearPlaneUniform = shaderProgram.getUniformLocation("nearPlane");
int farPlaneUniform = shaderProgram.getUniformLocation("farPlane");
// region dependent uniforms
int fogEnabledUniform = shaderProgram.getUniformLocation("fogEnabled");
int nearFogEnabledUniform = shaderProgram.getUniformLocation("nearFogEnabled");
int farFogEnabledUniform = shaderProgram.getUniformLocation("farFogEnabled");
// near
int nearFogStartUniform = shaderProgram.getUniformLocation("nearFogStart");
int nearFogEndUniform = shaderProgram.getUniformLocation("nearFogEnd");
// far
int farFogStartUniform = shaderProgram.getUniformLocation("farFogStart");
int farFogEndUniform = shaderProgram.getUniformLocation("farFogEnd");
@@ -312,12 +318,9 @@ public class LodRenderer
boolean cullingDisabled = CONFIG.client().graphics().advancedGraphics().getDisableDirectionalCulling();
boolean renderBufferStorage = CONFIG.client().graphics().advancedGraphics().getGpuUploadMethod() == GpuUploadMethod.BUFFER_STORAGE && glProxy.bufferStorageSupported;
// used to determine what type of fog to render
int halfWidth = vbos.length / 2;
int quarterWidth = vbos.length / 4;
// where the center of the buffers is (needed when culling regions)
RegionPos vboCenterRegionPos = new RegionPos(vbosCenter);
RegionPos vboPos = new RegionPos();
// render each of the buffers
@@ -325,14 +328,15 @@ public class LodRenderer
{
for (int z = 0; z < vbos.length; z++)
{
RegionPos vboPos = new RegionPos(
x + vboCenterRegionPos.x - (lodDim.getWidth() / 2),
z + vboCenterRegionPos.z - (lodDim.getWidth() / 2));
vboPos.x = x + vboCenterRegionPos.x - (lodDim.getWidth() / 2);
vboPos.z = z + vboCenterRegionPos.z - (lodDim.getWidth() / 2);
if (cullingDisabled || RenderUtil.isRegionInViewFrustum(MC_RENDER.getCameraBlockPosition(), MC_RENDER.getLookAtVector(), vboPos.blockPos()))
{
// fog may be different from region to region
applyFog(shaderProgram, fogSettings, nearPlaneUniform, farPlaneUniform, fogEnabledUniform, halfWidth, quarterWidth, x, z);
applyFog(shaderProgram,
fogSettings, fogEnabledUniform, nearFogEnabledUniform, farFogEnabledUniform,
nearFogStartUniform, nearFogEndUniform, farFogStartUniform, farFogEndUniform);
// actual rendering
@@ -412,7 +416,6 @@ public class LodRenderer
//=================//
// Setup Functions //
//=================//
@@ -425,154 +428,48 @@ public class LodRenderer
}
/** Return what fog settings should be used when rendering. */
private LodFogConfigContainer generateFogConfigContainer()
private LodFogConfig determineFogConfig()
{
LodFogConfigContainer fogSettings = new LodFogConfigContainer();
LodFogConfig fogConfig = new LodFogConfig();
FogQuality quality = REFLECTION_HANDLER.getFogQuality();
FogDrawOverride override = CONFIG.client().graphics().fogQuality().getFogDrawOverride();
fogConfig.fogDrawMode = CONFIG.client().graphics().fogQuality().getFogDrawMode();
if (fogConfig.fogDrawMode == FogDrawMode.USE_OPTIFINE_SETTING)
fogConfig.fogDrawMode = REFLECTION_HANDLER.getFogDrawMode();
fogSettings.vanillaIsRenderingFog = quality != FogQuality.OFF;
// use any fog overrides the user may have set
switch (override)
{
case FANCY:
quality = FogQuality.FANCY;
break;
case NO_FOG:
quality = FogQuality.OFF;
break;
case FAST:
quality = FogQuality.FAST;
break;
case OPTIFINE_SETTING:
// don't override anything
break;
}
fogSettings.fogQuality = quality;
// how different distances are drawn depends on the quality set
switch (quality)
{
case FANCY:
fogSettings.near.quality = FogQuality.FANCY;
fogSettings.far.quality = FogQuality.FANCY;
switch (CONFIG.client().graphics().fogQuality().getFogDistance())
{
case NEAR_AND_FAR:
fogSettings.near.distance = FogDistance.NEAR;
fogSettings.far.distance = FogDistance.FAR;
break;
case NEAR:
fogSettings.near.distance = FogDistance.NEAR;
fogSettings.far.distance = FogDistance.NEAR;
break;
case FAR:
fogSettings.near.distance = FogDistance.FAR;
fogSettings.far.distance = FogDistance.FAR;
break;
}
break;
case FAST:
fogSettings.near.quality = FogQuality.FAST;
fogSettings.far.quality = FogQuality.FAST;
// fast fog setting should only have one type of
// fog, since the LODs are separated into a near
// and far portion; and fast fog is rendered from the
// frustrum's perspective instead of the camera
switch (CONFIG.client().graphics().fogQuality().getFogDistance())
{
case NEAR_AND_FAR:
case NEAR:
fogSettings.near.distance = FogDistance.NEAR;
fogSettings.far.distance = FogDistance.NEAR;
break;
case FAR:
fogSettings.near.distance = FogDistance.FAR;
fogSettings.far.distance = FogDistance.FAR;
break;
}
break;
case OFF:
fogSettings.near.quality = FogQuality.OFF;
fogSettings.far.quality = FogQuality.OFF;
break;
}
populateFogConfig(fogSettings.near);
populateFogConfig(fogSettings.far);
return fogSettings;
}
/** populates the given LodFogConfig object */
private void populateFogConfig(LodFogConfigContainer.LodFogConfig fogSetting)
{
FogDistance fogDistance = fogSetting.distance;
FogQuality fogQuality = fogSetting.quality;
fogConfig.fogDistance = CONFIG.client().graphics().fogQuality().getFogDistance();
if (fogQuality == FogQuality.OFF)
return;
if (fogDistance == FogDistance.NEAR_AND_FAR)
{
throw new IllegalArgumentException("determineFogDistance doesn't accept the NEAR_AND_FAR fog distance.");
}
if (fogDistance == FogDistance.FAR)
{
if (fogQuality == FogQuality.FANCY)
{
// for more realistic fog when using FAR
if (CONFIG.client().graphics().fogQuality().getFogDistance() == FogDistance.NEAR_AND_FAR)
fogSetting.fogStart = farPlaneBlockDistance * 1.6f * 0.9f;
else
fogSetting.fogStart = Math.min(vanillaBlockRenderedDistance * 1.5f, farPlaneBlockDistance * 0.9f * 1.6f);
fogSetting.fogEnd = farPlaneBlockDistance * 1.6f;
}
else if (fogQuality == FogQuality.FAST)
{
// for the far fog of the normal chunks
// to start right where the LODs' end use:
// end = 0.8f, start = 1.5f
fogSetting.fogStart = farPlaneBlockDistance * 0.75f;
fogSetting.fogEnd = farPlaneBlockDistance * 1.0f;
}
}
else if (fogDistance == FogDistance.NEAR)
{
// the reason that I wrote fogEnd then fogStart backwards
// is because we are using fog backwards to how
// it is normally used, with it hiding near objects
// instead of far objects.
if (fogQuality == FogQuality.FANCY)
{
fogSetting.fogEnd = vanillaBlockRenderedDistance * 1.41f;
fogSetting.fogStart = vanillaBlockRenderedDistance * 1.6f;
}
else if (fogQuality == FogQuality.FAST)
{
fogSetting.fogEnd = vanillaBlockRenderedDistance * 1.0f;
fogSetting.fogStart = vanillaBlockRenderedDistance * 1.5f;
}
}
// far fog //
if (CONFIG.client().graphics().fogQuality().getFogDistance() == FogDistance.NEAR_AND_FAR)
fogConfig.farFogStart = farPlaneBlockDistance * 1.6f * 0.9f;
else
// for more realistic fog when using FAR
fogConfig.farFogStart = Math.min(vanillaBlockRenderedDistance * 1.5f, farPlaneBlockDistance * 0.9f * 1.6f);
fogConfig.farFogEnd = farPlaneBlockDistance * 1.6f;
// near fog //
// the reason that I wrote fogEnd then fogStart backwards
// is because we are using fog backwards to how
// it is normally used, hiding near objects
// instead of far objects.
fogConfig.nearFogEnd = vanillaBlockRenderedDistance * 1.41f;
fogConfig.nearFogStart = vanillaBlockRenderedDistance * 1.6f;
return fogConfig;
}
/**
@@ -650,24 +547,21 @@ public class LodRenderer
}
private void applyFog(LodShaderProgram shaderProgram,
LodFogConfigContainer fogSettings, int nearPlaneUniform, int farPlaneUniform, int fogEnabledUniform,
int halfWidth, int quarterWidth, int regionX, int regionZ)
LodFogConfig fogSettings, int fogEnabledUniform, int nearFogEnabledUniform, int farFogEnabledUniform,
int nearFogStartUniform, int nearFogEndUniform, int farFogStartUniform, int farFogEndUniform)
{
if (fogSettings.fogQuality != FogQuality.OFF)
if (fogSettings.fogDrawMode != FogDrawMode.FOG_DISABLED)
{
shaderProgram.setUniform(fogEnabledUniform, true);
shaderProgram.setUniform(nearFogEnabledUniform, fogSettings.fogDistance != FogDistance.FAR);
shaderProgram.setUniform(farFogEnabledUniform, fogSettings.fogDistance != FogDistance.NEAR);
if ((regionX > halfWidth - quarterWidth && regionX < halfWidth + quarterWidth)
&& (regionZ > halfWidth - quarterWidth && regionZ < halfWidth + quarterWidth))
{
shaderProgram.setUniform(nearPlaneUniform, fogSettings.near.fogStart);
shaderProgram.setUniform(farPlaneUniform, fogSettings.near.fogEnd);
}
else
{
shaderProgram.setUniform(nearPlaneUniform, fogSettings.far.fogStart);
shaderProgram.setUniform(farPlaneUniform, fogSettings.far.fogEnd);
}
// near
shaderProgram.setUniform(nearFogStartUniform, fogSettings.nearFogStart);
shaderProgram.setUniform(nearFogEndUniform, fogSettings.nearFogEnd);
// far
shaderProgram.setUniform(farFogStartUniform, fogSettings.farFogStart);
shaderProgram.setUniform(farFogEndUniform, fogSettings.farFogEnd);
}
else
{
@@ -683,6 +577,7 @@ public class LodRenderer
// Other Misc Functions //
//======================//
/**
* If this is called then the next time "drawLODs" is called
* the LODs will be regenerated; the same as if the player moved.
@@ -692,7 +587,6 @@ public class LodRenderer
fullRegen = true;
}
/**
* Replace the current Vertex Buffers with the newly
* created buffers from the lodBufferBuilder. <br><br>
@@ -717,6 +611,7 @@ public class LodRenderer
}
/** Determines if the LODs should have a fullRegen or partialRegen */
private void determineIfLodsShouldRegenerate(LodDimension lodDim, float partialTicks)
{
@@ -32,7 +32,7 @@ import com.seibel.lod.core.enums.config.VanillaOverdraw;
import com.seibel.lod.core.enums.config.VerticalQuality;
import com.seibel.lod.core.enums.rendering.DebugMode;
import com.seibel.lod.core.enums.rendering.FogDistance;
import com.seibel.lod.core.enums.rendering.FogDrawOverride;
import com.seibel.lod.core.enums.rendering.FogDrawMode;
import com.seibel.lod.core.objects.MinDefaultMax;
import com.seibel.lod.core.util.LodUtil;
@@ -132,15 +132,14 @@ public interface ILodConfigWrapperSingleton
public FogDistance getFogDistance();
public void setFogDistance(FogDistance newFogDistance);
FogDrawOverride FOG_DRAW_OVERRIDE_DEFAULT = FogDrawOverride.FANCY;
String FOG_DRAW_OVERRIDE_DESC = ""
FogDrawMode FOG_DRAW_MODE_DEFAULT = FogDrawMode.FOG_ENABLED;
String FOG_DRAW_MODE_DESC = ""
+ " When should fog be drawn? \n"
+ " " + FogDrawOverride.OPTIFINE_SETTING + ": Use whatever Fog setting Optifine is using. If Optifine isn't installed this defaults to " + FogDrawOverride.FANCY + ". \n"
+ " " + FogDrawOverride.NO_FOG + ": Never draw fog on the LODs \n"
+ " " + FogDrawOverride.FAST + ": Always draw fast fog on the LODs \n"
+ " " + FogDrawOverride.FANCY + ": Always draw fancy fog on the LODs (if your graphics card supports it) \n";
public FogDrawOverride getFogDrawOverride();
public void setFogDrawOverride(FogDrawOverride newFogDrawOverride);
+ " " + FogDrawMode.USE_OPTIFINE_SETTING + ": Use whatever Fog setting Optifine is using. If Optifine isn't installed this defaults to " + FogDrawMode.FOG_ENABLED + ". \n"
+ " " + FogDrawMode.FOG_ENABLED + ": Never draw fog on the LODs \n"
+ " " + FogDrawMode.FOG_DISABLED + ": Always draw fast fog on the LODs \n";
public FogDrawMode getFogDrawMode();
public void setFogDrawMode(FogDrawMode newFogDrawOverride);
boolean DISABLE_VANILLA_FOG_DEFAULT = false;
String DISABLE_VANILLA_FOG_DESC = ""
+25 -5
View File
@@ -12,8 +12,13 @@ out vec4 fragColor;
uniform vec3 cameraPos;
uniform bool fogEnabled;
uniform float farPlane;
uniform float nearPlane;
uniform bool nearFogEnabled;
uniform bool farFogEnabled;
uniform float nearFogStart;
uniform float nearFogEnd;
uniform float farFogStart;
uniform float farFogEnd;
uniform vec4 fogColor;
@@ -39,9 +44,22 @@ void main()
if (fogEnabled)
{
// add fog
float dist = distance(vertexWorldPos, vec4(cameraPos,1));
float fogAlpha = getFogAlpha(nearPlane, farPlane, dist);
returnColor = mix(vec4(fogColor.xyz, 1), vertexColor, fogAlpha);
// no fog by default
float fogAlpha = 0;
// less than because nearFogStart is farther away than nearFogEnd
if (nearFogEnabled && dist < nearFogStart)
{
fogAlpha = getFogAlpha(nearFogStart, nearFogEnd, dist);
}
else if (farFogEnabled)
{
fogAlpha = getFogAlpha(farFogStart, farFogEnd, dist);
}
returnColor = mix(vertexColor, vec4(fogColor.xyz, 1), fogAlpha);
}
else
{
@@ -60,10 +78,12 @@ void main()
/**
* Returns the fog strength for the given fragment.
* This is the same implementation as legacy OpenGL's Linear fog option.
* 1 = completely opaque fog
* 0 = no fog
*/
float getFogAlpha(float start, float end, float dist)
{
float fogAlpha = (end - dist) / (end - start);
float fogAlpha = 1 - ((end - dist) / (end - start));
return clamp(fogAlpha, 0, 1);
}