diff --git a/src/main/java/me/cortex/voxy/client/core/model/ModelFactory.java b/src/main/java/me/cortex/voxy/client/core/model/ModelFactory.java index ac6d194d..162348b0 100644 --- a/src/main/java/me/cortex/voxy/client/core/model/ModelFactory.java +++ b/src/main/java/me/cortex/voxy/client/core/model/ModelFactory.java @@ -23,13 +23,14 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.ColorResolver; import net.minecraft.world.level.LightLayer; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biomes; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.LeavesBlock; import net.minecraft.world.level.block.LiquidBlock; import net.minecraft.world.level.block.entity.BlockEntity; @@ -65,9 +66,9 @@ public class ModelFactory { //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(ColourDepthTextureData down, ColourDepthTextureData up, ColourDepthTextureData north, ColourDepthTextureData south, ColourDepthTextureData west, ColourDepthTextureData east, int fluidBlockStateId) { - public ModelEntry(ColourDepthTextureData[] textures, int fluidBlockStateId) { - this(textures[0], textures[1], textures[2], textures[3], textures[4], textures[5], fluidBlockStateId); + private record ModelEntry(ColourDepthTextureData down, ColourDepthTextureData up, ColourDepthTextureData north, ColourDepthTextureData south, ColourDepthTextureData west, ColourDepthTextureData east, int fluidBlockStateId, int tintingColour) { + public ModelEntry(ColourDepthTextureData[] textures, int fluidBlockStateId, int tintingColour) { + this(textures[0], textures[1], textures[2], textures[3], textures[4], textures[5], fluidBlockStateId, tintingColour); } } @@ -151,7 +152,19 @@ public class ModelFactory { this.customBlockStateIdMapping = mapping; } - private record RawBakeResult(int blockId, BlockState blockState, MemoryBuffer rawData) { + private static final class RawBakeResult { + private final int blockId; + private final BlockState blockState; + private final MemoryBuffer rawData; + + public boolean isShaded; + + public RawBakeResult(int blockId, BlockState blockState, MemoryBuffer rawData) { + this.blockId = blockId; + this.blockState = blockState; + this.rawData = rawData; + } + public RawBakeResult(int blockId, BlockState blockState) { this(blockId, blockState, new MemoryBuffer(MODEL_TEXTURE_SIZE*MODEL_TEXTURE_SIZE*2*4*6)); } @@ -206,7 +219,7 @@ public class ModelFactory { RawBakeResult result = new RawBakeResult(blockId, blockState); int allocation = this.downstream.download(MODEL_TEXTURE_SIZE*MODEL_TEXTURE_SIZE*2*4*6, ptr -> this.rawBakeResults.add(result.cpyBuf(ptr))); - this.bakery.renderToStream(blockState, this.downstream.getBufferId(), allocation); + result.isShaded = this.bakery.renderToStream(blockState, this.downstream.getBufferId(), allocation); return true; } @@ -232,7 +245,7 @@ public class ModelFactory { } } result.rawData.free(); - var bakeResult = this.processTextureBakeResult(result.blockId, result.blockState, textureData); + var bakeResult = this.processTextureBakeResult(result.blockId, result.blockState, textureData, result.isShaded); if (bakeResult!=null) { this.uploadResults.add(bakeResult); } @@ -248,7 +261,7 @@ public class ModelFactory { var biomeEntry = this.biomeQueue.poll(); while (biomeEntry != null) { var biomeRegistry = Minecraft.getInstance().level.registryAccess().lookupOrThrow(Registries.BIOME); - var res = this.addBiome0(biomeEntry.id, biomeRegistry.getValue(ResourceLocation.parse(biomeEntry.biome))); + var res = this.addBiome0(biomeEntry.id, biomeRegistry.getValue(Identifier.parse(biomeEntry.biome))); if (res != null) { this.uploadResults.add(res); } @@ -324,7 +337,7 @@ public class ModelFactory { } } - private ModelBakeResultUpload processTextureBakeResult(int blockId, BlockState blockState, ColourDepthTextureData[] textureData) { + private ModelBakeResultUpload processTextureBakeResult(int blockId, BlockState blockState, ColourDepthTextureData[] textureData, boolean isShaded) { if (this.idMappings[blockId] != -1) { //This should be impossible to reach as it means that multiple bakes for the same blockId happened and where inflight at the same time! throw new IllegalStateException("Block id already added: " + blockId + " for state: " + blockState); @@ -357,8 +370,16 @@ public class ModelFactory { } } + var colourProvider = getColourProvider(blockState.getBlock()); + + boolean isBiomeColourDependent = false; + if (colourProvider != null) { + isBiomeColourDependent = isBiomeDependentColour(colourProvider, blockState); + } + + ModelEntry entry; {//Deduplicate same entries - var entry = new ModelEntry(textureData, clientFluidStateId); + entry = new ModelEntry(textureData, clientFluidStateId, isBiomeColourDependent||colourProvider==null?-1:captureColourConstant(colourProvider, blockState, DEFAULT_BIOME)|0xFF000000); int possibleDuplicate = this.modelTexture2id.getInt(entry); if (possibleDuplicate != -1) {//Duplicate found this.idMappings[blockId] = possibleDuplicate; @@ -400,7 +421,6 @@ public class ModelFactory { int checkMode = blockRenderLayer==ChunkSectionLayer.SOLID?TextureUtils.WRITE_CHECK_STENCIL:TextureUtils.WRITE_CHECK_ALPHA; - var colourProvider = getColourProvider(blockState.getBlock()); ModelBakeResultUpload uploadResult = new ModelBakeResultUpload(); @@ -409,10 +429,7 @@ public class ModelFactory { //TODO: implement; // TODO: if it has a constant colour instead... idk why (apparently for things like spruce leaves)?? but premultiply the texture data by the constant colour - boolean isBiomeColourDependent = false; - if (colourProvider != null) { - isBiomeColourDependent = isBiomeDependentColour(colourProvider, blockState); - } + //If it contains fluid but isnt a fluid if ((!isFluid) && (!blockState.getFluidState().isEmpty()) && clientFluidStateId != -1) { @@ -535,7 +552,7 @@ public class ModelFactory { //Change the scale from 0->1 (ends inclusive) // this is cursed also warning stuff at 63 (i.e half a pixel from the end will be clamped to the end) int enc = Math.round(offset*64); - faceModelData |= Math.min(enc,63)<<16; + faceModelData |= Math.min(enc,62)<<16; //Still have 11 bits free //Stuff like fences are solid, however they have extra side piece that mean it needs to have discard on @@ -575,7 +592,10 @@ public class ModelFactory { modelFlags |= colourProvider != null?1:0; modelFlags |= isBiomeColourDependent?2:0;//Basicly whether to use the next int as a colour or as a base index/id into a colour buffer for biome dependent colours modelFlags |= blockRenderLayer == ChunkSectionLayer.TRANSLUCENT?4:0;//Is translucent - modelFlags |= blockRenderLayer == ChunkSectionLayer.CUTOUT?0:8;//Dont use mipmaps (AND ALSO FKING SPECIFIES IF IT HAS AO, WHY??? GREAT QUESTION, TODO FIXE THIS) + + + //TODO: THIS + modelFlags |= isShaded?8:0;//model has AO and shade //modelFlags |= blockRenderLayer == RenderLayer.getSolid()?0:1;// should discard alpha MemoryUtil.memPutInt(uploadPtr, modelFlags); uploadPtr += 4; @@ -585,7 +605,7 @@ public class ModelFactory { if (colourProvider == null) { MemoryUtil.memPutInt(uploadPtr, -1);//Set the default to nothing so that its faster on the gpu } else if (!isBiomeColourDependent) { - MemoryUtil.memPutInt(uploadPtr, captureColourConstant(colourProvider, blockState, DEFAULT_BIOME)|0xFF000000); + MemoryUtil.memPutInt(uploadPtr, entry.tintingColour); } else if (!this.biomes.isEmpty()) { //Populate the list of biomes for the model state int biomeIndex = this.modelsRequiringBiomeColours.size() * this.biomes.size(); diff --git a/src/main/java/me/cortex/voxy/client/core/model/bakery/ReuseVertexConsumer.java b/src/main/java/me/cortex/voxy/client/core/model/bakery/ReuseVertexConsumer.java index 469aea39..c0a18e72 100644 --- a/src/main/java/me/cortex/voxy/client/core/model/bakery/ReuseVertexConsumer.java +++ b/src/main/java/me/cortex/voxy/client/core/model/bakery/ReuseVertexConsumer.java @@ -2,6 +2,7 @@ package me.cortex.voxy.client.core.model.bakery; import me.cortex.voxy.common.util.MemoryBuffer; +import net.minecraft.client.model.geom.builders.UVPair; import net.minecraft.client.renderer.block.model.BakedQuad; import org.lwjgl.system.MemoryUtil; @@ -15,6 +16,8 @@ public final class ReuseVertexConsumer implements VertexConsumer { private int count; private int defaultMeta; + public boolean anyShaded; + public ReuseVertexConsumer() { this.reset(); } @@ -45,6 +48,11 @@ public final class ReuseVertexConsumer implements VertexConsumer { return this; } + @Override + public VertexConsumer setColor(int i) { + return this; + } + @Override public ReuseVertexConsumer setUv(float u, float v) { MemoryUtil.memPutFloat(this.ptr + 16, u); @@ -67,17 +75,19 @@ public final class ReuseVertexConsumer implements VertexConsumer { return this; } + @Override + public VertexConsumer setLineWidth(float f) { + return null; + } + public ReuseVertexConsumer quad(BakedQuad quad, int metadata) { + this.anyShaded |= quad.shade(); this.ensureCanPut(); - int[] data = quad.vertices(); for (int i = 0; i < 4; i++) { - float x = Float.intBitsToFloat(data[i * 8]); - float y = Float.intBitsToFloat(data[i * 8 + 1]); - float z = Float.intBitsToFloat(data[i * 8 + 2]); - this.addVertex(x,y,z); - float u = Float.intBitsToFloat(data[i * 8 + 4]); - float v = Float.intBitsToFloat(data[i * 8 + 5]); - this.setUv(u,v); + var pos = quad.position(i); + this.addVertex(pos.x(), pos.y(), pos.z()); + long puv = quad.packedUV(i); + this.setUv(UVPair.unpackU(puv),UVPair.unpackV(puv)); this.meta(metadata); } @@ -98,6 +108,7 @@ public final class ReuseVertexConsumer implements VertexConsumer { } public ReuseVertexConsumer reset() { + this.anyShaded = false; this.defaultMeta = 0;//RESET THE DEFAULT META this.count = 0; this.ptr = this.buffer.address - VERTEX_FORMAT_SIZE;//the thing is first time this gets incremented by FORMAT_STRIDE 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 c1d3b243..d933fbe3 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 @@ -191,8 +191,9 @@ public class RenderDataFactory { boolean a = ModelQueries.isTranslucent(metadata); boolean b = ModelQueries.isDoubleSided(metadata); //Pre shift by 1 - type = a|b?0:4; - type |= b?2:0; + //type = a|b?0:4; + //type |= b&!a?2:0; + type = a?0:(b?2:4); } return type; } diff --git a/src/main/resources/assets/voxy/shaders/lod/block_model.glsl b/src/main/resources/assets/voxy/shaders/lod/block_model.glsl index 5c859252..4ba94317 100644 --- a/src/main/resources/assets/voxy/shaders/lod/block_model.glsl +++ b/src/main/resources/assets/voxy/shaders/lod/block_model.glsl @@ -39,6 +39,6 @@ bool modelIsTranslucent(BlockModel model) { return ((model.flagsA)&4u) != 0; } -bool modelHasMipmaps(BlockModel model) { +bool modelIsShaded(BlockModel model) { return ((model.flagsA)&8u) != 0; } \ No newline at end of file diff --git a/src/main/resources/assets/voxy/shaders/lod/gl46/bindings.glsl b/src/main/resources/assets/voxy/shaders/lod/gl46/bindings.glsl index ffbf29fa..fff2af66 100644 --- a/src/main/resources/assets/voxy/shaders/lod/gl46/bindings.glsl +++ b/src/main/resources/assets/voxy/shaders/lod/gl46/bindings.glsl @@ -98,7 +98,7 @@ layout(binding = LIGHTING_SAMPLER_BINDING) uniform sampler2D lightSampler; vec4 getLighting(uint index) { int i2 = int(index); - return texture(lightSampler, clamp((vec2((i2>>4)&0xF, i2&0xF))/16, vec2(8.0f/256), vec2(248.0f/256))); + return texture(lightSampler, clamp((vec2((i2>>4)&0xF, i2&0xF))/15, vec2(8.0f/256), vec2(248.0f/256))); } #endif diff --git a/src/main/resources/assets/voxy/shaders/lod/gl46/quads.frag b/src/main/resources/assets/voxy/shaders/lod/gl46/quads.frag index 7e26cccd..b075fc26 100644 --- a/src/main/resources/assets/voxy/shaders/lod/gl46/quads.frag +++ b/src/main/resources/assets/voxy/shaders/lod/gl46/quads.frag @@ -43,15 +43,15 @@ vec4 uint2vec4RGBA(uint colour) { return vec4((uvec4(colour)>>uvec4(24,16,8,0))&uvec4(0xFF))/255.0; } -bool useMipmaps() { - return (interData.x&2u)==0u; -} +//bool useMipmaps() { +// return (interData.x&2u)==0u; +//} uint tintingState() { return (interData.x>>2)&3u; } -bool useCutout() { +bool useDiscard() { return (interData.x&1u)==1u; } @@ -129,14 +129,16 @@ void main() { vec2 uv2 = modf(uv, tile)*(1.0/(vec2(3.0,2.0)*256.0)); vec4 colour; vec2 texPos = uv2 + getBaseUV(); - if (useMipmaps()) { +//This is deprecated, TODO: remove the non mip code path + //if (useMipmaps()) + { vec2 uvSmol = uv*(1.0/(vec2(3.0,2.0)*256.0)); vec2 dx = dFdx(uvSmol);//vec2(lDx, dDx); vec2 dy = dFdy(uvSmol);//vec2(lDy, dDy); colour = textureGrad(blockModelAtlas, texPos, dx, dy); - } else { - colour = textureLod(blockModelAtlas, texPos, 0); - } + }// else { + // colour = textureLod(blockModelAtlas, texPos, 0); + //} //If we are in shaders and are a helper invocation, just exit, as it enables extra performance gains for small sized // fragments, we do this here after derivative computation @@ -162,7 +164,11 @@ void main() { //Also, small quad is really fking over the mipping level somehow - if (useCutout() && (textureLod(blockModelAtlas, texPos, 0).a <= 0.1f)) { + #ifndef TRANSLUCENT + if (useDiscard() && (textureLod(blockModelAtlas, texPos, 0).a <= 0.1f)) { + #else + if (textureLod(blockModelAtlas, texPos, 0).a == 0.0f) { + #endif //This is stupidly stupidly bad for divergence //TODO: FIXME, basicly what this do is sample the exact pixel (no lod) for discarding, this stops mipmapping fucking it over #ifndef DEBUG_RENDER diff --git a/src/main/resources/assets/voxy/shaders/lod/quad_util.glsl b/src/main/resources/assets/voxy/shaders/lod/quad_util.glsl index e59f98cc..a77e98e0 100644 --- a/src/main/resources/assets/voxy/shaders/lod/quad_util.glsl +++ b/src/main/resources/assets/voxy/shaders/lod/quad_util.glsl @@ -58,7 +58,8 @@ uint makeQuadFlags(uint faceData, uint modelId, ivec2 quadSize, const in BlockMo flags |= uint(any(greaterThan(quadSize, ivec2(1)))) & faceHasAlphaCuttoutOverride(faceData); } - flags |= uint(!modelHasMipmaps(model))<<1;//Not mipmaps + //TODO: remove, there is no non mip code path anymore + //flags |= uint(!modelHasMipmaps(model))<<1;//Not mipmaps flags |= faceTintState(faceData)<<2; flags |= face<<4;//Face @@ -71,6 +72,11 @@ uint packVec4(vec4 vec) { return vec_.x|vec_.y|vec_.z|vec_.w; } + +#ifndef PATCHED_SHADER +float computeDirectionalFaceTint(bool isShaded, uint face); +#endif + uvec3 makeRemainingAttributes(const in BlockModel model, const in Quad quad, uint lodLevel, uint face) { uvec3 attributes = uvec3(0); @@ -88,8 +94,10 @@ uvec3 makeRemainingAttributes(const in BlockModel model, const in Quad quad, uin attributes.y = tintColour; #else bool isTranslucent = modelIsTranslucent(model); - bool hasAO = modelHasMipmaps(model);//TODO: replace with per face AO flag - bool isShaded = hasAO;//TODO: make this a per face flag + + //afak, these are the same variable in vanilla, (i.e. shaded == ao) + bool isShaded = modelIsShaded(model); + bool hasAO = isShaded; vec4 tinting = getLighting(lighting); @@ -202,4 +210,5 @@ float computeDirectionalFaceTint(bool isShaded, uint face) { } #endif return 1.0f; -} \ No newline at end of file +} +#endif \ No newline at end of file