diff --git a/src/main/java/me/cortex/voxelmon/IGetVoxelCore.java b/src/main/java/me/cortex/voxelmon/IGetVoxelCore.java new file mode 100644 index 00000000..a87559a7 --- /dev/null +++ b/src/main/java/me/cortex/voxelmon/IGetVoxelCore.java @@ -0,0 +1,7 @@ +package me.cortex.voxelmon; + +import me.cortex.voxelmon.core.VoxelCore; + +public interface IGetVoxelCore { + VoxelCore getVoxelCore(); +} diff --git a/src/main/java/me/cortex/voxelmon/Voxelmon.java b/src/main/java/me/cortex/voxelmon/Voxelmon.java index c0f07545..cfd358ce 100644 --- a/src/main/java/me/cortex/voxelmon/Voxelmon.java +++ b/src/main/java/me/cortex/voxelmon/Voxelmon.java @@ -2,13 +2,17 @@ package me.cortex.voxelmon; import me.cortex.voxelmon.terrain.TestSparseGenCommand; //import me.cortex.voxelmon.terrain.WorldImportCommand; +import me.cortex.voxelmon.terrain.WorldImportCommand; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; public class Voxelmon implements ClientModInitializer { @Override public void onInitializeClient() { - //CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> WorldImportCommand.register(dispatcher)); + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> { + dispatcher.register(WorldImportCommand.register()); + }); } } diff --git a/src/main/java/me/cortex/voxelmon/core/DistanceTracker.java b/src/main/java/me/cortex/voxelmon/core/DistanceTracker.java index a04a2c24..1f1e97f5 100644 --- a/src/main/java/me/cortex/voxelmon/core/DistanceTracker.java +++ b/src/main/java/me/cortex/voxelmon/core/DistanceTracker.java @@ -29,7 +29,7 @@ public class DistanceTracker { this.tracker = tracker; this.scale = scale; - this.rings[0] = new TransitionRing2D(5, (int) Math.ceil(MinecraftClient.getInstance().gameRenderer.getViewDistance()/16)/2, (x, z)->{ + this.rings[0] = new TransitionRing2D(5, (int) MinecraftClient.getInstance().options.getClampedViewDistance()/2, (x, z)->{ if (false) { return; } diff --git a/src/main/java/me/cortex/voxelmon/core/VoxelCore.java b/src/main/java/me/cortex/voxelmon/core/VoxelCore.java index e2a7615f..9531b8ed 100644 --- a/src/main/java/me/cortex/voxelmon/core/VoxelCore.java +++ b/src/main/java/me/cortex/voxelmon/core/VoxelCore.java @@ -48,7 +48,7 @@ import static org.lwjgl.opengl.ARBFramebufferObject.glBindFramebuffer; //Ingest -> world engine -> raw render data -> render data public class VoxelCore { private static final Set biomeTintableAllFaces = new HashSet<>(List.of(Blocks.OAK_LEAVES, Blocks.JUNGLE_LEAVES, Blocks.ACACIA_LEAVES, Blocks.DARK_OAK_LEAVES, Blocks.VINE, Blocks.MANGROVE_LEAVES, - Blocks.TALL_GRASS, Blocks.LARGE_FERN, + Blocks.TALL_GRASS, Blocks.LARGE_FERN, Blocks.SHORT_GRASS, Blocks.SPRUCE_LEAVES, Blocks.BIRCH_LEAVES, @@ -58,9 +58,6 @@ public class VoxelCore { private static final Set waterTint = new HashSet<>(List.of(Blocks.WATER)); - - public static VoxelCore INSTANCE = new VoxelCore(); - private final WorldEngine world; private final DistanceTracker distanceTracker; private final RenderGenerationService renderGen; @@ -69,6 +66,8 @@ public class VoxelCore { private final AbstractFarWorldRenderer renderer; private final PostProcessing postProcessing; + //private final Thread shutdownThread = new Thread(this::shutdown); + public VoxelCore() { //Trigger the shared index buffer loading SharedIndexBuffer.INSTANCE.id(); @@ -81,33 +80,13 @@ public class VoxelCore { this.renderTracker.setRenderGen(this.renderGen); //To get to chunk scale multiply the scale by 2, the scale is after how many chunks does the lods halve - this.distanceTracker = new DistanceTracker(this.renderTracker, 5, 16); + this.distanceTracker = new DistanceTracker(this.renderTracker, 5, 16);//20 this.postProcessing = new PostProcessing(); this.world.getMapper().setCallbacks(this::stateUpdate, this::biomeUpdate); - Runtime.getRuntime().addShutdownHook(new Thread(this::shutdown)); - - - - /* - Random r = new Random(); - for (int ring = 0; ring < 5; ring++) { - for (int x = -32; x < 32; x++) { - for (int z = -32; z < 32; z++) { - if ((-16 < x && x < 16) && (-16 < z && z < 16)) { - continue; - } - var b = new MemoryBuffer(1000 * 8); - for (long j = 0; j < b.size; j += 8) { - MemoryUtil.memPutLong(b.address + j, r.nextLong()); - } - this.renderer.enqueueResult(new BuiltSectionGeometry(WorldEngine.getWorldSectionId(ring, x, 2>>ring, z), b, null)); - } - } - }*/ - + //Runtime.getRuntime().addShutdownHook(this.shutdownThread); //WorldImporter importer = new WorldImporter(this.world, MinecraftClient.getInstance().world); @@ -200,15 +179,21 @@ public class VoxelCore { // since they are AABBS crossing the normal is impossible without one of the axis being equal public void shutdown() { - try {this.world.shutdown();} catch (Exception e) {System.err.println(e);} + //if (Thread.currentThread() != this.shutdownThread) { + // Runtime.getRuntime().removeShutdownHook(this.shutdownThread); + //} + + //this.world.getMapper().forceResaveStates(); + System.out.println("Shutting down voxel core"); try {this.renderGen.shutdown();} catch (Exception e) {System.err.println(e);} + try {this.world.shutdown();} catch (Exception e) {System.err.println(e);} try {this.renderer.shutdown();} catch (Exception e) {System.err.println(e);} try {this.postProcessing.shutdown();} catch (Exception e) {System.err.println(e);} } public WorldImporter createWorldImporter(World mcWorld, File worldPath) { var importer = new WorldImporter(this.world, mcWorld); - importer.importWorldAsyncStart(worldPath, 10, null, ()->{ + importer.importWorldAsyncStart(worldPath, 5, null, ()->{ System.err.println("DONE IMPORT"); }); return importer; diff --git a/src/main/java/me/cortex/voxelmon/core/rendering/RenderTracker.java b/src/main/java/me/cortex/voxelmon/core/rendering/RenderTracker.java index 5a68b3b2..7d60f5c8 100644 --- a/src/main/java/me/cortex/voxelmon/core/rendering/RenderTracker.java +++ b/src/main/java/me/cortex/voxelmon/core/rendering/RenderTracker.java @@ -32,47 +32,6 @@ public class RenderTracker { public RenderTracker(WorldEngine world, AbstractFarWorldRenderer renderer) { this.world = world; this.renderer = renderer; - - - - var loader = new Thread(()->{ - try { - Thread.sleep(1); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - - int OX = 0;//-27; - int OZ = 0;//276; - int DROP = 48; - - //Do ring rendering - for (int i = 0; i < 5; i++) { - for (int x = -DROP; x <= DROP; x++) { - for (int z = -DROP; z <= DROP; z++) { - int d = x*x+z*z; - if (d<(DROP/2-1)*(DROP/2) || d>DROP*DROP) - continue; - - for (int y = -3>>i; y < Math.max(1, 10 >> i); y++) { - var sec = this.world.acquire(i, x + (OX>>(1+i)), y, z + (OZ>>(1+i))); - //this.renderGen.enqueueTask(sec); - sec.release(); - } - - try { - while (this.renderGen.getTaskCount() > 1000) { - Thread.sleep(50); - } - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - } - } - }); - loader.setDaemon(true); - //loader.start(); } //Adds a lvl 0 section into the world renderer diff --git a/src/main/java/me/cortex/voxelmon/core/util/TrackedObject.java b/src/main/java/me/cortex/voxelmon/core/util/TrackedObject.java index 48904611..93390600 100644 --- a/src/main/java/me/cortex/voxelmon/core/util/TrackedObject.java +++ b/src/main/java/me/cortex/voxelmon/core/util/TrackedObject.java @@ -38,7 +38,8 @@ public abstract class TrackedObject { boolean[] freed = new boolean[1]; var clean = cleaner.register(obj, ()->{ if (!freed[0]) { - System.err.println("Object named: "+ clazz+" was not freed, location at:\n" + trace); + System.err.println("Object named: "+ clazz+" was not freed, location at:\n"); + trace.printStackTrace(); System.err.flush(); } }); diff --git a/src/main/java/me/cortex/voxelmon/core/world/other/ColourResolver.java b/src/main/java/me/cortex/voxelmon/core/world/other/ColourResolver.java index f99fb3b4..b7a02116 100644 --- a/src/main/java/me/cortex/voxelmon/core/world/other/ColourResolver.java +++ b/src/main/java/me/cortex/voxelmon/core/world/other/ColourResolver.java @@ -131,6 +131,10 @@ public class ColourResolver { public static long resolveBiomeColour(String biomeId) { var biome = MinecraftClient.getInstance().world.getRegistryManager().get(RegistryKeys.BIOME).get(new Identifier(biomeId)); + if (biome == null) { + System.err.println("Biome: " + biomeId + " doesnt exist in registry!"); + return 0; + } int ARGBFoliage = biome.getFoliageColor(); int ARGBWater = biome.getWaterColor(); return Integer.toUnsignedLong(((ARGBFoliage&0xFFFFFF)<<8)|(ARGBFoliage>>>24)) | (Integer.toUnsignedLong(((ARGBWater&0xFFFFFF)<<8)|(ARGBWater>>>24))<<32); diff --git a/src/main/java/me/cortex/voxelmon/core/world/other/Mapper.java b/src/main/java/me/cortex/voxelmon/core/world/other/Mapper.java index a3ab39b4..80fd0e99 100644 --- a/src/main/java/me/cortex/voxelmon/core/world/other/Mapper.java +++ b/src/main/java/me/cortex/voxelmon/core/world/other/Mapper.java @@ -79,6 +79,7 @@ public class Mapper { List bentries = new ArrayList<>(); List> sentryErrors = new ArrayList<>(); + for (var entry : mappings.int2ObjectEntrySet()) { int entryType = entry.getIntKey()>>>30; int id = entry.getIntKey() & ((1<<30)-1); @@ -126,6 +127,7 @@ public class Mapper { } this.blockId2stateEntry.add(entry); }); + bentries.stream().sorted(Comparator.comparing(a->a.id)).forEach(entry -> { if (this.biomeId2biomeEntry.size() != entry.id) { throw new IllegalStateException("Biome entry not ordered"); @@ -135,7 +137,7 @@ public class Mapper { } - private StateEntry registerNewBlockState(BlockState state) { + private synchronized StateEntry registerNewBlockState(BlockState state) { StateEntry entry = new StateEntry(this.blockId2stateEntry.size(), state); //this.block2stateEntry.put(state, entry); this.blockId2stateEntry.add(entry); @@ -151,7 +153,7 @@ public class Mapper { return entry; } - private BiomeEntry registerNewBiome(String biome) { + private synchronized BiomeEntry registerNewBiome(String biome) { BiomeEntry entry = new BiomeEntry(this.biome2biomeEntry.size(), biome); //this.biome2biomeEntry.put(biome, entry); this.biomeId2biomeEntry.add(entry); @@ -207,6 +209,42 @@ public class Mapper { return out; } + public void forceResaveStates() { + var blocks = new ArrayList<>(this.block2stateEntry.values()); + var biomes = new ArrayList<>(this.biome2biomeEntry.values()); + + + for (var entry : blocks) { + if (entry.state.isAir() && entry.id == 0) { + continue; + } + if (this.blockId2stateEntry.indexOf(entry) != entry.id) { + throw new IllegalStateException("State Id NOT THE SAME, very critically bad"); + } + byte[] serialized = entry.serialize(); + ByteBuffer buffer = MemoryUtil.memAlloc(serialized.length); + buffer.put(serialized); + buffer.rewind(); + this.storage.putIdMapping(entry.id | (BLOCK_STATE_TYPE<<30), buffer); + MemoryUtil.memFree(buffer); + } + + for (var entry : biomes) { + if (this.biomeId2biomeEntry.indexOf(entry) != entry.id) { + throw new IllegalStateException("Biome Id NOT THE SAME, very critically bad"); + } + + byte[] serialized = entry.serialize(); + ByteBuffer buffer = MemoryUtil.memAlloc(serialized.length); + buffer.put(serialized); + buffer.rewind(); + this.storage.putIdMapping(entry.id | (BIOME_TYPE<<30), buffer); + MemoryUtil.memFree(buffer); + } + + this.storage.flush(); + } + public static final class StateEntry { public final int id; public final BlockState state; diff --git a/src/main/java/me/cortex/voxelmon/core/world/storage/StorageBackend.java b/src/main/java/me/cortex/voxelmon/core/world/storage/StorageBackend.java index ce75f215..68b066a9 100644 --- a/src/main/java/me/cortex/voxelmon/core/world/storage/StorageBackend.java +++ b/src/main/java/me/cortex/voxelmon/core/world/storage/StorageBackend.java @@ -115,7 +115,7 @@ public class StorageBackend { })); } - public void putIdMapping(int id, ByteBuffer data) { + public synchronized void putIdMapping(int id, ByteBuffer data) { this.resizingTransaction(()->this.idMappingDatabase.transaction(transaction->{ var keyBuff = transaction.stack.malloc(4); keyBuff.putInt(0, id); @@ -135,7 +135,9 @@ public class StorageBackend { int keyVal = keyPtr.mv_data().getInt(0); byte[] data = new byte[(int) valPtr.mv_size()]; Objects.requireNonNull(valPtr.mv_data()).get(data); - mapping.put(keyVal, data); + if (mapping.put(keyVal, data) != null) { + throw new IllegalStateException("Multiple mappings to same id"); + } } } return null; diff --git a/src/main/java/me/cortex/voxelmon/mixin/minecraft/MixinClientChunkManager.java b/src/main/java/me/cortex/voxelmon/mixin/minecraft/MixinClientChunkManager.java index 539f4676..e9ae8e7f 100644 --- a/src/main/java/me/cortex/voxelmon/mixin/minecraft/MixinClientChunkManager.java +++ b/src/main/java/me/cortex/voxelmon/mixin/minecraft/MixinClientChunkManager.java @@ -1,6 +1,7 @@ package me.cortex.voxelmon.mixin.minecraft; -import me.cortex.voxelmon.core.VoxelCore; +import me.cortex.voxelmon.IGetVoxelCore; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.world.ClientChunkManager; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.chunk.WorldChunk; @@ -14,6 +15,9 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture; public class MixinClientChunkManager { @Inject(method = "unload", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/world/ClientChunkManager$ClientChunkMap;compareAndSet(ILnet/minecraft/world/chunk/WorldChunk;Lnet/minecraft/world/chunk/WorldChunk;)Lnet/minecraft/world/chunk/WorldChunk;", shift = At.Shift.BEFORE), locals = LocalCapture.CAPTURE_FAILHARD) private void injectUnload(ChunkPos pos, CallbackInfo ci, int index, WorldChunk worldChunk) { - VoxelCore.INSTANCE.enqueueIngest(worldChunk); + var core = ((IGetVoxelCore)MinecraftClient.getInstance().worldRenderer).getVoxelCore(); + if (core != null) { + core.enqueueIngest(worldChunk); + } } } diff --git a/src/main/java/me/cortex/voxelmon/mixin/minecraft/MixinDebugHud.java b/src/main/java/me/cortex/voxelmon/mixin/minecraft/MixinDebugHud.java index da689ee7..c7cd158d 100644 --- a/src/main/java/me/cortex/voxelmon/mixin/minecraft/MixinDebugHud.java +++ b/src/main/java/me/cortex/voxelmon/mixin/minecraft/MixinDebugHud.java @@ -1,6 +1,8 @@ package me.cortex.voxelmon.mixin.minecraft; +import me.cortex.voxelmon.IGetVoxelCore; import me.cortex.voxelmon.core.VoxelCore; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.hud.DebugHud; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -14,6 +16,9 @@ public class MixinDebugHud { @Inject(method = "getRightText", at = @At("TAIL")) private void injectDebug(CallbackInfoReturnable> cir) { var ret = cir.getReturnValue(); - VoxelCore.INSTANCE.addDebugInfo(ret); + var core = ((IGetVoxelCore) MinecraftClient.getInstance().worldRenderer).getVoxelCore(); + if (core != null) { + core.addDebugInfo(ret); + } } } diff --git a/src/main/java/me/cortex/voxelmon/mixin/minecraft/MixinWorldRenderer.java b/src/main/java/me/cortex/voxelmon/mixin/minecraft/MixinWorldRenderer.java index c932d324..eb854183 100644 --- a/src/main/java/me/cortex/voxelmon/mixin/minecraft/MixinWorldRenderer.java +++ b/src/main/java/me/cortex/voxelmon/mixin/minecraft/MixinWorldRenderer.java @@ -1,40 +1,80 @@ package me.cortex.voxelmon.mixin.minecraft; +import me.cortex.voxelmon.IGetVoxelCore; import me.cortex.voxelmon.Voxelmon; import me.cortex.voxelmon.core.VoxelCore; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.*; +import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher; +import net.minecraft.client.render.entity.EntityRenderDispatcher; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.client.world.ClientWorld; +import org.jetbrains.annotations.Nullable; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(WorldRenderer.class) -public abstract class MixinWorldRenderer { +public abstract class MixinWorldRenderer implements IGetVoxelCore { @Shadow protected abstract void renderLayer(RenderLayer renderLayer, MatrixStack matrices, double cameraX, double cameraY, double cameraZ, Matrix4f positionMatrix); @Shadow protected abstract void setupTerrain(Camera camera, Frustum frustum, boolean hasForcedFrustum, boolean spectator); @Shadow private Frustum frustum; + @Shadow private @Nullable ClientWorld world; + @Unique private VoxelCore core; + @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/WorldRenderer;setupTerrain(Lnet/minecraft/client/render/Camera;Lnet/minecraft/client/render/Frustum;ZZ)V", shift = At.Shift.AFTER)) private void injectSetup(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f projectionMatrix, CallbackInfo ci) { - //Call our setup method - VoxelCore.INSTANCE.renderSetup(this.frustum, camera); + this.core.renderSetup(this.frustum, camera); } @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/WorldRenderer;renderLayer(Lnet/minecraft/client/render/RenderLayer;Lnet/minecraft/client/util/math/MatrixStack;DDDLorg/joml/Matrix4f;)V", ordinal = 2, shift = At.Shift.AFTER)) private void injectOpaqueRender(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f projectionMatrix, CallbackInfo ci) { var cam = camera.getPos(); - //Call the actual render method - VoxelCore.INSTANCE.renderOpaque(matrices, cam.x, cam.y, cam.z); + this.core.renderOpaque(matrices, cam.x, cam.y, cam.z); } + public VoxelCore getVoxelCore() { + return this.core; + } + @Inject(method = "reload()V", at = @At("TAIL")) + private void resetVoxelCore(CallbackInfo ci) { + if (this.world != null && this.core != null) { + this.core.shutdown(); + this.core = new VoxelCore(); + } + } + @Inject(method = "setWorld", at = @At("TAIL")) + private void initVoxelCore(ClientWorld world, CallbackInfo ci) { + if (world == null) { + if (this.core != null) { + this.core.shutdown(); + this.core = null; + } + return; + } + if (this.core != null) { + throw new IllegalStateException("Core is not null"); + } + this.core = new VoxelCore(); + } + + @Inject(method = "close", at = @At("HEAD")) + private void injectClose(CallbackInfo ci) { + if (this.core != null) { + this.core.shutdown(); + this.core = null; + } + } diff --git a/src/main/java/me/cortex/voxelmon/terrain/WorldImportCommand.java b/src/main/java/me/cortex/voxelmon/terrain/WorldImportCommand.java index b34b2301..0b1a71f6 100644 --- a/src/main/java/me/cortex/voxelmon/terrain/WorldImportCommand.java +++ b/src/main/java/me/cortex/voxelmon/terrain/WorldImportCommand.java @@ -1,29 +1,31 @@ package me.cortex.voxelmon.terrain; -import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.context.CommandContext; -import me.cortex.voxelmon.core.VoxelCore; +import me.cortex.voxelmon.IGetVoxelCore; import me.cortex.voxelmon.importers.WorldImporter; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientCommandSource; -import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.Text; +import org.jetbrains.annotations.NotNull; -import static com.mojang.brigadier.builder.LiteralArgumentBuilder.literal; -import static com.mojang.brigadier.builder.RequiredArgumentBuilder.argument; +import java.io.File; -/* public class WorldImportCommand { - public static void register(CommandDispatcher dispatcher) { - dispatcher.register(literal("zenith") - .then(literal("import").then(literal("world").then(argument("world_name", StringArgumentType.string()).executes(WorldImportCommand::importWorld))))); + public static LiteralArgumentBuilder register() { + return ClientCommandManager.literal("zenith").then(ClientCommandManager.literal("import").then(ClientCommandManager.literal("world").then(ClientCommandManager.argument("world_name", StringArgumentType.string()).executes(WorldImportCommand::importWorld)))); } + public static WorldImporter importerInstance; - private static int importWorld(CommandContext ctx) { - VoxelCore.INSTANCE.createWorldImporter(MinecraftClient.getInstance().world, ctx.getArgument("world_name", String.class)); + private static int importWorld(CommandContext ctx) { + var instance = MinecraftClient.getInstance(); + var file = new File(ctx.getArgument("world_name", String.class)); + importerInstance = ((IGetVoxelCore)instance.worldRenderer).getVoxelCore().createWorldImporter(MinecraftClient.getInstance().player.clientWorld, file); return 0; } -} -*/ \ No newline at end of file + +} \ No newline at end of file diff --git a/src/main/resources/assets/voxelmon/shaders/lod/gl46/quads.vert b/src/main/resources/assets/voxelmon/shaders/lod/gl46/quads.vert index 6630923f..06de08c3 100644 --- a/src/main/resources/assets/voxelmon/shaders/lod/gl46/quads.vert +++ b/src/main/resources/assets/voxelmon/shaders/lod/gl46/quads.vert @@ -81,7 +81,7 @@ void main() { if (face == 0) { colour.xyz *= vec3(0.75, 0.75, 0.75); } else if (face != 1) { - colour.xyz *= vec3((float(face-2)/4)*0.25 + 0.75); + colour.xyz *= vec3((float(face-2)/4)*0.5 + 0.5); }