Merge Horizontal Quality and Scale

The separation was confusing most of the time
This commit is contained in:
James Seibel
2023-06-11 15:10:16 -05:00
parent 0179f10166
commit 72b89814b6
7 changed files with 62 additions and 137 deletions
@@ -23,12 +23,7 @@ package com.seibel.lod.api.enums.config;
* LOWEST <br>
* LOW <br>
* MEDIUM <br>
* HIGH <br> <br>
*
* this indicates the base of the quadratic function we use for the quality drop-off
*
* @author Leonardo Amato
* @version 9-29-2021
* HIGH <br>
*/
public enum EHorizontalQuality
{
@@ -37,22 +32,27 @@ public enum EHorizontalQuality
// when removing items up the API major version
/** 1.0 AKA Linear */
LOWEST(1.0f),
// FIXME any quadraticBase less than 2.0f has issues with DetailDistanceUtil, and will always return the lowest detail level.
// So for now we are limiting the lowest value to 2.0
// LOWEST was originally 1.0f and LOW was 1.5f
/** exponent 1.5 */
LOW(1.5f),
LOWEST(2.0f, 4),
LOW(2.0f, 8),
MEDIUM(2.0f, 12),
HIGH(2.2f, 24),
EXTREME(2.4f, 64),
UNLIMITED(-1, -1);
/** exponent 2.0 */
MEDIUM(2.0f),
/** exponent 2.2 */
HIGH(2.2f);
public final double quadraticBase;
public final int distanceUnitInBlocks;
EHorizontalQuality(double distanceUnit)
EHorizontalQuality(double quadraticBase, int distanceUnitInBlocks)
{
this.quadraticBase = distanceUnit;
this.quadraticBase = quadraticBase;
this.distanceUnitInBlocks = distanceUnitInBlocks;
}
}
@@ -1,49 +0,0 @@
/*
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
* licensed under the GNU LGPL v3 License.
*
* Copyright (C) 2020-2022 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.lod.api.enums.config;
/**
* Low <br>
* Medium <br>
* High <br>
* <br>
* this is a quality scale for the detail drop-off
*
* @author Leonardo Amato
* @version 9-25-2021
*/
public enum EHorizontalScale
{
/** Lods are 2D with heightMap */
LOW(64),
/** Lods expand in three dimension */
MEDIUM(128),
/** Lods expand in three dimension */
HIGH(256);
public final int distanceUnit;
EHorizontalScale(int distanceUnit)
{
this.distanceUnit = distanceUnit;
}
}
@@ -178,15 +178,6 @@ public class Config
.addListener(RenderCacheConfigEventHandler.INSTANCE)
.build();
// TODO merge with horizontal quality
public static ConfigEntry<Integer> horizontalScale = new ConfigEntry.Builder<Integer>()
.setMinDefaultMax(2, 12, 64)
.comment(""
+ "This indicates how quickly fake chunks decrease in quality the further away they are. \n"
+ "Higher settings will render higher quality fake chunks farther away, \n"
+ " but will increase memory and GPU usage.")
.build();
public static ConfigEntry<EHorizontalQuality> horizontalQuality = new ConfigEntry.Builder<EHorizontalQuality>()
.set(EHorizontalQuality.MEDIUM)
.comment(""
@@ -4,9 +4,7 @@ import com.seibel.lod.api.DhApiMain;
import com.seibel.lod.api.enums.config.EHorizontalResolution;
import com.seibel.lod.api.enums.config.EVerticalQuality;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.config.listeners.ConfigChangeListener;
import com.seibel.lod.core.config.listeners.IConfigListener;
import com.seibel.lod.core.config.types.ConfigEntry;
import com.seibel.lod.core.util.DetailDistanceUtil;
/**
@@ -59,7 +57,7 @@ public class RenderCacheConfigEventHandler implements IConfigListener
if (refreshRenderData)
{
// TODO add a timeout to prevent rapidly changing settings causing the render data thrashing.
DetailDistanceUtil.minDetail = newHorizontalResolution.detailLevel;
DetailDistanceUtil.updateSettings();
DhApiMain.Delayed.renderProxy.clearRenderDataCache();
}
@@ -47,29 +47,15 @@ public class RenderQualityPresetConfigEventHandler implements IConfigListener
this.put(EQualityPreset.HIGH, EVerticalQuality.HIGH);
this.put(EQualityPreset.EXTREME, EVerticalQuality.HIGH);
}});
private final ConfigEntryWithPresetOptions<EQualityPreset, EHorizontalQuality> horizontalQuality = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Quality.horizontalQuality,
new HashMap<EQualityPreset, EHorizontalQuality>()
{{
this.put(EQualityPreset.MINIMUM, EHorizontalQuality.MEDIUM); // TODO Lowest and Low have a bug, making "chunk" the highest detail level
this.put(EQualityPreset.LOW, EHorizontalQuality.MEDIUM); // I should look into why this is instead of just removing the option
this.put(EQualityPreset.MINIMUM, EHorizontalQuality.LOWEST);
this.put(EQualityPreset.LOW, EHorizontalQuality.LOW);
this.put(EQualityPreset.MEDIUM, EHorizontalQuality.MEDIUM);
this.put(EQualityPreset.HIGH, EHorizontalQuality.HIGH);
this.put(EQualityPreset.EXTREME, EHorizontalQuality.HIGH);
}});
// // TODO merge horizontal scale and quality (merge the numbers into quality)
// private final ConfigEntryWithPresetOptions<EQualityPreset, Integer> horizontalScale = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Quality.horizontalScale,
// new HashMap<EQualityPreset, Integer>()
// {{
// this.put(EQualityPreset.MINIMUM, 4);
// this.put(EQualityPreset.LOW, 8);
// this.put(EQualityPreset.MEDIUM, 12);
// this.put(EQualityPreset.HIGH, 24);
// this.put(EQualityPreset.EXTREME, 64);
// }});
private final ConfigEntryWithPresetOptions<EQualityPreset, ETransparency> transparency = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Quality.transparency,
new HashMap<EQualityPreset, ETransparency>()
{{
@@ -1,5 +1,6 @@
package com.seibel.lod.core.render;
import com.seibel.lod.api.enums.config.EHorizontalQuality;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.config.listeners.ConfigChangeListener;
import com.seibel.lod.core.dataObjects.render.ColumnRenderSource;
@@ -9,12 +10,10 @@ import com.seibel.lod.core.pos.DhSectionPos;
import com.seibel.lod.core.file.renderfile.ILodRenderSourceProvider;
import com.seibel.lod.core.logging.DhLoggerBuilder;
import com.seibel.lod.core.util.DetailDistanceUtil;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.util.objects.quadTree.QuadNode;
import com.seibel.lod.core.util.objects.quadTree.QuadTree;
import org.apache.logging.log4j.Logger;
import java.util.HashSet;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
@@ -39,7 +38,7 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements AutoClose
private final IDhClientLevel level; //FIXME: Proper hierarchy to remove this reference!
private final ConfigChangeListener<Integer> horizontalScaleChangeListener;
private final ConfigChangeListener<EHorizontalQuality> horizontalScaleChangeListener;
@@ -56,7 +55,7 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements AutoClose
this.renderSourceProvider = provider;
this.blockRenderDistance = viewDistanceInBlocks;
this.horizontalScaleChangeListener = new ConfigChangeListener<>(Config.Client.Advanced.Graphics.Quality.horizontalScale, (newHorizontalScale) -> this.onHorizontalScaleChange());
this.horizontalScaleChangeListener = new ConfigChangeListener<>(Config.Client.Advanced.Graphics.Quality.horizontalQuality, (newHorizontalScale) -> this.onHorizontalQualityChange());
}
@@ -362,10 +361,10 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements AutoClose
// config listeners //
//==================//
private void onHorizontalScaleChange()
private void onHorizontalQualityChange()
{
// TODO this Util should probably be somewhere else or handled differently, but it works for now
// Updating the util is necessary whenever the horizontal quality or scale are changed, otherwise they won't be applied
// Updating this util is necessary whenever the horizontal quality is changed, since it handles the detail drop-off
DetailDistanceUtil.updateSettings();
@@ -19,8 +19,8 @@
package com.seibel.lod.core.util;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.api.enums.config.EHorizontalQuality;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.coreapi.util.MathUtil;
/**
@@ -31,67 +31,67 @@ import com.seibel.lod.coreapi.util.MathUtil;
@Deprecated
public class DetailDistanceUtil
{
public static byte minDetail = Config.Client.Advanced.Graphics.Quality.drawResolution.get().detailLevel;
/** smallest numerical detail level */
private static byte maxDetailLevel = Config.Client.Advanced.Graphics.Quality.drawResolution.get().detailLevel;
private static final byte maxDetail = Byte.MAX_VALUE;
/** largest numerical detail level */
private static final byte minDetailLevel = Byte.MAX_VALUE;
private static final double minDistance = 0;
private static double distanceUnit = 16 * Config.Client.Advanced.Graphics.Quality.horizontalScale.get();
private static double maxDistance = Config.Client.Advanced.Graphics.Quality.lodChunkRenderDistance.get() * 16 * 2;
// TODO merge with updateSettings() below
private static double distanceUnit = Config.Client.Advanced.Graphics.Quality.horizontalQuality.get().distanceUnitInBlocks * LodUtil.CHUNK_WIDTH;
private static double maxDistance = Config.Client.Advanced.Graphics.Quality.lodChunkRenderDistance.get() * LodUtil.CHUNK_WIDTH * 2;
private static double logBase = Math.log(Config.Client.Advanced.Graphics.Quality.horizontalQuality.get().quadraticBase);
public static void updateSettings()
{
distanceUnit = 16 * Config.Client.Advanced.Graphics.Quality.horizontalScale.get();
minDetail = Config.Client.Advanced.Graphics.Quality.drawResolution.get().detailLevel;
maxDistance = Config.Client.Advanced.Graphics.Quality.lodChunkRenderDistance.get() * 16 * 8;
maxDetailLevel = Config.Client.Advanced.Graphics.Quality.drawResolution.get().detailLevel;
distanceUnit = Config.Client.Advanced.Graphics.Quality.horizontalQuality.get().distanceUnitInBlocks * LodUtil.CHUNK_WIDTH;
maxDistance = Config.Client.Advanced.Graphics.Quality.lodChunkRenderDistance.get() * LodUtil.CHUNK_WIDTH * 2;
logBase = Math.log(Config.Client.Advanced.Graphics.Quality.horizontalQuality.get().quadraticBase);
}
public static double baseDistanceFunction(int detail)
{
if (detail <= minDetail)
return minDistance;
if (detail >= maxDetail)
return maxDistance;
detail-=minDetail;
if (Config.Client.Advanced.Graphics.Quality.horizontalQuality.get() == EHorizontalQuality.LOWEST)
return ((double)detail * distanceUnit);
else
if (detail <= maxDetailLevel)
{
double base = Config.Client.Advanced.Graphics.Quality.horizontalQuality.get().quadraticBase;
return Math.pow(base, detail) * distanceUnit;
return minDistance;
}
else if (detail >= minDetailLevel)
{
return maxDistance;
}
double base = Config.Client.Advanced.Graphics.Quality.horizontalQuality.get().quadraticBase;
return Math.pow(base, detail) * distanceUnit;
}
public static double getDrawDistanceFromDetail(int detail)
{
return baseDistanceFunction(detail);
}
public static double getDrawDistanceFromDetail(int detail) { return baseDistanceFunction(detail); }
public static byte baseInverseFunction(double distance)
{
double maxDetailDistance = getDrawDistanceFromDetail(maxDetail-1);
if (distance > maxDetailDistance) {
//ApiShared.LOGGER.info("DEBUG: Scale as max: {}", distance);
return maxDetail-1;
// special case, never drop the quality
if (Config.Client.Advanced.Graphics.Quality.horizontalQuality.get() == EHorizontalQuality.UNLIMITED)
{
return maxDetailLevel;
}
int detail;
if (Config.Client.Advanced.Graphics.Quality.horizontalQuality.get() == EHorizontalQuality.LOWEST)
detail = (int) (distance/distanceUnit);
else
detail = (int) (Math.log(distance/distanceUnit) / logBase);
double maxDetailDistance = getDrawDistanceFromDetail(minDetailLevel -1);
if (distance > maxDetailDistance)
{
return minDetailLevel - 1;
}
return (byte) MathUtil.clamp(minDetail, detail+minDetail, maxDetail - 1);
int detailLevel = (int) (Math.log(distance / distanceUnit) / logBase);
return (byte) MathUtil.clamp(maxDetailLevel, detailLevel, minDetailLevel - 1);
}
public static byte getDetailLevelFromDistance(double distance)
{
return baseInverseFunction(distance);
}
public static byte getDetailLevelFromDistance(double distance) { return baseInverseFunction(distance); }
}