It works even more :3
This commit is contained in:
@@ -28,15 +28,17 @@ public class DistanceTracker {
|
|||||||
this.minYSection = MinecraftClient.getInstance().world.getBottomSectionCoord()/2;
|
this.minYSection = MinecraftClient.getInstance().world.getBottomSectionCoord()/2;
|
||||||
this.maxYSection = MinecraftClient.getInstance().world.getTopSectionCoord()/2;
|
this.maxYSection = MinecraftClient.getInstance().world.getTopSectionCoord()/2;
|
||||||
|
|
||||||
this.rings[0] = new TransitionRing2D(5, MinecraftClient.getInstance().options.getViewDistance().getValue()/2, (x, z)->{
|
if (false) {
|
||||||
for (int y = this.minYSection; y <= this.maxYSection; y++) {
|
this.rings[0] = new TransitionRing2D(5, MinecraftClient.getInstance().options.getViewDistance().getValue() / 2, (x, z) -> {
|
||||||
this.tracker.remLvl0(x, y, z);
|
for (int y = this.minYSection; y <= this.maxYSection; y++) {
|
||||||
}
|
this.tracker.remLvl0(x, y, z);
|
||||||
}, (x, z) -> {
|
}
|
||||||
for (int y = this.minYSection; y <= this.maxYSection; y++) {
|
}, (x, z) -> {
|
||||||
this.tracker.addLvl0(x, y, z);
|
for (int y = this.minYSection; y <= this.maxYSection; y++) {
|
||||||
}
|
this.tracker.addLvl0(x, y, z);
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
//The rings 0+ start at 64 vanilla rd, no matter what the game is set at, that is if the game is set to 32 rd
|
//The rings 0+ start at 64 vanilla rd, no matter what the game is set at, that is if the game is set to 32 rd
|
||||||
// there will still be 32 chunks untill the first lod drop
|
// there will still be 32 chunks untill the first lod drop
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public class VoxelCore {
|
|||||||
System.out.println("World engine");
|
System.out.println("World engine");
|
||||||
|
|
||||||
this.renderTracker = new RenderTracker(this.world, this.renderer);
|
this.renderTracker = new RenderTracker(this.world, this.renderer);
|
||||||
this.renderGen = new RenderGenerationService(this.world,ZenithConfig.CONFIG.renderThreads, this.renderTracker::processBuildResult);
|
this.renderGen = new RenderGenerationService(this.world, this.renderer.getModelManager(), ZenithConfig.CONFIG.renderThreads, this.renderTracker::processBuildResult);
|
||||||
this.world.setDirtyCallback(this.renderTracker::sectionUpdated);
|
this.world.setDirtyCallback(this.renderTracker::sectionUpdated);
|
||||||
this.renderTracker.setRenderGen(this.renderGen);
|
this.renderTracker.setRenderGen(this.renderGen);
|
||||||
System.out.println("Render tracker and generator initialized");
|
System.out.println("Render tracker and generator initialized");
|
||||||
@@ -97,14 +97,10 @@ public class VoxelCore {
|
|||||||
boolean firstTime = true;
|
boolean firstTime = true;
|
||||||
public void renderSetup(Frustum frustum, Camera camera) {
|
public void renderSetup(Frustum frustum, Camera camera) {
|
||||||
if (this.firstTime) {
|
if (this.firstTime) {
|
||||||
//this.distanceTracker.init(camera.getBlockPos().getX(), camera.getBlockPos().getZ());
|
this.distanceTracker.init(camera.getBlockPos().getX(), camera.getBlockPos().getZ());
|
||||||
this.firstTime = false;
|
this.firstTime = false;
|
||||||
|
|
||||||
this.renderTracker.addLvl0(0,6,0);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
//this.distanceTracker.setCenter(camera.getBlockPos().getX(), camera.getBlockPos().getY(), camera.getBlockPos().getZ());
|
this.distanceTracker.setCenter(camera.getBlockPos().getX(), camera.getBlockPos().getY(), camera.getBlockPos().getZ());
|
||||||
this.renderer.setupRender(frustum, camera);
|
this.renderer.setupRender(frustum, camera);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -212,6 +212,15 @@ public class ModelManager {
|
|||||||
metadata |= occludesFace?1:0;
|
metadata |= occludesFace?1:0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
boolean canBeOccluded = true;
|
||||||
|
//TODO: make this an option on how far/close
|
||||||
|
canBeOccluded &= offset < 0.3;//If the face is rendered far away from the other face, then it cant be occluded
|
||||||
|
|
||||||
|
metadata |= canBeOccluded?4:0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Scale face size from 0->this.modelTextureSize-1 to 0->15
|
//Scale face size from 0->this.modelTextureSize-1 to 0->15
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
faceSize[i] = Math.round((((float)faceSize[i])/(this.modelTextureSize-1))*15);
|
faceSize[i] = Math.round((((float)faceSize[i])/(this.modelTextureSize-1))*15);
|
||||||
@@ -236,6 +245,28 @@ public class ModelManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean faceExists(long metadata, int face) {
|
||||||
|
return ((metadata>>(8*face))&0xFF)!=0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean faceCanBeOccluded(long metadata, int face) {
|
||||||
|
return ((metadata>>(8*face))&0b100)==0b100;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean faceOccludes(long metadata, int face) {
|
||||||
|
return faceExists(metadata, face) && ((metadata>>(8*face))&0b1)==0b1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isColoured(long metadata) {
|
||||||
|
//TODO: THIS
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isTranslucent(long metadata) {
|
||||||
|
//TODO: THIS
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package me.cortex.zenith.client.core.rendering.building;
|
package me.cortex.zenith.client.core.rendering.building;
|
||||||
|
|
||||||
|
|
||||||
|
import me.cortex.zenith.client.core.model.ModelManager;
|
||||||
|
import me.cortex.zenith.client.core.rendering.GeometryManager;
|
||||||
import me.cortex.zenith.client.core.util.Mesher2D;
|
import me.cortex.zenith.client.core.util.Mesher2D;
|
||||||
import me.cortex.zenith.common.world.other.Mapper;
|
import me.cortex.zenith.common.world.other.Mapper;
|
||||||
import net.minecraft.client.color.block.BlockColors;
|
import net.minecraft.client.color.block.BlockColors;
|
||||||
|
|||||||
@@ -1,19 +1,27 @@
|
|||||||
package me.cortex.zenith.client.core.rendering.building;
|
package me.cortex.zenith.client.core.rendering.building;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||||
|
import me.cortex.zenith.client.core.model.ModelManager;
|
||||||
|
import me.cortex.zenith.client.core.util.Mesher2D;
|
||||||
import me.cortex.zenith.common.util.MemoryBuffer;
|
import me.cortex.zenith.common.util.MemoryBuffer;
|
||||||
import me.cortex.zenith.common.world.WorldEngine;
|
import me.cortex.zenith.common.world.WorldEngine;
|
||||||
import me.cortex.zenith.common.world.WorldSection;
|
import me.cortex.zenith.common.world.WorldSection;
|
||||||
|
import me.cortex.zenith.common.world.other.Mapper;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
public class RenderDataFactory {
|
public class RenderDataFactory {
|
||||||
private final WorldEngine world;
|
private final WorldEngine world;
|
||||||
|
private final ModelManager modelMan;
|
||||||
private final QuadEncoder encoder;
|
private final QuadEncoder encoder;
|
||||||
private final long[] sectionCache = new long[32*32*32];
|
private final long[] sectionCache = new long[32*32*32];
|
||||||
private final long[] connectedSectionCache = new long[32*32*32];
|
private final long[] connectedSectionCache = new long[32*32*32];
|
||||||
public RenderDataFactory(WorldEngine world) {
|
public RenderDataFactory(WorldEngine world, ModelManager modelManager) {
|
||||||
this.world = world;
|
this.world = world;
|
||||||
|
this.modelMan = modelManager;
|
||||||
this.encoder = new QuadEncoder(world.getMapper(), MinecraftClient.getInstance().getBlockColors(), MinecraftClient.getInstance().world);
|
this.encoder = new QuadEncoder(world.getMapper(), MinecraftClient.getInstance().getBlockColors(), MinecraftClient.getInstance().world);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,15 +41,83 @@ public class RenderDataFactory {
|
|||||||
// if the connecting type of the translucent block is the same AND the face is full, discard it
|
// if the connecting type of the translucent block is the same AND the face is full, discard it
|
||||||
// this stops e.g. multiple layers of glass (and ocean) from having 3000 layers of quads etc
|
// this stops e.g. multiple layers of glass (and ocean) from having 3000 layers of quads etc
|
||||||
|
|
||||||
var buff = new MemoryBuffer(8*8);
|
|
||||||
MemoryUtil.memPutLong(buff.address, encodeRaw(2, 0,0,0,0,0,515,0, 0));//92
|
Mesher2D mesher = new Mesher2D(5,15);
|
||||||
MemoryUtil.memPutLong(buff.address+8, encodeRaw(3, 0,0,0,0,0,515,0, 0));//92
|
|
||||||
MemoryUtil.memPutLong(buff.address+16, encodeRaw(4, 0,2,0,0,0,515,0, 0));//92
|
LongArrayList outData = new LongArrayList(1000);
|
||||||
MemoryUtil.memPutLong(buff.address+24, encodeRaw(5, 0,2,0,0,0,515,0, 0));//92
|
|
||||||
MemoryUtil.memPutLong(buff.address+32, encodeRaw(2, 0,0,0,0,1,515,0, 0));//92
|
//Up direction
|
||||||
MemoryUtil.memPutLong(buff.address+40, encodeRaw(3, 0,0,0,0,1,515,0, 0));//92
|
|
||||||
MemoryUtil.memPutLong(buff.address+48, encodeRaw(2, 0,0,0,0,2,515,0, 0));//92
|
for (int y = 0; y < 32; y++) {
|
||||||
MemoryUtil.memPutLong(buff.address+56, encodeRaw(3, 0,0,0,0,2,515,0, 0));//92
|
mesher.reset();
|
||||||
|
for (int x = 0; x < 32; x++) {
|
||||||
|
for (int z = 0; z < 32; z++) {
|
||||||
|
long self = this.sectionCache[WorldSection.getIndex(x, y, z)];
|
||||||
|
if (Mapper.isAir(self)) continue;
|
||||||
|
|
||||||
|
int selfBlockId = Mapper.getBlockId(self);
|
||||||
|
long metadata = this.modelMan.getModelMetadata(selfBlockId);
|
||||||
|
|
||||||
|
//If the model doesnt have a face, then just skip it
|
||||||
|
if (!ModelManager.faceExists(metadata, 1)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
long facingState = Mapper.AIR;
|
||||||
|
//Need to access the other connecting section
|
||||||
|
if (y == 31) {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
facingState = this.sectionCache[WorldSection.getIndex(x, y+1, z)];
|
||||||
|
}
|
||||||
|
|
||||||
|
long facingMetadata = this.modelMan.getModelMetadata(Mapper.getBlockId(facingState));
|
||||||
|
|
||||||
|
//If face can be occluded and is occluded from the facing block, then dont render the face
|
||||||
|
if (ModelManager.faceCanBeOccluded(metadata, 1) && ModelManager.faceOccludes(facingMetadata, 0)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int clientModelId = this.modelMan.getModelId(selfBlockId);
|
||||||
|
|
||||||
|
mesher.put(x, z, ((long)clientModelId) | (((long) Mapper.getLightId(facingState))<<16) | (((long) Mapper.getBiomeId(self))<<24));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: encode translucents and double sided quads to different global buffers
|
||||||
|
int count = mesher.process();
|
||||||
|
var array = mesher.getArray();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
int quad = array[i];
|
||||||
|
long data = mesher.getDataFromQuad(quad);
|
||||||
|
outData.add(Integer.toUnsignedLong(QuadEncoder.encodePosition(1, y, quad)) | ((data&0xFFFF)<<26) | (((data>>16)&0xFF)<<55) | (((data>>24)&0x1FF)<<46));
|
||||||
|
//outData.add(Integer.toUnsignedLong(QuadEncoder.encodePosition(1, y, quad)) | (1<<26));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//var buff = new MemoryBuffer(8*8);
|
||||||
|
//MemoryUtil.memPutLong(buff.address, encodeRaw(2, 0,1,0,0,0,159,0, 0));//92 515
|
||||||
|
//MemoryUtil.memPutLong(buff.address+8, encodeRaw(3, 0,1,0,0,0,159,0, 0));//92 515
|
||||||
|
//MemoryUtil.memPutLong(buff.address+16, encodeRaw(4, 1,2,0,0,0,159,0, 0));//92 515
|
||||||
|
//MemoryUtil.memPutLong(buff.address+24, encodeRaw(5, 1,2,0,0,0,159,0, 0));//92 515
|
||||||
|
//MemoryUtil.memPutLong(buff.address+32, encodeRaw(2, 0,1,0,0,1,159,0, 0));//92 515
|
||||||
|
//MemoryUtil.memPutLong(buff.address+40, encodeRaw(3, 0,1,0,0,1,159,0, 0));//92 515
|
||||||
|
//MemoryUtil.memPutLong(buff.address+48, encodeRaw(2, 0,1,0,0,2,159,0, 0));//92 515
|
||||||
|
//MemoryUtil.memPutLong(buff.address+56, encodeRaw(3, 0,1,0,0,2,159,0, 0));//92 515
|
||||||
|
if (outData.isEmpty()) {
|
||||||
|
return new BuiltSection(section.getKey(), null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
//outData.add(encodeRaw(3, 0,1,0,0,0,159,0, 0));
|
||||||
|
var buff = new MemoryBuffer(outData.size()*8L);
|
||||||
|
long ptr = buff.address;
|
||||||
|
for (long data : outData) {
|
||||||
|
MemoryUtil.memPutLong(ptr, data); ptr+=8;
|
||||||
|
}
|
||||||
|
|
||||||
return new BuiltSection(section.getKey(), new BuiltSectionGeometry(buff, new short[0]), null);
|
return new BuiltSection(section.getKey(), new BuiltSectionGeometry(buff, new short[0]), null);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import org.lwjgl.system.MemoryUtil;
|
|||||||
|
|
||||||
|
|
||||||
public class RenderDataFactoryOld {
|
public class RenderDataFactoryOld {
|
||||||
|
/*
|
||||||
private final Mesher2D mesher = new Mesher2D(5,15);//15
|
private final Mesher2D mesher = new Mesher2D(5,15);//15
|
||||||
private final LongArrayList outData = new LongArrayList(1000);
|
private final LongArrayList outData = new LongArrayList(1000);
|
||||||
private final WorldEngine world;
|
private final WorldEngine world;
|
||||||
@@ -331,5 +332,6 @@ public class RenderDataFactoryOld {
|
|||||||
this.outData.clear();
|
this.outData.clear();
|
||||||
//return new BuiltSectionGeometry(section.getKey(), output, null);
|
//return new BuiltSectionGeometry(section.getKey(), output, null);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package me.cortex.zenith.client.core.rendering.building;
|
package me.cortex.zenith.client.core.rendering.building;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
||||||
|
import me.cortex.zenith.client.core.model.ModelManager;
|
||||||
import me.cortex.zenith.common.world.WorldEngine;
|
import me.cortex.zenith.common.world.WorldEngine;
|
||||||
import me.cortex.zenith.common.world.WorldSection;
|
import me.cortex.zenith.common.world.WorldSection;
|
||||||
|
|
||||||
@@ -22,10 +23,12 @@ public class RenderGenerationService {
|
|||||||
|
|
||||||
private final Semaphore taskCounter = new Semaphore(0);
|
private final Semaphore taskCounter = new Semaphore(0);
|
||||||
private final WorldEngine world;
|
private final WorldEngine world;
|
||||||
|
private final ModelManager modelManager;
|
||||||
private final Consumer<BuiltSection> resultConsumer;
|
private final Consumer<BuiltSection> resultConsumer;
|
||||||
|
|
||||||
public RenderGenerationService(WorldEngine world, int workers, Consumer<BuiltSection> consumer) {
|
public RenderGenerationService(WorldEngine world, ModelManager modelManager, int workers, Consumer<BuiltSection> consumer) {
|
||||||
this.world = world;
|
this.world = world;
|
||||||
|
this.modelManager = modelManager;
|
||||||
this.resultConsumer = consumer;
|
this.resultConsumer = consumer;
|
||||||
this.workers = new Thread[workers];
|
this.workers = new Thread[workers];
|
||||||
for (int i = 0; i < workers; i++) {
|
for (int i = 0; i < workers; i++) {
|
||||||
@@ -41,7 +44,7 @@ public class RenderGenerationService {
|
|||||||
//TODO: add a generated render data cache
|
//TODO: add a generated render data cache
|
||||||
private void renderWorker() {
|
private void renderWorker() {
|
||||||
//Thread local instance of the factory
|
//Thread local instance of the factory
|
||||||
var factory = new RenderDataFactory(this.world);
|
var factory = new RenderDataFactory(this.world, this.modelManager);
|
||||||
while (this.running) {
|
while (this.running) {
|
||||||
this.taskCounter.acquireUninterruptibly();
|
this.taskCounter.acquireUninterruptibly();
|
||||||
if (!this.running) break;
|
if (!this.running) break;
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package me.cortex.zenith.client.mixin.sodium;
|
||||||
|
|
||||||
|
import me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer;
|
||||||
|
import me.jellysquid.mods.sodium.client.render.chunk.occlusion.OcclusionCuller;
|
||||||
|
import net.minecraft.client.render.RenderLayer;
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
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(value = SodiumWorldRenderer.class, remap = false)
|
||||||
|
public class MixinSodiumWorldRender {
|
||||||
|
@Inject(method = "drawChunkLayer", at = @At("HEAD"), cancellable = true)
|
||||||
|
private void cancelRender(RenderLayer renderLayer, MatrixStack matrixStack, double x, double y, double z, CallbackInfo ci) {
|
||||||
|
ci.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -51,18 +51,20 @@ public class Mapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static boolean isTranslucent(long id) {
|
|
||||||
//Atm hardcode to air
|
|
||||||
return ((id>>27)&((1<<20)-1)) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isAir(long id) {
|
public static boolean isAir(long id) {
|
||||||
return ((id>>27)&((1<<20)-1)) == 0;
|
return ((id>>27)&((1<<20)-1)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean shouldRenderFace(int dirId, long self, long other) {
|
public static int getBlockId(long id) {
|
||||||
//TODO: fixme make it be with respect to the type itself e.g. water, glass etc
|
return (int) ((id>>27)&((1<<20)-1));
|
||||||
return isTranslucent(other);
|
}
|
||||||
|
|
||||||
|
public static int getBiomeId(long id) {
|
||||||
|
return (int) ((id>>47)&0x1FF);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getLightId(long id) {
|
||||||
|
return (int) ((id>>56)&0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCallbacks(Consumer<StateEntry> stateCallback, Consumer<BiomeEntry> biomeCallback) {
|
public void setCallbacks(Consumer<StateEntry> stateCallback, Consumer<BiomeEntry> biomeCallback) {
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ struct SectionMeta {
|
|||||||
uint _padA;
|
uint _padA;
|
||||||
uint ptr;
|
uint ptr;
|
||||||
uint cnt;
|
uint cnt;
|
||||||
|
uint _padB;
|
||||||
|
uint _padC;
|
||||||
};
|
};
|
||||||
|
|
||||||
//TODO: see if making the stride 2*4*4 bytes or something cause you get that 16 byte write
|
//TODO: see if making the stride 2*4*4 bytes or something cause you get that 16 byte write
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
},
|
},
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"sodium.MixinOcclusionCuller"
|
"sodium.MixinOcclusionCuller",
|
||||||
|
"sodium.MixinSodiumWorldRender"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user