From 53d5d1c41f288b93a47bc3cf2dd0597887e02543 Mon Sep 17 00:00:00 2001 From: mcrcortex <18544518+MCRcortex@users.noreply.github.com> Date: Fri, 16 Feb 2024 22:32:17 +1000 Subject: [PATCH] AAA --- .../core/model/BakedBlockEntityModel.java | 144 ++++++++++++++++++ .../voxy/client/core/model/ModelManager.java | 40 ++++- .../client/core/model/ModelTextureBakery.java | 60 ++++---- .../rendering/AbstractFarWorldRenderer.java | 2 +- .../core/rendering/FrustumLoDComputation.java | 5 + .../core/rendering/Gl46FarWorldRenderer.java | 7 +- .../rendering/building/RenderDataFactory.java | 23 ++- .../core/rendering/util/BufferArena.java | 3 + .../core/rendering/util/UploadStream.java | 3 + .../voxy/common/world/other/Mapper.java | 3 +- .../assets/voxy/shaders/lod/gl46/quads.vert | 2 +- src/main/resources/voxy.accesswidener | 6 + 12 files changed, 255 insertions(+), 43 deletions(-) create mode 100644 src/main/java/me/cortex/voxy/client/core/model/BakedBlockEntityModel.java create mode 100644 src/main/java/me/cortex/voxy/client/core/rendering/FrustumLoDComputation.java diff --git a/src/main/java/me/cortex/voxy/client/core/model/BakedBlockEntityModel.java b/src/main/java/me/cortex/voxy/client/core/model/BakedBlockEntityModel.java new file mode 100644 index 00000000..e974d959 --- /dev/null +++ b/src/main/java/me/cortex/voxy/client/core/model/BakedBlockEntityModel.java @@ -0,0 +1,144 @@ +package me.cortex.voxy.client.core.model; + +import net.minecraft.block.BlockEntityProvider; +import net.minecraft.block.BlockState; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.*; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D; +import static org.lwjgl.opengl.GL11.glBindTexture; + +public class BakedBlockEntityModel { + private static final class BakedVertices implements VertexConsumer { + public final RenderLayer layer; + private float cX, cY, cZ; + private int cR, cG, cB, cA; + private float cU, cV; + + private final List vertices = new ArrayList<>(); + + private BakedVertices(RenderLayer layer) { + this.layer = layer; + } + + @Override + public VertexConsumer vertex(double x, double y, double z) { + this.cX = (float) x; + this.cY = (float) y; + this.cZ = (float) z; + return this; + } + + @Override + public VertexConsumer color(int red, int green, int blue, int alpha) { + this.cR = 0;//red; + this.cG = 0;//green; + this.cB = 0;//blue; + this.cA = alpha; + return this; + } + + @Override + public VertexConsumer texture(float u, float v) { + this.cU = u; + this.cV = v; + return this; + } + + @Override + public VertexConsumer overlay(int u, int v) { + return this; + } + + @Override + public VertexConsumer light(int u, int v) { + return this; + } + + @Override + public VertexConsumer normal(float x, float y, float z) { + return this; + } + + @Override + public void fixedColor(int red, int green, int blue, int alpha) { + + } + + @Override + public void unfixColor() { + + } + + @Override + public void next() { + this.vertices.add(new int[]{ + Float.floatToIntBits(this.cX), Float.floatToIntBits(this.cY), Float.floatToIntBits(this.cZ), + this.cR, this.cG, this.cB, this.cA, + Float.floatToIntBits(this.cU), Float.floatToIntBits(this.cV)}); + } + + public void putInto(VertexConsumer vc) { + for (var vert : this.vertices) { + vc.vertex(Float.intBitsToFloat(vert[0]), Float.intBitsToFloat(vert[1]), Float.intBitsToFloat(vert[2])) + .color(vert[3], vert[4], vert[5], vert[6]) + .texture(Float.intBitsToFloat(vert[7]), Float.intBitsToFloat(vert[8])) + .next(); + } + } + } + + private final List layers; + private BakedBlockEntityModel(List layers) { + this.layers = layers; + } + + public void renderOut() { + var vc = Tessellator.getInstance().getBuffer(); + for (var layer : this.layers) { + vc.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR_TEXTURE); + if (layer.layer instanceof RenderLayer.MultiPhase mp) { + Identifier textureId = mp.phases.texture.getId().orElse(null); + if (textureId == null) { + System.err.println("ERROR: Empty texture id for layer: " + layer); + } else { + var texture = MinecraftClient.getInstance().getTextureManager().getTexture(textureId); + glBindTexture(GL_TEXTURE_2D, texture.getGlId()); + } + } + layer.putInto(vc); + BufferRenderer.draw(vc.end()); + } + } + + public static BakedBlockEntityModel bake(BlockState state) { + Map map = new HashMap<>(); + var entity = ((BlockEntityProvider)state.getBlock()).createBlockEntity(BlockPos.ORIGIN, state); + if (entity == null) { + return null; + } + var renderer = MinecraftClient.getInstance().getBlockEntityRenderDispatcher().get(entity); + if (renderer != null) { + entity.setWorld(MinecraftClient.getInstance().world); + try { + renderer.render(entity, 0.0f, new MatrixStack(), layer->map.computeIfAbsent(layer, BakedVertices::new), 0, 0); + } catch (Exception e) { + System.err.println("Unable to bake block entity: " + entity); + e.printStackTrace(); + } + } + entity.markRemoved(); + if (map.isEmpty()) { + return null; + } + return new BakedBlockEntityModel(map.values().stream().toList()); + } +} diff --git a/src/main/java/me/cortex/voxy/client/core/model/ModelManager.java b/src/main/java/me/cortex/voxy/client/core/model/ModelManager.java index 6bf15886..e498dd3e 100644 --- a/src/main/java/me/cortex/voxy/client/core/model/ModelManager.java +++ b/src/main/java/me/cortex/voxy/client/core/model/ModelManager.java @@ -3,6 +3,9 @@ package me.cortex.voxy.client.core.model; import com.mojang.blaze3d.platform.GlConst; import com.mojang.blaze3d.platform.GlStateManager; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import it.unimi.dsi.fastutil.objects.ObjectSet; import me.cortex.voxy.client.core.IGetVoxelCore; import me.cortex.voxy.client.core.gl.GlBuffer; import me.cortex.voxy.client.core.gl.GlTexture; @@ -53,6 +56,7 @@ import static org.lwjgl.opengl.GL45C.glTextureSubImage2D; // to all other models already loaded, if it is a duplicate, create a mapping from the id to the already loaded id, this will help with meshing aswell // as leaves and such will be able to be merged public class ModelManager { + //TODO: replace the fluid BlockState with a client model id integer of the fluidState, requires looking up // the fluid state in the mipper private record ModelEntry(List textures, int fluidBlockStateId){ @@ -108,6 +112,7 @@ public class ModelManager { private final List biomes = new ArrayList<>(); private final List> modelsRequiringBiomeColours = new ArrayList<>(); + private static final ObjectSet LOGGED_SELF_CULLING_WARNING = new ObjectOpenHashSet<>(); public ModelManager(int modelTextureSize) { this.modelTextureSize = modelTextureSize; @@ -225,6 +230,31 @@ public class ModelManager { boolean needsDoubleSidedQuads = (sizes[0] < -0.1 && sizes[1] < -0.1) || (sizes[2] < -0.1 && sizes[3] < -0.1) || (sizes[4] < -0.1 && sizes[5] < -0.1); + boolean cullsSame = false; + + { + //TODO: Could also move this into the RenderDataFactory and do it on the actual blockstates instead of a guestimation + boolean allTrue = true; + boolean allFalse = true; + //Guestimation test for if the block culls itself + for (var dir : Direction.values()) { + if (blockState.isSideInvisible(blockState, dir)) { + allFalse = false; + } else { + allTrue = false; + } + } + + if (allFalse == allTrue) {//If only some sides where self culled then abort + cullsSame = false; + if (LOGGED_SELF_CULLING_WARNING.add(blockState)) System.err.println("Warning! blockstate: " + blockState + " only culled against its self some of the time"); + } + + if (allTrue) { + cullsSame = true; + } + } + //Each face gets 1 byte, with the top 2 bytes being for whatever long metadata = 0; @@ -234,6 +264,8 @@ public class ModelManager { metadata |= (!blockState.getFluidState().isEmpty())?8:0;//Has a fluid state accosiacted with it metadata |= isFluid?16:0;//Is a fluid + metadata |= cullsSame?32:0; + //TODO: add a bunch of control config options for overriding/setting options of metadata for each face of each type for (int face = 5; face != -1; face--) {//In reverse order to make indexing into the metadata long easier long faceUploadPtr = uploadPtr + 4L * face;//Each face gets 4 bytes worth of data @@ -512,6 +544,10 @@ public class ModelManager { return ((metadata>>(8*6))&1) != 0; } + //NOTE: this might need to be moved to per face + public static boolean cullsSame(long metadata) { + return ((metadata>>(8*6))&32) != 0; + } @@ -590,8 +626,8 @@ public class ModelManager { int Y = ((id>>8)&0xFF) * this.modelTextureSize*2; for (int subTex = 0; subTex < 6; subTex++) { - int x = X + (subTex%3)*this.modelTextureSize; - int y = Y + (subTex/3)*this.modelTextureSize; + int x = X + (subTex>>1)*this.modelTextureSize; + int y = Y + (subTex&1)*this.modelTextureSize; GlStateManager._pixelStore(GlConst.GL_UNPACK_ROW_LENGTH, 0); GlStateManager._pixelStore(GlConst.GL_UNPACK_SKIP_PIXELS, 0); diff --git a/src/main/java/me/cortex/voxy/client/core/model/ModelTextureBakery.java b/src/main/java/me/cortex/voxy/client/core/model/ModelTextureBakery.java index da5e4602..7bc6fe85 100644 --- a/src/main/java/me/cortex/voxy/client/core/model/ModelTextureBakery.java +++ b/src/main/java/me/cortex/voxy/client/core/model/ModelTextureBakery.java @@ -102,6 +102,7 @@ public class ModelTextureBakery { } + //TODO: For block entities, also somehow attempt to render the default block entity, e.g. chests and stuff // cause that will result in ok looking micro details in the terrain public ColourDepthTextureData[] renderFaces(BlockState state, long randomValue, boolean renderFluid) { @@ -111,6 +112,8 @@ public class ModelTextureBakery { .getBlockModels() .getModel(state); + var entityModel = state.hasBlockEntity()?BakedBlockEntityModel.bake(state):null; + int oldFB = GlStateManager.getBoundFramebuffer(); var oldProjection = new Matrix4f(RenderSystem.getProjectionMatrix()); GL11C.glViewport(0, 0, this.width, this.height); @@ -165,13 +168,12 @@ public class ModelTextureBakery { this.rasterShader.bind(); glActiveTexture(GL_TEXTURE0); int texId = MinecraftClient.getInstance().getTextureManager().getTexture(new Identifier("minecraft", "textures/atlas/blocks.png")).getGlId(); - glBindTexture(GL_TEXTURE_2D, texId); GlUniform.uniform1(0, 0); var faces = new ColourDepthTextureData[FACE_VIEWS.size()]; for (int i = 0; i < faces.length; i++) { - faces[i] = captureView(state, model, FACE_VIEWS.get(i), randomValue, i, renderFluid); - //glBlitNamedFramebuffer(this.framebuffer.id, oldFB, 0,0,16,16,300*(i%3),300*(i/3),300*(i%3)+256,300*(i/3)+256, GL_COLOR_BUFFER_BIT, GL_NEAREST); + faces[i] = captureView(state, model, entityModel, FACE_VIEWS.get(i), randomValue, i, renderFluid, texId); + //glBlitNamedFramebuffer(this.framebuffer.id, oldFB, 0,0,16,16,300*(i>>1),300*(i&1),300*(i>>1)+256,300*(i&1)+256, GL_COLOR_BUFFER_BIT, GL_NEAREST); } renderLayer.endDrawing(); @@ -188,28 +190,21 @@ public class ModelTextureBakery { return faces; } - private ColourDepthTextureData captureView(BlockState state, BakedModel model, MatrixStack stack, long randomValue, int face, boolean renderFluid) { + + private ColourDepthTextureData captureView(BlockState state, BakedModel model, BakedBlockEntityModel blockEntityModel, MatrixStack stack, long randomValue, int face, boolean renderFluid, int textureId) { var vc = Tessellator.getInstance().getBuffer(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + + float[] mat = new float[4*4]; + new Matrix4f(RenderSystem.getProjectionMatrix()).mul(stack.peek().getPositionMatrix()).get(mat); + glUniformMatrix4fv(1, false, mat); + + + if (blockEntityModel != null && !renderFluid) { + blockEntityModel.renderOut(); + } + vc.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR_TEXTURE); - - - //if (state.hasBlockEntity() && state.getBlock() == Blocks.CHEST) { - // //TODO: finish BlockEntity raster - // var entity = ((BlockEntityProvider)state.getBlock()).createBlockEntity(BlockPos.ORIGIN, state); - // var renderer = MinecraftClient.getInstance().getBlockEntityRenderDispatcher().get(entity); - // if (renderer != null) { - // entity.setWorld(MinecraftClient.getInstance().world); - // renderer.render(entity, 0.0f, new MatrixStack(), (layer) -> { - // //glBindTexture(GL_TEXTURE_2D); - // return vc; - // }, 0, 0); - // } - // entity.markRemoved(); - //} - - - if (!renderFluid) { renderQuads(vc, state, model, new MatrixStack(), randomValue); } else { @@ -240,13 +235,21 @@ public class ModelTextureBakery { return null; } - //TODO: make it so it returns air on some positions, e.g. so from UP, @Override public BlockState getBlockState(BlockPos pos) { - //TODO:FIXME: Dont hardcode if (pos.equals(Direction.byId(face).getVector())) { return Blocks.AIR.getDefaultState(); } + + //Fixme: + // This makes it so that the top face of water is always air, if this is commented out + // the up block will be a liquid state which makes the sides full + // if this is uncommented, that issue is fixed but e.g. stacking water layers ontop of eachother + // doesnt fill the side of the block + + //if (pos.getY() == 1) { + // return Blocks.AIR.getDefaultState(); + //} return state; } @@ -255,6 +258,9 @@ public class ModelTextureBakery { if (pos.equals(Direction.byId(face).getVector())) { return Blocks.AIR.getDefaultState().getFluidState(); } + //if (pos.getY() == 1) { + // return Blocks.AIR.getDefaultState().getFluidState(); + //} return state.getFluidState(); } @@ -270,11 +276,7 @@ public class ModelTextureBakery { }, vc, state, state.getFluidState()); } - - - float[] mat = new float[4*4]; - new Matrix4f(RenderSystem.getProjectionMatrix()).mul(stack.peek().getPositionMatrix()).get(mat); - glUniformMatrix4fv(1, false, mat); + glBindTexture(GL_TEXTURE_2D, textureId); BufferRenderer.draw(vc.end()); diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/AbstractFarWorldRenderer.java b/src/main/java/me/cortex/voxy/client/core/rendering/AbstractFarWorldRenderer.java index 3ebbd38f..2239afc9 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/AbstractFarWorldRenderer.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/AbstractFarWorldRenderer.java @@ -105,7 +105,7 @@ public abstract class AbstractFarWorldRenderer { UploadStream.INSTANCE.commit(); } - int maxUpdatesPerFrame = 10; + int maxUpdatesPerFrame = 40; //Do any BlockChanges while ((!this.blockStateUpdates.isEmpty()) && (maxUpdatesPerFrame-- > 0)) { diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/FrustumLoDComputation.java b/src/main/java/me/cortex/voxy/client/core/rendering/FrustumLoDComputation.java new file mode 100644 index 00000000..29558e5f --- /dev/null +++ b/src/main/java/me/cortex/voxy/client/core/rendering/FrustumLoDComputation.java @@ -0,0 +1,5 @@ +package me.cortex.voxy.client.core.rendering; + +public class FrustumLoDComputation { + +} diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/Gl46FarWorldRenderer.java b/src/main/java/me/cortex/voxy/client/core/rendering/Gl46FarWorldRenderer.java index bfd50076..5cb6855d 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/Gl46FarWorldRenderer.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/Gl46FarWorldRenderer.java @@ -8,6 +8,7 @@ import me.cortex.voxy.client.core.gl.shader.ShaderType; import me.cortex.voxy.client.core.rendering.util.UploadStream; import me.cortex.voxy.client.mixin.joml.AccessFrustumIntersection; import net.minecraft.block.Blocks; +import net.minecraft.block.FluidBlock; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.RenderLayer; import net.minecraft.client.util.math.MatrixStack; @@ -113,7 +114,8 @@ public class Gl46FarWorldRenderer extends AbstractFarWorldRenderer { glDisable(GL_BLEND); - //this.models.bakery.renderFaces(Blocks.OAK_LEAVES.getDefaultState(), 1234, false); + //this.models.bakery.renderFaces(Blocks.WATER.getDefaultState().with(FluidBlock.LEVEL, 1), 1234, true); + //this.models.bakery.renderFaces(Blocks.CHEST.getDefaultState(), 1234, false); RenderLayer.getCutoutMipped().startDrawing(); @@ -141,8 +143,9 @@ public class Gl46FarWorldRenderer extends AbstractFarWorldRenderer { this.lodShader.bind(); glDisable(GL_CULL_FACE); - glPointSize(10); + //glPointSize(10); glMultiDrawElementsIndirectCountARB(GL_TRIANGLES, GL_UNSIGNED_SHORT, 0, 0, (int) (this.geometry.getSectionCount()*4.4), 0); + //glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, 0, (int) (this.geometry.getSectionCount()*4.4), 0); glEnable(GL_CULL_FACE); glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT | GL_FRAMEBUFFER_BARRIER_BIT); diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/building/RenderDataFactory.java b/src/main/java/me/cortex/voxy/client/core/rendering/building/RenderDataFactory.java index 5c529bd5..9b38ba05 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/building/RenderDataFactory.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/building/RenderDataFactory.java @@ -245,18 +245,29 @@ public class RenderDataFactory { } if (facingFluidClientId != -1) { - if (this.world.getMapper().getBlockStateFromId(selfBlockId).getFluidState().getFluid() == this.world.getMapper().getBlockStateFromId(facingState).getFluidState().getFluid()) { - return false; + if (this.world.getMapper().getBlockStateFromBlockId(selfBlockId).getBlock() == this.world.getMapper().getBlockStateFromBlockId(Mapper.getBlockId(facingState)).getBlock()) { + return false; } } + if (ModelManager.faceOccludes(facingMetadata, opposingFace)) { return false; } - //NOTE: if the model has a fluid state but is not a liquid need to see if the solid state had a face rendered and that face is occluding, if so, dont render the fluid state face + //if the model has a fluid state but is not a liquid need to see if the solid state had a face rendered and that face is occluding, if so, dont render the fluid state face + if (ModelManager.faceOccludes(metadata, face)) { + return false; + } - //TODO:FIXME FINISH + + + + //TODO:FIXME SOMEHOW THIS IS CRITICAL!!!!!!!!!!!!!!!!!! + // so there is one more issue need to be fixed, if water is layered ontop of eachother, the side faces depend on the water state ontop + // this has been hackfixed in the model texture bakery but a proper solution that doesnt explode the sides of the water textures needs to be done + // the issue is that the fluid rendering depends on the up state aswell not just the face state which is really really painful to account for + // e.g the sides of a full water is 8 high or something, not the full block height, this results in a gap between water layers @@ -276,8 +287,8 @@ public class RenderDataFactory { return false; } - if (ModelManager.isTranslucent(metadata) && selfBlockId == Mapper.getBlockId(facingState)) { - //If we are facing a block, and are translucent and it is the same block as us, cull the quad + if (ModelManager.cullsSame(metadata) && selfBlockId == Mapper.getBlockId(facingState)) { + //If we are facing a block, and we are both the same state, dont render that face return false; } diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/util/BufferArena.java b/src/main/java/me/cortex/voxy/client/core/rendering/util/BufferArena.java index 40b3199c..a7a4043a 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/util/BufferArena.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/util/BufferArena.java @@ -28,6 +28,9 @@ public class BufferArena { } int size = (int) (buffer.size/this.elementSize); long addr = this.allocationMap.alloc(size); + if (addr == -1) { + throw new IllegalStateException("Buffer arena out of memory"); + } long uploadPtr = UploadStream.INSTANCE.upload(this.buffer, addr * this.elementSize, buffer.size); MemoryUtil.memCopy(buffer.address, uploadPtr, buffer.size); this.used += size; diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/util/UploadStream.java b/src/main/java/me/cortex/voxy/client/core/rendering/util/UploadStream.java index ed037c93..2a7f48da 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/util/UploadStream.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/util/UploadStream.java @@ -36,6 +36,9 @@ public class UploadStream { private long caddr = -1; private long offset = 0; public long upload(GlBuffer buffer, long destOffset, long size) { + if (destOffset<0) { + throw new IllegalArgumentException(); + } if (size > Integer.MAX_VALUE) { throw new IllegalArgumentException(); } diff --git a/src/main/java/me/cortex/voxy/common/world/other/Mapper.java b/src/main/java/me/cortex/voxy/common/world/other/Mapper.java index 123b2887..2fd71f65 100644 --- a/src/main/java/me/cortex/voxy/common/world/other/Mapper.java +++ b/src/main/java/me/cortex/voxy/common/world/other/Mapper.java @@ -179,8 +179,7 @@ public class Mapper { return composeMappingId(light, this.getIdForBlockState(state), this.getIdForBiome(biome)); } - public BlockState getBlockStateFromId(long id) { - int blockId = (int) ((id>>27)&((1<<20)-1)); + public BlockState getBlockStateFromBlockId(int blockId) { return this.blockId2stateEntry.get(blockId).state; } diff --git a/src/main/resources/assets/voxy/shaders/lod/gl46/quads.vert b/src/main/resources/assets/voxy/shaders/lod/gl46/quads.vert index 66e452dc..645aa55e 100644 --- a/src/main/resources/assets/voxy/shaders/lod/gl46/quads.vert +++ b/src/main/resources/assets/voxy/shaders/lod/gl46/quads.vert @@ -86,7 +86,7 @@ void main() { vec2 modelUV = vec2(modelId&0xFF, (modelId>>8)&0xFF)*(1.0/(256.0)); //TODO: make the face orientated by 2x3 so that division is not a integer div and modulo isnt needed // as these are very slow ops - baseUV = modelUV + (vec2(face%3, face/3) * (1.0/(vec2(3.0, 2.0)*256.0))); + baseUV = modelUV + (vec2(face>>1, face&1) * (1.0/(vec2(3.0, 2.0)*256.0))); //TODO: add an option to scale the quad size by the lod level so that // e.g. at lod level 2 a face will have 2x2 uv = respectiveQuadSize + faceOffset;//Add in the face offset for 0,0 uv diff --git a/src/main/resources/voxy.accesswidener b/src/main/resources/voxy.accesswidener index bd50e6e8..0b19a2a7 100644 --- a/src/main/resources/voxy.accesswidener +++ b/src/main/resources/voxy.accesswidener @@ -10,4 +10,10 @@ accessible field net/minecraft/client/render/GameRenderer zoom F accessible field net/minecraft/client/world/ClientWorld worldRenderer Lnet/minecraft/client/render/WorldRenderer; accessible field net/minecraft/world/biome/source/BiomeAccess seed J +accessible class net/minecraft/client/render/RenderLayer$MultiPhase +accessible class net/minecraft/client/render/RenderLayer$MultiPhaseParameters +accessible field net/minecraft/client/render/RenderLayer$MultiPhaseParameters texture Lnet/minecraft/client/render/RenderPhase$TextureBase; +accessible method net/minecraft/client/render/RenderPhase$TextureBase getId ()Ljava/util/Optional; +accessible field net/minecraft/client/render/RenderLayer$MultiPhase phases Lnet/minecraft/client/render/RenderLayer$MultiPhaseParameters; + accessible method net/minecraft/client/render/GameRenderer getFov (Lnet/minecraft/client/render/Camera;FZ)D \ No newline at end of file