Mostly finished Model data i think

This commit is contained in:
mcrcortex
2024-01-28 15:13:04 +10:00
parent 66be05369c
commit 2e5eca6f24
5 changed files with 74 additions and 38 deletions

View File

@@ -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

View File

@@ -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};
}

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -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);
}
}