Compare commits

..

28 Commits

Author SHA1 Message Date
James Seibel afe4e111c3 Add release version a1.3.2 2021-08-04 22:58:06 -05:00
James Seibel 3675c5da46 Add deprecation suppressions in LodRenderer 2021-07-29 07:20:22 -05:00
James Seibel a4cc39dbac Add 400 px icons 2021-07-27 22:32:18 -05:00
James Seibel e3787079b7 Add icon files 2021-07-27 21:24:11 -05:00
James Seibel b2f98e2d92 Improve grass colors (#36) 2021-07-26 22:27:20 -05:00
James Seibel e1edd01069 Implement a few small features in LodServerWorld 2021-07-26 22:20:00 -05:00
James Seibel eb3455452b Fix getting the GPU's fancy fog capabilities 2021-07-26 20:26:24 -05:00
James Seibel 34baf923b2 Fix #45 (Half and Full qualities checkerboard) 2021-07-26 07:56:00 -05:00
James Seibel 499308870d fix a typo 2021-07-25 20:55:15 -05:00
James Seibel f852a79a0e Fix LODs rendering with an offset 2021-07-25 20:52:30 -05:00
James Seibel fa98454151 Hopefully reduce the chance of index out of bounds exceptions 2021-07-25 20:51:52 -05:00
James Seibel 286fc91db6 Slightly improve gamma lighting 2021-07-25 20:51:18 -05:00
James Seibel 99209f920d Fix a few truncation and off by 1 errors 2021-07-25 18:48:25 -05:00
James Seibel 19fd1aff98 Close #36 (Improve foliage colors)
While the colors could still be improved, I'm not sure what else to do with them to do so.
2021-07-25 18:20:34 -05:00
James Seibel 9ebc5aeb32 Improve comments in CublicLodTemplate 2021-07-25 18:06:42 -05:00
James Seibel 7c890a4627 Add a config option to change LOD brightness and saturation
Related to issue #36
2021-07-25 18:00:39 -05:00
James Seibel ccc661225e Improve the DARKEN_SIDES shading mode 2021-07-25 17:58:46 -05:00
James Seibel d7b13a2e0b fix a typo 2021-07-25 15:49:18 -05:00
James Seibel c53ce15f7d Hopefully fix #38 (teleporting causing regions to save in the wrong place) 2021-07-25 14:14:07 -05:00
James Seibel 35ac6fc756 Fix a typo 2021-07-25 14:10:08 -05:00
James Seibel 6bcf58959b Fix #46 (MC crashing when joining a server) 2021-07-25 13:18:47 -05:00
James Seibel 5051508e42 Fix #48 (Lava showing up as water) 2021-07-25 12:29:40 -05:00
James Seibel 196e02e61a Partially close #43 (add SSAO)
I am surprised how much this small change improves how things look. I may still implement SSAO in the future but for the time being this is a big improvement for how things look.
2021-07-25 12:19:14 -05:00
James Seibel 814ac5df84 Change distanceBiomeOnlyGeneration to distanceGenerationMode in the configHandler 2021-07-11 18:41:38 -05:00
James Seibel 55f9d142e6 Add 1.16.5 a1.3.1 to the compiled Jars 2021-07-09 23:10:36 -05:00
James Seibel 58607ab1fc Update the version to a1.3.1 2021-07-09 23:09:32 -05:00
James Seibel 433ab4f92f Fix #37 (Z fighting far from the world's origin) 2021-07-09 23:08:30 -05:00
James Seibel 8840973a1e Fix #41 (leaving a world causing Lod generation to break) 2021-07-09 22:57:32 -05:00
23 changed files with 806 additions and 177 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -18,7 +18,7 @@ apply plugin: 'org.spongepowered.mixin'
apply plugin: 'eclipse'
apply plugin: 'maven-publish'
version = 'a1.3'
version = 'a1.3.2'
group = 'com.backsun.lod'
archivesBaseName = 'lod_1.16.5'
-20
View File
@@ -17,15 +17,11 @@
*/
package com.seibel.lod;
import org.lwjgl.opengl.GL;
import com.seibel.lod.handlers.LodConfig;
import com.seibel.lod.proxy.ClientProxy;
import com.seibel.lod.render.LodRenderer;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.DeferredWorkQueue;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig;
@@ -55,22 +51,6 @@ public class LodMain
private void init(final FMLCommonSetupEvent event)
{
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, LodConfig.clientSpec);
Thread setFancyFog = new Thread(() ->
{
LodRenderer.fancyFogAvailable = GL.getCapabilities().GL_NV_fog_distance;
if (!LodRenderer.fancyFogAvailable)
{
ClientProxy.LOGGER.info("This GPU does not support GL_NV_fog_distance. This means that fancy fog options will not be available.");
}
});
// This will be run on the main thread when it is able.
// If it wasn't run on the main thread GL.getCapabilities()
// would fail.
DeferredWorkQueue.runLater(setFancyFog);
}
+1 -1
View File
@@ -28,5 +28,5 @@ public final class ModInfo
public static final String MODID = "lod";
public static final String MODNAME = "Level of Detail";
public static final String MODAPI = "LodAPI";
public static final String VERSION = "a1.3";
public static final String VERSION = "a1.3.2";
}
@@ -24,6 +24,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import org.lwjgl.opengl.GL11;
import com.seibel.lod.builders.worldGeneration.LodChunkGenWorker;
import com.seibel.lod.enums.LodDetail;
import com.seibel.lod.handlers.LodConfig;
import com.seibel.lod.objects.LodChunk;
import com.seibel.lod.objects.LodDimension;
@@ -34,8 +35,6 @@ import com.seibel.lod.util.LodUtil;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.biome.BiomeContainer;
import net.minecraft.world.chunk.ChunkStatus;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.common.WorldWorkerManager;
@@ -43,7 +42,7 @@ import net.minecraftforge.common.WorldWorkerManager;
* This object is used to create NearFarBuffer objects.
*
* @author James Seibel
* @version 06-19-2021
* @version 07-25-2021
*/
public class LodBufferBuilder
{
@@ -90,15 +89,11 @@ public class LodBufferBuilder
}
private BiomeContainer biomeContainer = null;
private LodDimension previousDimension = null;
/**
* Create a thread to asynchronously generate LOD buffers
* centered around the given camera X and Z.
* <br>
* This method will write to the drawableNearBuffers and drawableFarBuffers.
* This method will write to the drawable near and far buffers.
* <br>
* After the buildable buffers have been generated they must be
* swapped with the drawable buffers in the LodRenderer to be drawn.
@@ -113,12 +108,6 @@ public class LodBufferBuilder
if (buildableNearBuffer == null || buildableFarBuffer == null)
throw new IllegalStateException("generateLodBuffersAsync was called before the buildableNearBuffer and buildableFarBuffer were created.");
if (previousDimension != lodDim)
{
biomeContainer = LodUtil.getServerWorldFromDimension(lodDim.dimension).getChunk(0, 0, ChunkStatus.EMPTY).getBiomes();
previousDimension = lodDim;
}
generatingBuffers = true;
@@ -168,12 +157,14 @@ public class LodBufferBuilder
continue;
}
LodDetail detail = LodConfig.CLIENT.lodDetail.get();
// set where this square will be drawn in the world
double xOffset = (LodChunk.WIDTH * i) + // offset by the number of LOD blocks
startX; // offset so the center LOD block is centered underneath the player
startX + // offset so the center LOD block is centered underneath the player
detail.offset; // truncation(?) correction
double yOffset = 0;
double zOffset = (LodChunk.WIDTH * j) + startZ;
double zOffset = (LodChunk.WIDTH * j) + startZ + detail.offset;
LodChunk lod = lodDim.getLodFromCoordinates(chunkX, chunkZ);
@@ -209,8 +200,9 @@ public class LodBufferBuilder
// issue #40
// TODO optimize this code,
// using the purely optimized code above we can achieve close to
// 100% CPU utilization, this code generally achieves 40 - 50 %
// I'm sure there is a better data structure for this.
// 100% CPU utilization, this code generally achieves 40 - 50%
// after a certain point; and I'm sure there is a better data
// structure for this.
if (newDistance < minChunkDist)
{
// this chunk is closer, clear any previous
@@ -269,11 +261,12 @@ public class LodBufferBuilder
chunkGenIndex++;
}
}
}
// don't render this null chunk
} // lod null and can generate more chunks
// don't render this null/empty chunk
continue;
}
} // lod null or empty
BufferBuilder currentBuffer = null;
@@ -290,6 +283,7 @@ public class LodBufferBuilder
}
}
// issue #19
// TODO add a way for a server side mod to generate chunks requested here
if(mc.hasSingleplayerServer())
{
@@ -315,7 +309,7 @@ public class LodBufferBuilder
numberOfChunksWaitingToGenerate.addAndGet(1);
LodChunkGenWorker genWorker = new LodChunkGenWorker(chunkPos, renderer, lodChunkBuilder, this, lodDim, serverWorld, biomeContainer);
LodChunkGenWorker genWorker = new LodChunkGenWorker(chunkPos, renderer, lodChunkBuilder, this, lodDim, serverWorld);
WorldWorkerManager.addWorker(genWorker);
}
}
@@ -33,10 +33,10 @@ import net.minecraft.block.AbstractPlantBlock;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.BushBlock;
import net.minecraft.block.FlowingFluidBlock;
import net.minecraft.block.GrassBlock;
import net.minecraft.block.IGrowable;
import net.minecraft.block.LeavesBlock;
import net.minecraft.block.material.MaterialColor;
import net.minecraft.world.DimensionType;
import net.minecraft.world.IWorld;
import net.minecraft.world.biome.Biome;
@@ -50,7 +50,7 @@ import net.minecraft.world.gen.Heightmap;
* (specifically: Lod World, Dimension, Region, and Chunk objects)
*
* @author James Seibel
* @version 6-27-2021
* @version 7-26-2021
*/
public class LodChunkBuilder
{
@@ -64,6 +64,13 @@ public class LodChunkBuilder
public static final int CHUNK_SECTION_HEIGHT = LodChunk.WIDTH;
// reminder now how to access biome info
// String name = biome.getRegistryName().getPath();
// String deepColdName = Biomes.DEEP_COLD_OCEAN.location().getPath();
// Biome deepCold = WorldGenRegistries.BIOME.get(Biomes.DEEP_COLD_OCEAN);
public LodChunkBuilder()
{
@@ -289,7 +296,7 @@ public class LodChunkBuilder
// enough blocks in this
// layer to count as an
// LOD point
return (short) (y + (section * CHUNK_SECTION_HEIGHT));
return (short) (y + 1 + (section * CHUNK_SECTION_HEIGHT));
}
}
}
@@ -334,7 +341,7 @@ public class LodChunkBuilder
* If true use biome foliage, water, and grass colors, <br>
* otherwise only use the block's material color
*/
private Color generateLodColorForArea(IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX, int endZ)
private Color generateLodColorForArea(IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX, int endZ)
{
ChunkSection[] chunkSections = chunk.getSections();
@@ -374,7 +381,8 @@ public class LodChunkBuilder
if (config.useBiomeColors)
{
Biome biome = chunk.getBiomes().getNoiseBiome(x, y + i * chunkSections.length, z);
// the bit shift is equivalent to dividing by 4
Biome biome = chunk.getBiomes().getNoiseBiome(x >> 2, y + i * chunkSections.length >> 2, z >> 2);
if (biome.getBiomeCategory() == Biome.Category.OCEAN ||
biome.getBiomeCategory() == Biome.Category.RIVER)
@@ -414,7 +422,9 @@ public class LodChunkBuilder
}
else
{
Biome biome = chunk.getBiomes().getNoiseBiome(x, y + i * chunkSections.length, z);
// I have no idea why I need to bit shift to the right, but
// if I don't the biomes don't show up correctly.
Biome biome = chunk.getBiomes().getNoiseBiome(x >> 2, y + i * chunkSections.length >> 2, z >> 2);
colorInt = getColorForBlock(x,z, blockState, biome);
}
@@ -434,7 +444,6 @@ public class LodChunkBuilder
}
}
}
}
}
@@ -457,12 +466,17 @@ public class LodChunkBuilder
{
int colorInt = 0;
// block special cases
if (blockState == Blocks.AIR.defaultBlockState())
{
colorInt = biome.getGrassColor(x, z);
}
else if (blockState == Blocks.MYCELIUM.defaultBlockState())
{
colorInt = MaterialColor.COLOR_LIGHT_GRAY.col;
}
// plant life
else if (blockState.getBlock() instanceof LeavesBlock)
{
Color leafColor = LodUtil.intToColor(biome.getFoliageColor()).darker();
@@ -473,12 +487,18 @@ public class LodChunkBuilder
blockState.getBlock() instanceof BushBlock ||
blockState.getBlock() instanceof IGrowable)
{
colorInt = biome.getGrassColor(x, z);
Color tmp = LodUtil.intToColor(biome.getGrassColor(x, z));
tmp = tmp.darker();
colorInt = LodUtil.colorToInt(tmp);
}
else if (blockState.getBlock() instanceof FlowingFluidBlock)
// water
else if (blockState.getBlock() == Blocks.WATER)
{
colorInt = biome.getWaterColor();
}
// everything else
else
{
colorInt = blockState.materialColor.col;
@@ -19,11 +19,12 @@ package com.seibel.lod.builders.lodTemplates;
import java.awt.Color;
import com.seibel.lod.enums.ColorDirection;
import com.seibel.lod.enums.LodDetail;
import com.seibel.lod.enums.ShadingMode;
import com.seibel.lod.handlers.LodConfig;
import com.seibel.lod.objects.LodChunk;
import com.seibel.lod.objects.LodDimension;
import com.seibel.lod.util.LodUtil;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.util.math.AxisAlignedBB;
@@ -32,7 +33,7 @@ import net.minecraft.util.math.AxisAlignedBB;
* Builds LODs as rectangular prisms.
*
* @author James Seibel
* @version 06-16-2021
* @version 07-25-2021
*/
public class CubicLodTemplate extends AbstractLodTemplate
{
@@ -104,77 +105,82 @@ public class CubicLodTemplate extends AbstractLodTemplate
private void addBoundingBoxToBuffer(BufferBuilder buffer, AxisAlignedBB bb, Color c)
{
Color topColor = c;
Color northSouthColor = c;
Color eastWestColor = c;
Color bottomColor = c;
// darken the bottom and side colors if requested
if (LodConfig.CLIENT.shadingMode.get() == ShadingMode.DARKEN_SIDES)
{
// the side colors are different because
// when using fast lighting in Minecraft the north/south
// and east/west sides are different in a similar way
int northSouthDarkenAmount = 25;
int eastWestDarkenAmount = 50;
int bottomDarkenAmount = 75;
northSouthColor = new Color(Math.max(0, c.getRed() - northSouthDarkenAmount), Math.max(0, c.getGreen() - northSouthDarkenAmount), Math.max(0, c.getBlue() - northSouthDarkenAmount), c.getAlpha());
eastWestColor = new Color(Math.max(0, c.getRed() - eastWestDarkenAmount), Math.max(0, c.getGreen() - eastWestDarkenAmount), Math.max(0, c.getBlue() - eastWestDarkenAmount), c.getAlpha());
bottomColor = new Color(Math.max(0, c.getRed() - bottomDarkenAmount), Math.max(0, c.getGreen() - bottomDarkenAmount), Math.max(0, c.getBlue() - bottomDarkenAmount), c.getAlpha());
}
// apply the user specified saturation and brightness
float saturationMultiplier = LodConfig.CLIENT.saturationMultiplier.get().floatValue();
float brightnessMultiplier = LodConfig.CLIENT.brightnessMultiplier.get().floatValue();
topColor = applySaturationAndBrightnessMultipliers(topColor, saturationMultiplier, brightnessMultiplier);
northSouthColor = applySaturationAndBrightnessMultipliers(northSouthColor, saturationMultiplier, brightnessMultiplier);
bottomColor = applySaturationAndBrightnessMultipliers(bottomColor, saturationMultiplier, brightnessMultiplier);
// top (facing up)
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, topColor.getRed(), topColor.getGreen(), topColor.getBlue(), topColor.getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, topColor.getRed(), topColor.getGreen(), topColor.getBlue(), topColor.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, topColor.getRed(), topColor.getGreen(), topColor.getBlue(), topColor.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, topColor.getRed(), topColor.getGreen(), topColor.getBlue(), topColor.getAlpha());
// bottom (facing down)
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, bottomColor.getRed(), bottomColor.getGreen(), bottomColor.getBlue(), bottomColor.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, bottomColor.getRed(), bottomColor.getGreen(), bottomColor.getBlue(), bottomColor.getAlpha());
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, bottomColor.getRed(), bottomColor.getGreen(), bottomColor.getBlue(), bottomColor.getAlpha());
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, bottomColor.getRed(), bottomColor.getGreen(), bottomColor.getBlue(), bottomColor.getAlpha());
// south (facing -Z)
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, northSouthColor.getRed(), northSouthColor.getGreen(), northSouthColor.getBlue(), northSouthColor.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, northSouthColor.getRed(), northSouthColor.getGreen(), northSouthColor.getBlue(), northSouthColor.getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, northSouthColor.getRed(), northSouthColor.getGreen(), northSouthColor.getBlue(), northSouthColor.getAlpha());
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, northSouthColor.getRed(), northSouthColor.getGreen(), northSouthColor.getBlue(), northSouthColor.getAlpha());
// north (facing +Z)
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, northSouthColor.getRed(), northSouthColor.getGreen(), northSouthColor.getBlue(), northSouthColor.getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, northSouthColor.getRed(), northSouthColor.getGreen(), northSouthColor.getBlue(), northSouthColor.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, northSouthColor.getRed(), northSouthColor.getGreen(), northSouthColor.getBlue(), northSouthColor.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, northSouthColor.getRed(), northSouthColor.getGreen(), northSouthColor.getBlue(), northSouthColor.getAlpha());
// west (facing -X)
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, eastWestColor.getRed(), eastWestColor.getGreen(), eastWestColor.getBlue(), eastWestColor.getAlpha());
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, eastWestColor.getRed(), eastWestColor.getGreen(), eastWestColor.getBlue(), eastWestColor.getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, eastWestColor.getRed(), eastWestColor.getGreen(), eastWestColor.getBlue(), eastWestColor.getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, eastWestColor.getRed(), eastWestColor.getGreen(), eastWestColor.getBlue(), eastWestColor.getAlpha());
// east (facing +X)
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, eastWestColor.getRed(), eastWestColor.getGreen(), eastWestColor.getBlue(), eastWestColor.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, eastWestColor.getRed(), eastWestColor.getGreen(), eastWestColor.getBlue(), eastWestColor.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, eastWestColor.getRed(), eastWestColor.getGreen(), eastWestColor.getBlue(), eastWestColor.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, eastWestColor.getRed(), eastWestColor.getGreen(), eastWestColor.getBlue(), eastWestColor.getAlpha());
}
@SuppressWarnings("unused")
private void addBoundingBoxToBuffer(BufferBuilder buffer, AxisAlignedBB bb, Color[] c)
/**
* Edit the given color as a HSV (Hue Saturation Value) color.
*/
private Color applySaturationAndBrightnessMultipliers(Color color, float saturationMultiplier, float brightnessMultiplier)
{
// top (facing up)
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, c[ColorDirection.TOP.value].getRed(), c[ColorDirection.TOP.value].getGreen(), c[ColorDirection.TOP.value].getBlue(), c[ColorDirection.TOP.value].getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, c[ColorDirection.TOP.value].getRed(), c[ColorDirection.TOP.value].getGreen(), c[ColorDirection.TOP.value].getBlue(), c[ColorDirection.TOP.value].getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, c[ColorDirection.TOP.value].getRed(), c[ColorDirection.TOP.value].getGreen(), c[ColorDirection.TOP.value].getBlue(), c[ColorDirection.TOP.value].getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, c[ColorDirection.TOP.value].getRed(), c[ColorDirection.TOP.value].getGreen(), c[ColorDirection.TOP.value].getBlue(), c[ColorDirection.TOP.value].getAlpha());
// bottom (facing down)
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, c[ColorDirection.BOTTOM.value].getRed(), c[ColorDirection.BOTTOM.value].getGreen(), c[ColorDirection.BOTTOM.value].getBlue(), c[ColorDirection.BOTTOM.value].getAlpha());
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, c[ColorDirection.BOTTOM.value].getRed(), c[ColorDirection.BOTTOM.value].getGreen(), c[ColorDirection.BOTTOM.value].getBlue(), c[ColorDirection.BOTTOM.value].getAlpha());
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, c[ColorDirection.BOTTOM.value].getRed(), c[ColorDirection.BOTTOM.value].getGreen(), c[ColorDirection.BOTTOM.value].getBlue(), c[ColorDirection.BOTTOM.value].getAlpha());
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, c[ColorDirection.BOTTOM.value].getRed(), c[ColorDirection.BOTTOM.value].getGreen(), c[ColorDirection.BOTTOM.value].getBlue(), c[ColorDirection.BOTTOM.value].getAlpha());
// south (facing -Z)
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, c[ColorDirection.SOUTH.value].getRed(), c[ColorDirection.SOUTH.value].getGreen(), c[ColorDirection.SOUTH.value].getBlue(), c[ColorDirection.SOUTH.value].getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, c[ColorDirection.SOUTH.value].getRed(), c[ColorDirection.SOUTH.value].getGreen(), c[ColorDirection.SOUTH.value].getBlue(), c[ColorDirection.SOUTH.value].getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, c[ColorDirection.SOUTH.value].getRed(), c[ColorDirection.SOUTH.value].getGreen(), c[ColorDirection.SOUTH.value].getBlue(), c[ColorDirection.SOUTH.value].getAlpha());
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, c[ColorDirection.SOUTH.value].getRed(), c[ColorDirection.SOUTH.value].getGreen(), c[ColorDirection.SOUTH.value].getBlue(), c[ColorDirection.SOUTH.value].getAlpha());
// north (facing +Z)
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, c[ColorDirection.NORTH.value].getRed(), c[ColorDirection.NORTH.value].getGreen(), c[ColorDirection.NORTH.value].getBlue(), c[ColorDirection.NORTH.value].getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, c[ColorDirection.NORTH.value].getRed(), c[ColorDirection.NORTH.value].getGreen(), c[ColorDirection.NORTH.value].getBlue(), c[ColorDirection.NORTH.value].getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, c[ColorDirection.NORTH.value].getRed(), c[ColorDirection.NORTH.value].getGreen(), c[ColorDirection.NORTH.value].getBlue(), c[ColorDirection.NORTH.value].getAlpha());
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, c[ColorDirection.NORTH.value].getRed(), c[ColorDirection.NORTH.value].getGreen(), c[ColorDirection.NORTH.value].getBlue(), c[ColorDirection.NORTH.value].getAlpha());
// west (facing -X)
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, c[ColorDirection.WEST.value].getRed(), c[ColorDirection.WEST.value].getGreen(), c[ColorDirection.WEST.value].getBlue(), c[ColorDirection.WEST.value].getAlpha());
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, c[ColorDirection.WEST.value].getRed(), c[ColorDirection.WEST.value].getGreen(), c[ColorDirection.WEST.value].getBlue(), c[ColorDirection.WEST.value].getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, c[ColorDirection.WEST.value].getRed(), c[ColorDirection.WEST.value].getGreen(), c[ColorDirection.WEST.value].getBlue(), c[ColorDirection.WEST.value].getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, c[ColorDirection.WEST.value].getRed(), c[ColorDirection.WEST.value].getGreen(), c[ColorDirection.WEST.value].getBlue(), c[ColorDirection.WEST.value].getAlpha());
// east (facing +X)
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, c[ColorDirection.EAST.value].getRed(), c[ColorDirection.EAST.value].getGreen(), c[ColorDirection.EAST.value].getBlue(), c[ColorDirection.EAST.value].getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, c[ColorDirection.EAST.value].getRed(), c[ColorDirection.EAST.value].getGreen(), c[ColorDirection.EAST.value].getBlue(), c[ColorDirection.EAST.value].getAlpha());
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, c[ColorDirection.EAST.value].getRed(), c[ColorDirection.EAST.value].getGreen(), c[ColorDirection.EAST.value].getBlue(), c[ColorDirection.EAST.value].getAlpha());
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, c[ColorDirection.EAST.value].getRed(), c[ColorDirection.EAST.value].getGreen(), c[ColorDirection.EAST.value].getBlue(), c[ColorDirection.EAST.value].getAlpha());
float[] hsv = Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), null);
return Color.getHSBColor(
hsv[0], // hue
LodUtil.clamp(0.0f, hsv[1] * saturationMultiplier, 1.0f),
LodUtil.clamp(0.0f, hsv[2] * brightnessMultiplier, 1.0f));
}
@@ -43,7 +43,6 @@ import net.minecraft.util.WeightedList.Entry;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.palette.UpgradeData;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.BiomeContainer;
import net.minecraft.world.chunk.ChunkPrimer;
import net.minecraft.world.chunk.ChunkStatus;
import net.minecraft.world.chunk.IChunk;
@@ -70,11 +69,11 @@ import net.minecraftforge.common.WorldWorkerManager.IWorker;
* This is used to generate a LodChunk at a given ChunkPos.
*
* @author James Seibel
* @version 7-5-2021
* @version 7-26-2021
*/
public class LodChunkGenWorker implements IWorker
{
public static final ExecutorService genThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.numberOfWorldGenerationThreads.get());
public static ExecutorService genThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.numberOfWorldGenerationThreads.get());
private boolean threadStarted = false;
private LodChunkGenThread thread;
@@ -88,12 +87,29 @@ public class LodChunkGenWorker implements IWorker
public LodChunkGenWorker(ChunkPos newPos, LodRenderer newLodRenderer,
LodChunkBuilder newLodBuilder, LodBufferBuilder newLodBufferBuilder,
LodDimension newLodDimension, ServerWorld newServerWorld,
BiomeContainer newBiomeContainer)
LodDimension newLodDimension, ServerWorld newServerWorld)
{
// just a few sanity checks
if (newPos == null)
throw new IllegalArgumentException("LodChunkGenWorker must have a non-null ChunkPos");
if (newLodRenderer == null)
throw new IllegalArgumentException("LodChunkGenWorker must have a non-null LodRenderer");
if (newLodBuilder == null)
throw new IllegalArgumentException("LodChunkGenThread requires a non-null LodChunkBuilder");
if (newLodBufferBuilder == null)
throw new IllegalArgumentException("LodChunkGenThread requires a non-null LodBufferBuilder");
if (newLodDimension == null)
throw new IllegalArgumentException("LodChunkGenThread requires a non-null LodDimension");
if (newServerWorld == null)
throw new IllegalArgumentException("LodChunkGenWorker must have a non-null ServerWorld");
throw new IllegalArgumentException("LodChunkGenThread requires a non-null ServerWorld");
thread = new LodChunkGenThread(newPos, newLodRenderer,
newLodBuilder, newLodBufferBuilder,
newLodDimension, newServerWorld);
@@ -124,6 +140,7 @@ public class LodChunkGenWorker implements IWorker
// useful for debugging
// ClientProxy.LOGGER.info(thread.lodDim.getNumberOfLods());
// ClientProxy.LOGGER.info(genThreads.toString());
}
return false;
@@ -144,7 +161,7 @@ public class LodChunkGenWorker implements IWorker
public final LodDimension lodDim;
public final LodChunkBuilder lodChunkBuilder;
public final LodRenderer lodRenderer;
private LodBufferBuilder lodBufferBuilder;
private final LodBufferBuilder lodBufferBuilder;
private ChunkPos pos;
@@ -246,7 +263,7 @@ public class LodChunkGenWorker implements IWorker
// these heights are of course aren't super accurate,
// they are just to simulate height data where there isn't any
switch(chunk.getBiomes().getNoiseBiome(x, seaLevel, z).getBiomeCategory())
switch(chunk.getBiomes().getNoiseBiome(x >> 2, seaLevel >> 2, z >> 2).getBiomeCategory())
{
case NETHER:
heightmap.setHeight(x, z, serverWorld.getHeight() / 2);
@@ -383,7 +400,7 @@ public class LodChunkGenWorker implements IWorker
{
for (int z = 0; z < LodChunk.WIDTH; z++)
{
Biome biome = chunk.getBiomes().getNoiseBiome(x, serverWorld.getSeaLevel(), z);
Biome biome = chunk.getBiomes().getNoiseBiome(x >> 2, serverWorld.getSeaLevel() >> 2, z >> 2);
// Issue #35
// For some reason Jungle biomes cause incredible lag
@@ -573,6 +590,28 @@ public class LodChunkGenWorker implements IWorker
}
/**
* Stops the current genThreads if they are running
* and then recreates the Executer service. <br><br>
*
* This is done to clear any outstanding tasks
* that may exist after the player leaves their current world.
* If this isn't done unfinished tasks may be left in the queue
* preventing new LodChunks form being generated.
*/
public static void restartExecuterService()
{
if (genThreads != null && !genThreads.isShutdown())
{
genThreads.shutdownNow();
}
genThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.numberOfWorldGenerationThreads.get());
}
/*
* performance/generation tests related to
* serverWorld.getChunk(x, z, ChunkStatus. *** )
@@ -67,7 +67,7 @@ import net.minecraft.world.storage.IWorldInfo;
* to multithread generation.
*
* @author James Seibel
* @version 7-4-2021
* @version 7-26-2021
*/
public class LodServerWorld implements ISeedReader {
@@ -101,7 +101,7 @@ public class LodServerWorld implements ISeedReader {
@Override
public Biome getBiome(BlockPos pos)
{
return chunk.getBiomes().getNoiseBiome(pos.getX(), pos.getY(), pos.getZ());
return chunk.getBiomes().getNoiseBiome(pos.getX() >> 2, pos.getY() >> 2, pos.getZ() >> 2);
}
@Override
@@ -160,6 +160,17 @@ public class LodServerWorld implements ISeedReader {
return new WorldLightManager(null, false, false);
}
@Override
public long getSeed()
{
return serverWorld.getSeed();
}
@Override
public DynamicRegistries registryAccess()
{
return serverWorld.registryAccess();
}
@@ -190,10 +201,6 @@ public class LodServerWorld implements ISeedReader {
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public DynamicRegistries registryAccess() {
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public BiomeManager getBiomeManager() {
throw new UnsupportedOperationException("Not Implemented");
}
@@ -221,11 +228,6 @@ public class LodServerWorld implements ISeedReader {
public boolean destroyBlock(BlockPos pos, boolean dropBlock, Entity entity, int recursionLeft) {
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public long getSeed() {
throw new UnsupportedOperationException("Not Implemented");
}
@Override
@@ -17,31 +17,30 @@
*/
package com.seibel.lod.enums;
import com.seibel.lod.objects.LodChunk;
import com.seibel.lod.objects.LodDataPoint;
/**
* single, double, quad, half, full
*
* @author James Seibel
* @version 06-13-2021
* @version 07-26-2021
*/
public enum LodDetail
{
/** render 1 LOD for each chunk */
SINGLE(1),
SINGLE(1, 4),
/** render 4 LODs for each chunk */
DOUBLE(2),
DOUBLE(2, 2),
/** render 16 LODs for each chunk */
QUAD(4),
QUAD(4, 1),
/** render 64 LODs for each chunk */
HALF(8),
HALF(8, 0),
/** render 256 LODs for each chunk */
FULL(16);
FULL(16, 0);
/** How many DataPoints should
@@ -62,19 +61,19 @@ public enum LodDetail
* when creating a LodChunk with this detail level */
public final int lodChunkStringDelimiterCount;
/** in LodBufferBuilder some detail options don't render
* in the correct spot, this number fixes that.
* TODO find out why this is needed and see if it
* needed / could be removed */
public final int offset;
private LodDetail(int newLengthCount)
private LodDetail(int newLengthCount, int newOffset)
{
dataPointLengthCount = newLengthCount;
dataPointWidth = 16 / dataPointLengthCount;
if(newLengthCount == LodChunk.WIDTH)
{
// this is to prevent overflow
newLengthCount = LodChunk.WIDTH - 1;
}
offset = newOffset;
startX = new int[dataPointLengthCount * dataPointLengthCount];
endX = new int[dataPointLengthCount * dataPointLengthCount];
@@ -0,0 +1,18 @@
package com.seibel.lod.enums;
/**
* NONE, DARKEN_SIDES
*
* @author James Seibel
* @version 7-25-2020
*/
public enum ShadingMode
{
/** LODs will have the same lighting on every side.
Fastest, but can make large similarly colored areas hard to differentiate */
NONE,
/** LODs will have darker sides and bottoms to simulate top down lighting.
Fastest */
DARKEN_SIDES;
}
@@ -31,6 +31,7 @@ import com.seibel.lod.enums.FogDistance;
import com.seibel.lod.enums.FogDrawOverride;
import com.seibel.lod.enums.LodDetail;
import com.seibel.lod.enums.LodTemplate;
import com.seibel.lod.enums.ShadingMode;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.eventbus.api.SubscribeEvent;
@@ -40,7 +41,7 @@ import net.minecraftforge.fml.config.ModConfig;
/**
*
* @author James Seibel
* @version 7-5-2021
* @version 7-25-2021
*/
@Mod.EventBusSubscriber
public class LodConfig
@@ -65,10 +66,15 @@ public class LodConfig
public ForgeConfigSpec.IntValue numberOfWorldGenerationThreads;
public ForgeConfigSpec.EnumValue<ShadingMode> shadingMode;
/** this is multiplied by the default view distance
* to determine how far out to generate/render LODs */
public ForgeConfigSpec.IntValue lodChunkRadiusMultiplier;
public ForgeConfigSpec.DoubleValue brightnessMultiplier;
public ForgeConfigSpec.DoubleValue saturationMultiplier;
Client(ForgeConfigSpec.Builder builder)
@@ -177,11 +183,11 @@ public class LodConfig
+ " This will also show player made structures if you \n"
+ " are adding the mod to a pre-existing world. \n"
+ " Singlethreaded - Slow (15-50 ms, with spikes up to 200 ms) \n")
.defineEnum("distanceBiomeOnlyGeneration", DistanceGenerationMode.SURFACE);
.defineEnum("distanceGenerationMode", DistanceGenerationMode.SURFACE);
allowUnstableFeatureGeneration = builder
.comment("\n\n"
+ " When using the " + DistanceGenerationMode.FEATURES.toString() + "generation mode \n"
+ " When using the " + DistanceGenerationMode.FEATURES.toString() + " generation mode \n"
+ " some features may not be thread safe, which could \n"
+ " cause instability and crashes. \n"
+ " By default (false) those features are skipped, \n"
@@ -210,6 +216,36 @@ public class LodConfig
)
.defineInRange("numberOfWorldGenerationThreads", Runtime.getRuntime().availableProcessors(), 1, Runtime.getRuntime().availableProcessors());
shadingMode = builder
.comment("\n\n"
+ " What kind of shading should LODs have? \n"
+ " " + ShadingMode.NONE.toString() + " \n"
+ " " + "LODs will have the same lighting on every side. \n"
+ " " + "Can make large similarly colored areas hard to differentiate. \n"
+ " " + "Fastest"
+ "/n"
+ " " + ShadingMode.DARKEN_SIDES.toString() + " \n"
+ " " + "LODs will have darker sides and bottoms to simulate top down lighting."
+ " " + "Fastest /n")
.defineEnum("lightingMode", ShadingMode.DARKEN_SIDES);
brightnessMultiplier = builder
.comment("\n\n"
+ " Change how bright LOD colors are. \n"
+ " 0 = black \n"
+ " 1 = normal color value \n"
+ " 2 = washed out colors \n")
.defineInRange("brightnessMultiplier", 1.0, 0, 2);
saturationMultiplier = builder
.comment("\n\n"
+ " Change how saturated LOD colors are. \n"
+ " 0 = black and white \n"
+ " 1 = normal saturation \n"
+ " 2 = very saturated \n")
.defineInRange("saturationMultiplier", 1.0, 0, 2);
builder.pop();
}
@@ -46,8 +46,8 @@ public class LodDimension
public volatile LodRegion regions[][];
public volatile boolean isRegionDirty[][];
private int centerX;
private int centerZ;
private volatile int centerX;
private volatile int centerZ;
private LodDimensionFileHandler fileHandler;
@@ -108,7 +108,7 @@ public class LodDimension
* Move the center of this LodDimension and move all owned
* regions over by the given x and z offset.
*/
public void move(int xOffset, int zOffset)
public synchronized void move(int xOffset, int zOffset)
{
// if the x or z offset is equal to or greater than
// the total size, just delete the current data
@@ -236,7 +236,7 @@ public class LodDimension
* Overwrite the LodRegion at the location of newRegion with newRegion.
* @throws ArrayIndexOutOfBoundsException if newRegion is outside what can be stored in this LodDimension.
*/
public void setRegion(LodRegion newRegion) throws ArrayIndexOutOfBoundsException
public void addOrOverwriteRegion(LodRegion newRegion) throws ArrayIndexOutOfBoundsException
{
int xIndex = (newRegion.x - centerX) + halfWidth;
int zIndex = (centerZ - newRegion.z) + halfWidth;
@@ -273,13 +273,13 @@ public class LodDimension
{
// if no region exists, create it
region = new LodRegion(pos.x, pos.z);
setRegion(region);
addOrOverwriteRegion(region);
}
region.addLod(lod);
// don't save empty place holders to disk
if (!lod.isPlaceholder() && fileHandler != null)
// only save valid LODs to disk
if (!(lod.isPlaceholder() || lod.dontSave) && fileHandler != null)
{
// mark the region as dirty so it will be saved to disk
int xIndex = (pos.x - centerX) + halfWidth;
@@ -388,13 +388,22 @@ public class LodDimension
public int getWidth()
{
return width;
if (regions != null)
{
// we want to get the length directly from the
// source to make sure it is in sync with region
// and isRegionDirty
return regions.length;
}
else
{
return width;
}
}
public void setRegionWidth(int newWidth)
{
width = newWidth;
halfWidth = (int)Math.floor(width / 2);
regions = new LodRegion[width][width];
isRegionDirty = new boolean[width][width];
@@ -18,7 +18,7 @@
package com.seibel.lod.objects;
/**
* A LodRegion is the a 32x32
* A LodRegion is a 32x32
* 2D array of LodChunk objects.
* Each LodRegion corresponds to
* one file in the file system.
@@ -22,6 +22,9 @@ import org.apache.logging.log4j.Logger;
import com.seibel.lod.builders.LodBufferBuilder;
import com.seibel.lod.builders.LodChunkBuilder;
import com.seibel.lod.builders.worldGeneration.LodChunkGenWorker;
import com.seibel.lod.enums.DistanceGenerationMode;
import com.seibel.lod.enums.LodDetail;
import com.seibel.lod.handlers.LodConfig;
import com.seibel.lod.objects.LodChunk;
import com.seibel.lod.objects.LodDimension;
@@ -42,7 +45,7 @@ import net.minecraftforge.eventbus.api.SubscribeEvent;
* and is the starting point for most of this program.
*
* @author James_Seibel
* @version 06-27-2021
* @version 7-9-2021
*/
public class ClientProxy
{
@@ -111,21 +114,27 @@ public class ClientProxy
// for testing
// LodConfig.CLIENT.drawLODs.set(true);
// LodConfig.CLIENT.debugMode.set(false);
// LodConfig.CLIENT.lodDetail.set(LodDetail.DOUBLE);
LodConfig.CLIENT.lodDetail.set(LodDetail.QUAD);
// LodConfig.CLIENT.lodChunkRadiusMultiplier.set(12);
// LodConfig.CLIENT.fogDistance.set(FogDistance.FAR);
// LodConfig.CLIENT.fogDrawOverride.set(FogDrawOverride.ALWAYS_DRAW_FOG_FANCY);
// LodConfig.CLIENT.shadingMode.set(ShadingMode.DARKEN_SIDES);
// LodConfig.CLIENT.brightnessMultiplier.set(1.0);
// LodConfig.CLIENT.saturationMultiplier.set(1.0);
// LodConfig.CLIENT.distanceGenerationMode.set(DistanceGenerationMode.FEATURES);
LodConfig.CLIENT.distanceGenerationMode.set(DistanceGenerationMode.FEATURES);
// LodConfig.CLIENT.allowUnstableFeatureGeneration.set(false);
// LOGGER.info(lodBufferBuilder.numberOfChunksWaitingToGenerate.get());
// Note to self:
// if "unspecified" shows up in the pie chart, it is
// possibly because the amount of time between sections
// is too small for the profile to measure
// is too small for the profiler to measure
IProfiler profiler = mc.getProfiler();
profiler.pop(); // get out of "terrain"
profiler.push("LOD");
@@ -167,6 +176,10 @@ public class ClientProxy
if(mc.getConnection().getLevel() == null)
{
// if this isn't done unfinished tasks may be left in the queue
// preventing new LodChunks form being generated
LodChunkGenWorker.restartExecuterService();
lodBufferBuilder.numberOfChunksWaitingToGenerate.set(0);
// the player has disconnected from a server
lodWorld.deselectWorld();
@@ -22,6 +22,7 @@ import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.HashSet;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.NVFogDistance;
@@ -87,7 +88,7 @@ public class LodRenderer
public static final int MAX_ALOCATEABLE_DIRECT_MEMORY = 64 * 1024 * 1024;
/** Does this computer's GPU support fancy fog? */
public static boolean fancyFogAvailable = false;
private static Boolean fancyFogAvailable = null;
@@ -153,6 +154,7 @@ public class LodRenderer
* @param newDimension The dimension to draw, if null doesn't replace the current dimension.
* @param partialTicks how far into the current tick this method was called.
*/
@SuppressWarnings("deprecation")
public void drawLODs(LodDimension lodDim, float partialTicks, IProfiler newProfiler)
{
if (lodDim == null)
@@ -174,6 +176,20 @@ public class LodRenderer
profiler = newProfiler;
profiler.push("LOD setup");
// only check the GPU capability's once
if (fancyFogAvailable == null)
{
// see if this GPU can run fancy fog
fancyFogAvailable = GL.getCapabilities().GL_NV_fog_distance;
if (!LodRenderer.fancyFogAvailable)
{
ClientProxy.LOGGER.info("This GPU does not support GL_NV_fog_distance. This means that fancy fog options will not be available.");
}
}
ClientPlayerEntity player = mc.player;
// should LODs be regenerated?
@@ -405,7 +421,7 @@ public class LodRenderer
// determine the fog distance mode to use
int glFogDistanceMode = NVFogDistance.GL_EYE_RADIAL_NV;
int glFogDistanceMode;
if (fogQuality == FogQuality.FANCY)
{
// fancy fog (fragment distance based fog)
@@ -467,6 +483,7 @@ public class LodRenderer
/**
* Revert any changes that were made to the fog.
*/
@SuppressWarnings("deprecation")
private void cleanupFog(NearFarFogSettings fogSettings,
float defaultFogStartDist, float defaultFogEndDist,
int defaultFogMode, int defaultFogDistance)
@@ -549,15 +566,16 @@ public class LodRenderer
matrixStack.mulPose(vector3f.rotationDegrees(f2));
}
// this projection matrix allows us to see past the normal
// world render distance
Matrix4f projectionMatrix =
Matrix4f.perspective(
getFov(partialTicks, true),
(float)this.mc.getWindow().getScreenWidth() / (float)this.mc.getWindow().getScreenHeight(),
0.5F,
(float)this.mc.getWindow().getScreenWidth() / (float)this.mc.getWindow().getScreenHeight(),
// it is possible to see the near clip plane, but
// you have to be flying quickly in spectator mode through ungenerated
// terrain, so I don't think it is much of an issue.
LodConfig.CLIENT.lodChunkRadiusMultiplier.get(),
this.farPlaneDistance * LodConfig.CLIENT.lodChunkRadiusMultiplier.get() * 2);
// add the screen space distortions
@@ -570,11 +588,12 @@ public class LodRenderer
/**
* setup the lighting to be used for the LODs
*/
@SuppressWarnings("deprecation")
private void setupLighting(LodDimension lodDimension, float partialTicks)
{
float sunBrightness = lodDimension.dimension.hasSkyLight() ? mc.level.getSkyDarken(partialTicks) : 0.2f;
float gammaMultiplyer = (float)mc.options.gamma - 0.5f;
float lightStrength = ((sunBrightness / 2f) - 0.2f) + (gammaMultiplyer * 0.2f);
float lightStrength = ((sunBrightness / 2f) - 0.2f) + (gammaMultiplyer * 0.3f);
float lightAmbient[] = {lightStrength, lightStrength, lightStrength, 1.0f};
@@ -254,4 +254,32 @@ public class LodUtil
{
return color.getRGB();
}
/**
* Clamps the given value between the min and max values.
* May behave strangely if min > max.
*/
public static int clamp(int min, int value, int max)
{
return Math.min(max, Math.max(value, min));
}
/**
* Clamps the given value between the min and max values.
* May behave strangely if min > max.
*/
public static float clamp(float min, float value, float max)
{
return Math.min(max, Math.max(value, min));
}
/**
* Clamps the given value between the min and max values.
* May behave strangely if min > max.
*/
public static double clamp(double min, double value, double max)
{
return Math.min(max, Math.max(value, min));
}
}
+1 -1
View File
@@ -24,7 +24,7 @@ modId="lod" #mandatory
#// The version number of the mod - there's a few well known ${} variables useable here or just hardcode it
#//${file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata
#// see the associated build.gradle script for how to populate this completely automatically during a build
version="a1.3" #mandatory
version="a1.3.2" #mandatory
#// A display name for the mod
displayName="Level of Detail" #mandatory
+1 -1
View File
@@ -3,7 +3,7 @@
"modid": "lod",
"name": "Level Of Detail",
"description": "Generates and renders simplified chunks beyond the normal view distance, at a low performance cost.",
"version": "a1.3",
"version": "a1.3.2",
"mcversion": "1.16.4",
"url": "",
"updateUrl": "",