Mostly finished Model data i think
This commit is contained in:
@@ -5,12 +5,14 @@ import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import me.cortex.zenith.client.core.gl.GlBuffer;
|
||||
import me.cortex.zenith.client.core.gl.GlTexture;
|
||||
import me.cortex.zenith.client.core.rendering.util.UploadStream;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.client.render.RenderLayers;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -155,23 +157,68 @@ public class ModelManager {
|
||||
// solid layer renders it as black so might need to add a bitset in the model data of whether the face is rendering
|
||||
// in discard or solid mode maybe?
|
||||
|
||||
long uploadPtr = UploadStream.INSTANCE.upload(this.modelBuffer, (long) modelId * MODEL_SIZE, MODEL_SIZE);
|
||||
|
||||
|
||||
//TODO: implement
|
||||
boolean hasBiomeColourResolver = false;
|
||||
|
||||
//This also checks if there is a block colour resolver for the given blockstate and marks that the block has a resolver
|
||||
var sizes = this.computeModelDepth(textureData, checkMode);
|
||||
|
||||
for (int face = 0; face < 6; face++) {
|
||||
if (sizes[face] < -0.1) {//Face is empty, so ignore
|
||||
//Each face gets 1 byte, with the top 2 bytes being for whatever
|
||||
long metadata = hasBiomeColourResolver?1:0;
|
||||
metadata |= blockRenderLayer == RenderLayer.getTranslucent()?2: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
|
||||
metadata <<= 8;
|
||||
float offset = sizes[face];
|
||||
if (offset < -0.1) {//Face is empty, so ignore
|
||||
metadata |= 0xFF;//Mark the face as non-existent
|
||||
//Set to -1 as safepoint
|
||||
MemoryUtil.memPutLong(faceUploadPtr, -1);
|
||||
continue;
|
||||
}
|
||||
//TODO: replace this with a more intelligent method that
|
||||
// if using solid use TextureUtils.computeBounds() with depth testing
|
||||
// if using translucent or transparent compare if alpha is 0
|
||||
var faceSize = TextureUtils.computeBounds(textureData[face], checkMode);
|
||||
|
||||
int eee = 0;
|
||||
boolean faceCoversFullBlock = faceSize[0] == 0 && faceSize[2] == 0 &&
|
||||
faceSize[1] == (this.modelTextureSize-1) && faceSize[3] == (this.modelTextureSize-1);
|
||||
|
||||
metadata |= faceCoversFullBlock?2:0;
|
||||
|
||||
//TODO: add alot of config options for the following
|
||||
boolean occludesFace = true;
|
||||
occludesFace &= blockRenderLayer != RenderLayer.getTranslucent();//If its translucent, it doesnt occlude
|
||||
|
||||
//TODO: make this an option, basicly if the face is really close, it occludes otherwise it doesnt
|
||||
occludesFace &= offset < 0.1;//If the face is rendered far away from the other face, then it doesnt occlude
|
||||
|
||||
if (occludesFace) {
|
||||
int writeCount = TextureUtils.getWrittenPixelCount(textureData[face], checkMode);
|
||||
occludesFace &= ((float)writeCount)/(this.modelTextureSize * this.modelTextureSize) > 0.9;// only occlude if the face covers more than 90% of the face
|
||||
}
|
||||
metadata |= occludesFace?1:0;
|
||||
|
||||
|
||||
//Scale face size from 0->this.modelTextureSize-1 to 0->15
|
||||
for (int i = 0; i < 4; i++) {
|
||||
faceSize[i] = Math.round((((float)faceSize[i])/(this.modelTextureSize-1))*15);
|
||||
}
|
||||
|
||||
int faceModelData = 0;
|
||||
faceModelData |= faceSize[0] | (faceSize[1]<<4) | (faceSize[2]<<8) | (faceSize[3]<<12);
|
||||
faceModelData |= Math.round(offset*63);//Change the scale from 0->1 (ends inclusive) float to 0->63 (6 bits) NOTE! that 63 == 1.0f meaning its shifted all the way to the other side of the model
|
||||
//Still have 11 bits free
|
||||
|
||||
MemoryUtil.memPutInt(faceUploadPtr, faceModelData);
|
||||
}
|
||||
this.metadataCache[modelId] = metadata;
|
||||
|
||||
uploadPtr += 4*6;
|
||||
//Have 40 bytes free for remaining model data
|
||||
// todo: put in like the render layer type ig? along with colour resolver info
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,25 +4,11 @@ import java.util.Map;
|
||||
|
||||
//Texturing utils to manipulate data from the model bakery
|
||||
public class TextureUtils {
|
||||
//Returns a bitset of
|
||||
public static int computeColourData(ColourDepthTextureData texture) {
|
||||
final var colour = texture.colour();
|
||||
int bitset = 0b101;
|
||||
for (int i = 0; i < colour.length && bitset != 0b010; i++) {
|
||||
int pixel = colour[i];
|
||||
int alpha = (pixel>>24)&0xFF;
|
||||
bitset |= (alpha != 0 && alpha != 255)?2:0;//Test if the pixel is translucent (has alpha)
|
||||
bitset &= (alpha != 0)?3:7;// test if the pixel is not empty (assumes that if alpha is 0 it wasnt written to!!) FIXME: THIS MIGHT NOT BE CORRECT
|
||||
bitset &= alpha != 255?6:7;// test if the pixel is anything but solid, (occlusion culling stuff)
|
||||
}
|
||||
return bitset;
|
||||
}
|
||||
|
||||
//Returns the number of non pixels not written to
|
||||
public static int getNonWrittenPixels(ColourDepthTextureData texture) {
|
||||
public static int getWrittenPixelCount(ColourDepthTextureData texture, int checkMode) {
|
||||
int count = 0;
|
||||
for (int pixel : texture.depth()) {
|
||||
count += ((pixel&0xFF) == 0)?1:0;
|
||||
for (int i = 0; i < texture.colour().length; i++) {
|
||||
count += wasPixelWritten(texture, checkMode, i)?1:0;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
@@ -140,7 +126,7 @@ public class TextureUtils {
|
||||
}
|
||||
maxX--;
|
||||
} while (maxX != -1);
|
||||
maxX++;
|
||||
//maxX++;
|
||||
|
||||
|
||||
//Compute y bounds
|
||||
@@ -168,7 +154,7 @@ public class TextureUtils {
|
||||
}
|
||||
maxY--;
|
||||
} while (maxY != -1);
|
||||
maxY++;
|
||||
//maxY++;
|
||||
|
||||
return new int[]{minX, maxX, minY, maxY};
|
||||
}
|
||||
|
||||
@@ -142,18 +142,19 @@ public class GeometryManager {
|
||||
|
||||
//TODO: pack the offsets of each axis so that implicit face culling can work
|
||||
//Note! the opaquePreDataCount and translucentPreDataCount are never writen to the meta buffer, as they are indexed in reverse relative to the base opaque and translucent geometry
|
||||
private record SectionMeta(long position, int aabb, int opaqueGeometryPtr, int opaqueQuadCount, int opaquePreDataCount, int translucentGeometryPtr, int translucentQuadCount, int translucentPreDataCount) {
|
||||
private record SectionMeta(long position, int aabb, int opaqueGeometryPtr, int count, int translucentGeometryPtr) {
|
||||
public void writeMetadata(long ptr) {
|
||||
//THIS IS DUE TO ENDIANNESS and that we are splitting a long into 2 ints
|
||||
MemoryUtil.memPutInt(ptr, (int) (this.position>>32)); ptr += 4;
|
||||
MemoryUtil.memPutInt(ptr, (int) this.position); ptr += 4;
|
||||
ptr += 8;
|
||||
MemoryUtil.memPutInt(ptr, (int) this.aabb); ptr += 4;
|
||||
ptr += 4;
|
||||
|
||||
MemoryUtil.memPutInt(ptr, (int) this.opaqueGeometryPtr + this.opaquePreDataCount); ptr += 4;
|
||||
MemoryUtil.memPutInt(ptr, this.opaqueQuadCount); ptr += 4;
|
||||
MemoryUtil.memPutInt(ptr, this.count); ptr += 4;
|
||||
//MemoryUtil.memPutInt(ptr, this.opaqueQuadCount); ptr += 4;
|
||||
|
||||
MemoryUtil.memPutInt(ptr, (int) this.translucentGeometryPtr + this.translucentPreDataCount); ptr += 4;
|
||||
MemoryUtil.memPutInt(ptr, this.translucentQuadCount); ptr += 4;
|
||||
//MemoryUtil.memPutInt(ptr, (int) this.translucentGeometryPtr + this.translucentPreDataCount); ptr += 4;
|
||||
//MemoryUtil.memPutInt(ptr, this.translucentQuadCount); ptr += 4;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +162,8 @@ public class GeometryManager {
|
||||
int geometryPtr = (int) this.geometryBuffer.upload(geometry.opaque.buffer());
|
||||
|
||||
//TODO: support translucent geometry
|
||||
return new SectionMeta(geometry.position, 0, geometryPtr, (int) (geometry.opaque.buffer().size/8), 0, -1,0, 0);
|
||||
//return new SectionMeta(geometry.position, 0, geometryPtr, (int) (geometry.opaque.buffer().size/8), 0, -1,0, 0);
|
||||
return new SectionMeta(geometry.position, 0, geometryPtr, (int) (geometry.opaque.buffer().size/8), 0);
|
||||
}
|
||||
|
||||
private void freeMeta(SectionMeta meta) {
|
||||
|
||||
@@ -78,9 +78,6 @@ public class Gl46FarWorldRenderer extends AbstractFarWorldRenderer {
|
||||
}
|
||||
|
||||
public void renderFarAwayOpaque(MatrixStack stack, double cx, double cy, double cz) {
|
||||
this.getModelManager().addEntry(this.frameId%(1<<15), Blocks.OAK_BUTTON.getDefaultState().with(WallMountedBlock.FACE, BlockFace.FLOOR).with(WallMountedBlock.FACING, Direction.SOUTH));
|
||||
//this.getModelManager().addEntry(this.frameId%(1<<15), Blocks.HEAVY_WEIGHTED_PRESSURE_PLATE.getDefaultState());
|
||||
//this.getModelManager().addEntry(this.frameId%(1<<15), Blocks.COMPARATOR.getDefaultState());
|
||||
if (this.geometry.getSectionCount() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -29,9 +29,13 @@ public class RenderDataFactory {
|
||||
public BuiltSection generateMesh(WorldSection section, int buildMask) {
|
||||
section.copyDataTo(this.sectionCache);
|
||||
|
||||
var output = new MemoryBuffer(8*1);
|
||||
//TODO:NOTE! when doing face culling of translucent blocks,
|
||||
// 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
|
||||
|
||||
return new BuiltSection(section.getKey(), new BuiltSectionGeometry(output, new short[0]), null);
|
||||
var buff = new MemoryBuffer(8*1);
|
||||
|
||||
return new BuiltSection(section.getKey(), new BuiltSectionGeometry(buff, new short[0]), null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user