AAA
This commit is contained in:
@@ -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<int[]> 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<BakedVertices> layers;
|
||||
private BakedBlockEntityModel(List<BakedVertices> 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<RenderLayer, BakedVertices> 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());
|
||||
}
|
||||
}
|
||||
@@ -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<ColourDepthTextureData> textures, int fluidBlockStateId){
|
||||
@@ -108,6 +112,7 @@ public class ModelManager {
|
||||
private final List<Biome> biomes = new ArrayList<>();
|
||||
private final List<Pair<Integer, BlockState>> modelsRequiringBiomeColours = new ArrayList<>();
|
||||
|
||||
private static final ObjectSet<BlockState> 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);
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package me.cortex.voxy.client.core.rendering;
|
||||
|
||||
public class FrustumLoDComputation {
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user