This commit is contained in:
mcrcortex
2025-12-14 23:44:46 +10:00
parent 03d971385c
commit c7cf4a74d5
9 changed files with 221 additions and 143 deletions

View File

@@ -64,6 +64,6 @@ public class VoxyClient implements ClientModInitializer {
} }
public static boolean disableSodiumChunkRender() { public static boolean disableSodiumChunkRender() {
return getOcclusionDebugState() != 0; return false;// getOcclusionDebugState() != 0;
} }
} }

View File

@@ -376,7 +376,7 @@ public class VoxyRenderSystem {
return base.mulLocal( return base.mulLocal(
makeProjectionMatrix(0.05f, Minecraft.getInstance().gameRenderer.getDepthFar()).invert(), makeProjectionMatrix(0.05f, Minecraft.getInstance().gameRenderer.getDepthFar()).invert(),
new Matrix4f() new Matrix4f()
).mulLocal(makeProjectionMatrix(VoxyClient.getOcclusionDebugState()<=1?16f:0.1f, 16*3000)); ).mulLocal(makeProjectionMatrix(VoxyClient.disableSodiumChunkRender()?0.1f:16f, 16*3000));
} }
private boolean frexStillHasWork() { private boolean frexStillHasWork() {

View File

@@ -0,0 +1,128 @@
package me.cortex.voxy.client.core.model;
import it.unimi.dsi.fastutil.bytes.ByteArrayFIFOQueue;
import me.cortex.voxy.common.util.MemoryBuffer;
import net.caffeinemc.mods.sodium.client.util.color.ColorSRGB;
import org.lwjgl.system.MemoryUtil;
import java.util.Arrays;
import static me.cortex.voxy.client.core.model.ModelFactory.LAYERS;
import static me.cortex.voxy.client.core.model.ModelFactory.MODEL_TEXTURE_SIZE;
public class MipGen {
static {
if (MODEL_TEXTURE_SIZE>16) throw new IllegalStateException("TODO: THIS MUST BE UPDATED, IT CURRENTLY ASSUMES 16 OR SMALLER SIZE");
}
private static final short[] SCRATCH = new short[MODEL_TEXTURE_SIZE*MODEL_TEXTURE_SIZE];
private static final ByteArrayFIFOQueue QUEUE = new ByteArrayFIFOQueue(MODEL_TEXTURE_SIZE*MODEL_TEXTURE_SIZE);
private static long getOffset(int bx, int by, int i) {
bx += i&(MODEL_TEXTURE_SIZE-1);
by += i/MODEL_TEXTURE_SIZE;
return bx+by*MODEL_TEXTURE_SIZE*3;
}
private static void solidify(long baseAddr, byte msk) {
for (int idx = 0; idx < 6; idx++) {
if (((msk>>idx)&1)==0) continue;
int bx = (idx>>1)*MODEL_TEXTURE_SIZE;
int by = (idx&1)*MODEL_TEXTURE_SIZE;
long cAddr = baseAddr + (long)(bx+by*MODEL_TEXTURE_SIZE*3)*4;
Arrays.fill(SCRATCH, (short) -1);
for (int y = 0; y<MODEL_TEXTURE_SIZE;y++) {
for (int x = 0; x<MODEL_TEXTURE_SIZE;x++) {
int colour = MemoryUtil.memGetInt(cAddr+(x+y*MODEL_TEXTURE_SIZE*3)*4);
if ((colour&0xFF000000)!=0) {
int pos = x+y*MODEL_TEXTURE_SIZE;
SCRATCH[pos] = ((short)pos);
QUEUE.enqueue((byte) pos);
}
}
}
while (!QUEUE.isEmpty()) {
int pos = Byte.toUnsignedInt(QUEUE.dequeueByte());
int x = pos&(MODEL_TEXTURE_SIZE-1);
int y = pos/MODEL_TEXTURE_SIZE;//this better be turned into a bitshift
short newVal = (short) (SCRATCH[pos]+(short) 0x0100);
for (int D = 3; D!=-1; D--) {
int d = 2*(D&1)-1;
int x2 = x+(((D&2)==2)?d:0);
int y2 = y+(((D&2)==0)?d:0);
if (x2<0||x2>=MODEL_TEXTURE_SIZE||y2<0||y2>=MODEL_TEXTURE_SIZE) continue;
int pos2 = x2+y2*MODEL_TEXTURE_SIZE;
if ((newVal&0xFF00)<(SCRATCH[pos2]&0xFF00)) {
SCRATCH[pos2] = newVal;
QUEUE.enqueue((byte) pos2);
}
}
}
for (int i = 0; i < MODEL_TEXTURE_SIZE*MODEL_TEXTURE_SIZE; i++) {
int d = Short.toUnsignedInt(SCRATCH[i]);
if ((d&0xFF00)!=0) {
int c = MemoryUtil.memGetInt(baseAddr+getOffset(bx, by, d&0xFF)*4)&0x00FFFFFF;
MemoryUtil.memPutInt(baseAddr+getOffset(bx, by, i)*4, c);
}
}
}
}
public static void putTextures(boolean darkened, ColourDepthTextureData[] textures, MemoryBuffer into) {
//if (MODEL_TEXTURE_SIZE != 16) {throw new IllegalStateException("THIS METHOD MUST BE REDONE IF THIS CONST CHANGES");}
//TODO: need to use a write mask to see what pixels must be used to contribute to mipping
// as in, using the depth/stencil info, check if pixel was written to, if so, use that pixel when blending, else dont
final long addr = into.address;
final int LENGTH_B = MODEL_TEXTURE_SIZE*3;
byte solidMsk = 0;
for (int i = 0; i < 6; i++) {
int x = (i>>1)*MODEL_TEXTURE_SIZE;
int y = (i&1)*MODEL_TEXTURE_SIZE;
int j = 0;
boolean anyTransparent = false;
for (int t : textures[i].colour()) {
int o = ((y+(j>>LAYERS))*LENGTH_B + ((j&(MODEL_TEXTURE_SIZE-1))+x))*4; j++;//LAYERS here is just cause faster
//t = ((t&0xFF000000)==0)?0x00_FF_00_FF:t;//great for testing
MemoryUtil.memPutInt(addr+o, t);
anyTransparent |= ((t&0xFF000000)==0);
}
solidMsk |= (anyTransparent?1:0)<<i;
}
if (!darkened) {
solidify(addr, solidMsk);
}
//Mip the scratch
long dAddr = addr;
for (int i = 0; i < LAYERS-1; i++) {
long sAddr = dAddr;
dAddr += (MODEL_TEXTURE_SIZE*MODEL_TEXTURE_SIZE*3*2*4)>>(i<<1);//is.. i*2 because shrink both MODEL_TEXTURE_SIZE by >>i so is 2*i total shift
int width = (MODEL_TEXTURE_SIZE*3)>>(i+1);
int sWidth = (MODEL_TEXTURE_SIZE*3)>>i;
int height = (MODEL_TEXTURE_SIZE*2)>>(i+1);
//TODO: OPTIMZIE THIS
for (int px = 0; px < width; px++) {
for (int py = 0; py < height; py++) {
long bp = sAddr + (px*2 + py*2*sWidth)*4;
int C00 = MemoryUtil.memGetInt(bp);
int C01 = MemoryUtil.memGetInt(bp+sWidth*4);
int C10 = MemoryUtil.memGetInt(bp+4);
int C11 = MemoryUtil.memGetInt(bp+sWidth*4+4);
MemoryUtil.memPutInt(dAddr + (px+py*width) * 4L, TextureUtils.mipColours(darkened, C00, C01, C10, C11));
}
}
}
/*
*/
}
public static void generateMipmaps(long[] textures, int size) {
}
}

View File

@@ -63,6 +63,7 @@ import static org.lwjgl.opengl.GL11.*;
// this _quarters_ the memory requirements for the texture atlas!!! WHICH IS HUGE saving // this _quarters_ the memory requirements for the texture atlas!!! WHICH IS HUGE saving
public class ModelFactory { public class ModelFactory {
public static final int MODEL_TEXTURE_SIZE = 16; public static final int MODEL_TEXTURE_SIZE = 16;
public static final int LAYERS = Integer.numberOfTrailingZeros(MODEL_TEXTURE_SIZE);
//TODO: replace the fluid BlockState with a client model id integer of the fluidState, requires looking up //TODO: replace the fluid BlockState with a client model id integer of the fluidState, requires looking up
// the fluid state in the mipper // the fluid state in the mipper
@@ -158,6 +159,7 @@ public class ModelFactory {
private final MemoryBuffer rawData; private final MemoryBuffer rawData;
public boolean isShaded; public boolean isShaded;
public boolean hasDarkenedTextures;
public RawBakeResult(int blockId, BlockState blockState, MemoryBuffer rawData) { public RawBakeResult(int blockId, BlockState blockState, MemoryBuffer rawData) {
this.blockId = blockId; this.blockId = blockId;
@@ -219,7 +221,9 @@ public class ModelFactory {
RawBakeResult result = new RawBakeResult(blockId, blockState); 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))); int allocation = this.downstream.download(MODEL_TEXTURE_SIZE*MODEL_TEXTURE_SIZE*2*4*6, ptr -> this.rawBakeResults.add(result.cpyBuf(ptr)));
result.isShaded = this.bakery.renderToStream(blockState, this.downstream.getBufferId(), allocation); int flags = this.bakery.renderToStream(blockState, this.downstream.getBufferId(), allocation);
result.hasDarkenedTextures = (flags&2)!=0;
result.isShaded = (flags&1)!=0;
return true; return true;
} }
@@ -245,7 +249,7 @@ public class ModelFactory {
} }
} }
result.rawData.free(); result.rawData.free();
var bakeResult = this.processTextureBakeResult(result.blockId, result.blockState, textureData, result.isShaded); var bakeResult = this.processTextureBakeResult(result.blockId, result.blockState, textureData, result.isShaded, result.hasDarkenedTextures);
if (bakeResult!=null) { if (bakeResult!=null) {
this.uploadResults.add(bakeResult); this.uploadResults.add(bakeResult);
} }
@@ -337,7 +341,7 @@ public class ModelFactory {
} }
} }
private ModelBakeResultUpload processTextureBakeResult(int blockId, BlockState blockState, ColourDepthTextureData[] textureData, boolean isShaded) { private ModelBakeResultUpload processTextureBakeResult(int blockId, BlockState blockState, ColourDepthTextureData[] textureData, boolean isShaded, boolean darkenedTinting) {
if (this.idMappings[blockId] != -1) { 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! //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); throw new IllegalStateException("Block id already added: " + blockId + " for state: " + blockState);
@@ -636,7 +640,7 @@ public class ModelFactory {
//TODO callback to inject extra data into the model data //TODO callback to inject extra data into the model data
this.putTextures(textureData, uploadResult.texture); MipGen.putTextures(darkenedTinting, textureData, uploadResult.texture);
//glGenerateTextureMipmap(this.textures.id); //glGenerateTextureMipmap(this.textures.id);
@@ -734,7 +738,7 @@ public class ModelFactory {
// if it is, need to add it to a list and mark it as biome colour dependent or something then the shader // if it is, need to add it to a list and mark it as biome colour dependent or something then the shader
// will either use the uint as an index or a direct colour multiplier // will either use the uint as an index or a direct colour multiplier
private static int captureColourConstant(BlockColor colorProvider, BlockState state, Biome biome) { private static int captureColourConstant(BlockColor colorProvider, BlockState state, Biome biome) {
return colorProvider.getColor(state, new BlockAndTintGetter() { var getter = new BlockAndTintGetter() {
@Override @Override
public float getShade(Direction direction, boolean shaded) { public float getShade(Direction direction, boolean shaded) {
return 0; return 0;
@@ -780,12 +784,16 @@ public class ModelFactory {
public int getMinY() { public int getMinY() {
return 0; return 0;
} }
}, BlockPos.ZERO, 0); };
//Multiple layer bs to do with flower beds
int c = colorProvider.getColor(state, getter, BlockPos.ZERO, 0);
if (c!=-1) return c;
return colorProvider.getColor(state, getter, BlockPos.ZERO, 1);
} }
private static boolean isBiomeDependentColour(BlockColor colorProvider, BlockState state) { private static boolean isBiomeDependentColour(BlockColor colorProvider, BlockState state) {
boolean[] biomeDependent = new boolean[1]; boolean[] biomeDependent = new boolean[1];
colorProvider.getColor(state, new BlockAndTintGetter() { var getter = new BlockAndTintGetter() {
@Override @Override
public float getShade(Direction direction, boolean shaded) { public float getShade(Direction direction, boolean shaded) {
return 0; return 0;
@@ -832,7 +840,9 @@ public class ModelFactory {
public int getMinY() { public int getMinY() {
return 0; return 0;
} }
}, BlockPos.ZERO, 0); };
colorProvider.getColor(state, getter, BlockPos.ZERO, 0);
colorProvider.getColor(state, getter, BlockPos.ZERO, 1);
return biomeDependent[0]; return biomeDependent[0];
} }
@@ -881,57 +891,6 @@ public class ModelFactory {
} }
private static int computeSizeWithMips(int size) {
int total = 0;
for (;size!=0;size>>=1) total += size*size;
return total;
}
private static final MemoryBuffer SCRATCH_TEX = new MemoryBuffer((2L*3*computeSizeWithMips(MODEL_TEXTURE_SIZE))*4);
private static final int LAYERS = Integer.numberOfTrailingZeros(MODEL_TEXTURE_SIZE);
//TODO: redo to batch blit, instead of 6 seperate blits, and also fix mipping
private void putTextures(ColourDepthTextureData[] textures, MemoryBuffer into) {
//if (MODEL_TEXTURE_SIZE != 16) {throw new IllegalStateException("THIS METHOD MUST BE REDONE IF THIS CONST CHANGES");}
//TODO: need to use a write mask to see what pixels must be used to contribute to mipping
// as in, using the depth/stencil info, check if pixel was written to, if so, use that pixel when blending, else dont
final long addr = into.address;
final int LENGTH_B = MODEL_TEXTURE_SIZE*3;
for (int i = 0; i < 6; i++) {
int x = (i>>1)*MODEL_TEXTURE_SIZE;
int y = (i&1)*MODEL_TEXTURE_SIZE;
int j = 0;
for (int t : textures[i].colour()) {
int o = ((y+(j>>LAYERS))*LENGTH_B + ((j&(MODEL_TEXTURE_SIZE-1))+x))*4; j++;//LAYERS here is just cause faster
MemoryUtil.memPutInt(addr+o, t);
}
}
//Mip the scratch
long dAddr = addr;
for (int i = 0; i < LAYERS-1; i++) {
long sAddr = dAddr;
dAddr += (MODEL_TEXTURE_SIZE*MODEL_TEXTURE_SIZE*3*2*4)>>(i<<1);//is.. i*2 because shrink both MODEL_TEXTURE_SIZE by >>i so is 2*i total shift
int width = (MODEL_TEXTURE_SIZE*3)>>(i+1);
int sWidth = (MODEL_TEXTURE_SIZE*3)>>i;
int height = (MODEL_TEXTURE_SIZE*2)>>(i+1);
//TODO: OPTIMZIE THIS
for (int px = 0; px < width; px++) {
for (int py = 0; py < height; py++) {
long bp = sAddr + (px*2 + py*2*sWidth)*4;
int C00 = MemoryUtil.memGetInt(bp);
int C01 = MemoryUtil.memGetInt(bp+sWidth*4);
int C10 = MemoryUtil.memGetInt(bp+4);
int C11 = MemoryUtil.memGetInt(bp+sWidth*4+4);
MemoryUtil.memPutInt(dAddr + (px+py*width) * 4L, TextureUtils.mipColours(C00, C01, C10, C11));
}
}
}
/*
*/
}
public void free() { public void free() {
this.bakery.free(); this.bakery.free();
this.downstream.free(); this.downstream.free();
@@ -954,4 +913,11 @@ public class ModelFactory {
size += this.biomeQueue.size(); size += this.biomeQueue.size();
return size; return size;
} }
private static int computeSizeWithMips(int size) {
int total = 0;
for (;size!=0;size>>=1) total += size*size;
return total;
}
} }

View File

@@ -2,6 +2,7 @@ package me.cortex.voxy.client.core.model;
import net.caffeinemc.mods.sodium.client.util.color.ColorSRGB; import net.caffeinemc.mods.sodium.client.util.color.ColorSRGB;
import net.minecraft.client.renderer.texture.MipmapGenerator; import net.minecraft.client.renderer.texture.MipmapGenerator;
import net.minecraft.util.ARGB;
//Texturing utils to manipulate data from the model bakery //Texturing utils to manipulate data from the model bakery
public class TextureUtils { public class TextureUtils {
@@ -9,14 +10,14 @@ public class TextureUtils {
public static int getWrittenPixelCount(ColourDepthTextureData texture, int checkMode) { public static int getWrittenPixelCount(ColourDepthTextureData texture, int checkMode) {
int count = 0; int count = 0;
for (int i = 0; i < texture.colour().length; i++) { for (int i = 0; i < texture.colour().length; i++) {
count += wasPixelWritten(texture, checkMode, i)?1:0; count += wasPixelWritten(texture, checkMode, i) ? 1 : 0;
} }
return count; return count;
} }
public static boolean isSolid(ColourDepthTextureData texture) { public static boolean isSolid(ColourDepthTextureData texture) {
for (int pixel : texture.colour()) { for (int pixel : texture.colour()) {
if (((pixel>>24)&0xFF) != 255) { if (((pixel >> 24) & 0xFF) != 255) {
return false; return false;
} }
} }
@@ -26,14 +27,15 @@ public class TextureUtils {
public static final int WRITE_CHECK_STENCIL = 1; public static final int WRITE_CHECK_STENCIL = 1;
public static final int WRITE_CHECK_DEPTH = 2; public static final int WRITE_CHECK_DEPTH = 2;
public static final int WRITE_CHECK_ALPHA = 3; public static final int WRITE_CHECK_ALPHA = 3;
private static boolean wasPixelWritten(ColourDepthTextureData data, int mode, int index) { private static boolean wasPixelWritten(ColourDepthTextureData data, int mode, int index) {
if (mode == WRITE_CHECK_STENCIL) { if (mode == WRITE_CHECK_STENCIL) {
return (data.depth()[index]&0xFF)!=0; return (data.depth()[index] & 0xFF) != 0;
} else if (mode == WRITE_CHECK_DEPTH) { } else if (mode == WRITE_CHECK_DEPTH) {
return (data.depth()[index]>>>8)!=((1<<24)-1); return (data.depth()[index] >>> 8) != ((1 << 24) - 1);
} else if (mode == WRITE_CHECK_ALPHA) { } else if (mode == WRITE_CHECK_ALPHA) {
//TODO:FIXME: for some reason it has an alpha of 1 even if its ment to be 0 //TODO:FIXME: for some reason it has an alpha of 1 even if its ment to be 0
return ((data.colour()[index]>>>24)&0xff)>1; return ((data.colour()[index] >>> 24) & 0xff) > 1;
} }
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
@@ -54,10 +56,10 @@ public class TextureUtils {
if (!wasPixelWritten(texture, checkMode, i)) { if (!wasPixelWritten(texture, checkMode, i)) {
continue; continue;
} }
if ((colourData[i]&0xFFFFFF) == 0 || (colourData[i]>>>24)==0) {//If the pixel is fully black (or translucent) if ((colourData[i] & 0xFFFFFF) == 0 || (colourData[i] >>> 24) == 0) {//If the pixel is fully black (or translucent)
continue; continue;
} }
boolean pixelTinited = (depthData[i]&(1<<7))!=0; boolean pixelTinited = (depthData[i] & (1 << 7)) != 0;
wasWriten |= true; wasWriten |= true;
allTinted &= pixelTinited; allTinted &= pixelTinited;
someTinted |= pixelTinited; someTinted |= pixelTinited;
@@ -66,7 +68,7 @@ public class TextureUtils {
if (!wasWriten) { if (!wasWriten) {
return 0; return 0;
} }
return someTinted?(allTinted?3:2):1; return someTinted ? (allTinted ? 3 : 2) : 1;
} }
public static final int DEPTH_MODE_AVG = 1; public static final int DEPTH_MODE_AVG = 1;
@@ -90,7 +92,7 @@ public class TextureUtils {
if (!wasPixelWritten(texture, checkMode, i)) { if (!wasPixelWritten(texture, checkMode, i)) {
continue; continue;
} }
int depth = depthData[i]>>>8; int depth = depthData[i] >>> 8;
if (mode == DEPTH_MODE_AVG) { if (mode == DEPTH_MODE_AVG) {
a++; a++;
b += depth; b += depth;
@@ -105,7 +107,7 @@ public class TextureUtils {
if (a == 0) { if (a == 0) {
return -1; return -1;
} }
return u2fdepth((int) (b/a)); return u2fdepth((int) (b / a));
} else if (mode == DEPTH_MODE_MAX) { } else if (mode == DEPTH_MODE_MAX) {
if (a == Long.MIN_VALUE) { if (a == Long.MIN_VALUE) {
return -1; return -1;
@@ -121,7 +123,7 @@ public class TextureUtils {
} }
private static float u2fdepth(int depth) { private static float u2fdepth(int depth) {
float depthF = (float) ((double)depth/((1<<24)-1)); float depthF = (float) ((double) depth / ((1 << 24) - 1));
//https://registry.khronos.org/OpenGL-Refpages/gl4/html/glDepthRange.xhtml //https://registry.khronos.org/OpenGL-Refpages/gl4/html/glDepthRange.xhtml
// due to this and the unsigned bullshit, believe the depth value needs to get multiplied by 2 // due to this and the unsigned bullshit, believe the depth value needs to get multiplied by 2
@@ -150,10 +152,10 @@ public class TextureUtils {
minX++; minX++;
} while (minX != data.width()); } while (minX != data.width());
int maxX = data.width()-1; int maxX = data.width() - 1;
maxXCheck: maxXCheck:
do { do {
for (int y = data.height()-1; y!=-1; y--) { for (int y = data.height() - 1; y != -1; y--) {
int idx = maxX + (y * data.width()); int idx = maxX + (y * data.width());
if (wasPixelWritten(data, checkMode, idx)) { if (wasPixelWritten(data, checkMode, idx)) {
break maxXCheck;//pixel was written too so break from loop break maxXCheck;//pixel was written too so break from loop
@@ -178,10 +180,10 @@ public class TextureUtils {
} while (minY != data.height()); } while (minY != data.height());
int maxY = data.height()-1; int maxY = data.height() - 1;
maxYCheck: maxYCheck:
do { do {
for (int x = data.width()-1; x!=-1; x--) { for (int x = data.width() - 1; x != -1; x--) {
int idx = (maxY * data.height()) + x; int idx = (maxY * data.height()) + x;
if (wasPixelWritten(data, checkMode, idx)) { if (wasPixelWritten(data, checkMode, idx)) {
break maxYCheck;//pixel was written too so break from loop break maxYCheck;//pixel was written too so break from loop
@@ -195,70 +197,42 @@ public class TextureUtils {
} }
public static int mipColours(boolean darkend, int C00, int C01, int C10, int C11) {
darkend = !darkend;//Invert to make it easier
float r = 0.0f;
float g = 0.0f;
float b = 0.0f;
float a = 0.0f;
if (darkend || (C00 >>> 24) != 0) {
r += ColorSRGB.srgbToLinear((C00 >> 0) & 0xFF);
g += ColorSRGB.srgbToLinear((C00 >> 8) & 0xFF);
b += ColorSRGB.srgbToLinear((C00 >> 16) & 0xFF);
a += darkend ? (C00 >>> 24) : ColorSRGB.srgbToLinear(C00 >>> 24);
public static int mipColours(int one, int two, int three, int four) {
if (false) {
return 0;
//return MipmapGenerator.alphaBlend(one, two, three, four, false);
} else {
return weightedAverageColor(weightedAverageColor(one, two), weightedAverageColor(three, four));
} }
} if (darkend || (C01 >>> 24) != 0) {
r += ColorSRGB.srgbToLinear((C01 >> 0) & 0xFF);
//TODO: FIXME!!! ITS READING IT AS ABGR??? isnt the format RGBA?? g += ColorSRGB.srgbToLinear((C01 >> 8) & 0xFF);
private static int weightedAverageColor(int a, int b) { b += ColorSRGB.srgbToLinear((C01 >> 16) & 0xFF);
//We specifically want the entire other component if the alpha is zero a += darkend ? (C01 >>> 24) : ColorSRGB.srgbToLinear(C01 >>> 24);
// this prevents black mips from generating due to A) non filled colours, and B) when the sampler samples everything it doesnt detonate
if ((a&0xFF000000) == 0) {
//return (b&0x00FFFFFF)|((b>>>2)&0x3FC00000);
return b;
} }
if ((b&0xFF000000) == 0) { if (darkend || (C10 >>> 24) != 0) {
//return (a&0x00FFFFFF)|((a>>>2)&0x3FC00000); r += ColorSRGB.srgbToLinear((C10 >> 0) & 0xFF);
return a; g += ColorSRGB.srgbToLinear((C10 >> 8) & 0xFF);
b += ColorSRGB.srgbToLinear((C10 >> 16) & 0xFF);
a += darkend ? (C10 >>> 24) : ColorSRGB.srgbToLinear(C10 >>> 24);
}
if (darkend || (C11 >>> 24) != 0) {
r += ColorSRGB.srgbToLinear((C11 >> 0) & 0xFF);
g += ColorSRGB.srgbToLinear((C11 >> 8) & 0xFF);
b += ColorSRGB.srgbToLinear((C11 >> 16) & 0xFF);
a += darkend ? (C11 >>> 24) : ColorSRGB.srgbToLinear(C11 >>> 24);
} }
if (((a^b)&0xFF000000)==0) { return ColorSRGB.linearToSrgb(
return ColorSRGB.linearToSrgb( r / 4,
addHalfLinear(0, a,b), g / 4,
addHalfLinear(8, a,b), b / 4,
addHalfLinear(16, a,b), darkend ? ((int) a) / 4 : ARGB.linearToSrgbChannel(a / 4)
a>>>24); );
}
{
int A = (a>>>24);
int B = (a>>>24);
float mul = 1.0F / (float)(A+B);
float wA = A * mul;
float wB = B * mul;
return ColorSRGB.linearToSrgb(
addMulLinear(0, a,b,wA,wB),
addMulLinear(8, a,b,wA,wB),
addMulLinear(16, a,b,wA,wB)
, (A + B)/2);
}
}
private static float addHalfLinear(int shift, int a, int b) {
return addMulLinear(shift, a, b, 0.5f, 0.5f);
}
private static float addMulLinear(int shift, int a, int b, float mulA, float mulB) {
return Math.fma(ColorSRGB.srgbToLinear((a>>shift)&0xFF),mulA, ColorSRGB.srgbToLinear((b>>shift)&0xFF)*mulB);
} }
} }

View File

@@ -170,7 +170,7 @@ public class ModelTextureBakery {
} }
public boolean renderToStream(BlockState state, int streamBuffer, int streamOffset) { public int renderToStream(BlockState state, int streamBuffer, int streamOffset) {
this.capture.clear(); this.capture.clear();
boolean isBlock = true; boolean isBlock = true;
ChunkSectionLayer layer; ChunkSectionLayer layer;
@@ -221,10 +221,12 @@ public class ModelTextureBakery {
} }
boolean isAnyShaded = false; boolean isAnyShaded = false;
boolean isAnyDarkend = false;
if (isBlock) { if (isBlock) {
this.vc.reset(); this.vc.reset();
this.bakeBlockModel(state, layer); this.bakeBlockModel(state, layer);
isAnyShaded |= this.vc.anyShaded; isAnyShaded |= this.vc.anyShaded;
isAnyDarkend |= this.vc.anyDarkendTex;
if (!this.vc.isEmpty()) {//only render if there... is shit to render if (!this.vc.isEmpty()) {//only render if there... is shit to render
//Setup for continual emission //Setup for continual emission
@@ -267,6 +269,7 @@ public class ModelTextureBakery {
this.bakeFluidState(state, layer, i); this.bakeFluidState(state, layer, i);
if (this.vc.isEmpty()) continue; if (this.vc.isEmpty()) continue;
isAnyShaded |= this.vc.anyShaded; isAnyShaded |= this.vc.anyShaded;
isAnyDarkend |= this.vc.anyDarkendTex;
BudgetBufferRenderer.setup(this.vc.getAddress(), this.vc.quadCount(), blockTextureId); BudgetBufferRenderer.setup(this.vc.getAddress(), this.vc.quadCount(), blockTextureId);
glViewport((i % 3) * this.width, (i / 3) * this.height, this.width, this.height); glViewport((i % 3) * this.width, (i / 3) * this.height, this.width, this.height);
@@ -331,7 +334,7 @@ public class ModelTextureBakery {
GL14.glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); GL14.glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
} }
return isAnyShaded; return (isAnyShaded?1:0)|(isAnyDarkend?2:0);
} }

View File

@@ -4,6 +4,7 @@ package me.cortex.voxy.client.core.model.bakery;
import me.cortex.voxy.common.util.MemoryBuffer; import me.cortex.voxy.common.util.MemoryBuffer;
import net.minecraft.client.model.geom.builders.UVPair; import net.minecraft.client.model.geom.builders.UVPair;
import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.texture.MipmapStrategy;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import static me.cortex.voxy.client.core.model.bakery.BudgetBufferRenderer.VERTEX_FORMAT_SIZE; import static me.cortex.voxy.client.core.model.bakery.BudgetBufferRenderer.VERTEX_FORMAT_SIZE;
@@ -17,6 +18,7 @@ public final class ReuseVertexConsumer implements VertexConsumer {
private int defaultMeta; private int defaultMeta;
public boolean anyShaded; public boolean anyShaded;
public boolean anyDarkendTex;
public ReuseVertexConsumer() { public ReuseVertexConsumer() {
this.reset(); this.reset();
@@ -82,6 +84,7 @@ public final class ReuseVertexConsumer implements VertexConsumer {
public ReuseVertexConsumer quad(BakedQuad quad, int metadata) { public ReuseVertexConsumer quad(BakedQuad quad, int metadata) {
this.anyShaded |= quad.shade(); this.anyShaded |= quad.shade();
this.anyDarkendTex |= quad.sprite().contents().mipmapStrategy == MipmapStrategy.DARK_CUTOUT;
this.ensureCanPut(); this.ensureCanPut();
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
var pos = quad.position(i); var pos = quad.position(i);
@@ -109,6 +112,7 @@ public final class ReuseVertexConsumer implements VertexConsumer {
public ReuseVertexConsumer reset() { public ReuseVertexConsumer reset() {
this.anyShaded = false; this.anyShaded = false;
this.anyDarkendTex = false;
this.defaultMeta = 0;//RESET THE DEFAULT META this.defaultMeta = 0;//RESET THE DEFAULT META
this.count = 0; this.count = 0;
this.ptr = this.buffer.address - VERTEX_FORMAT_SIZE;//the thing is first time this gets incremented by FORMAT_STRIDE this.ptr = this.buffer.address - VERTEX_FORMAT_SIZE;//the thing is first time this gets incremented by FORMAT_STRIDE

View File

@@ -166,6 +166,7 @@ void main() {
//Also, small quad is really fking over the mipping level somehow //Also, small quad is really fking over the mipping level somehow
#ifndef TRANSLUCENT #ifndef TRANSLUCENT
if (useDiscard() && (textureLod(blockModelAtlas, texPos, 0).a <= 0.1f)) { if (useDiscard() && (textureLod(blockModelAtlas, texPos, 0).a <= 0.1f)) {
//if (useDiscard() && (colour.a <= 0.1f)) {
#else #else
if (textureLod(blockModelAtlas, texPos, 0).a == 0.0f) { if (textureLod(blockModelAtlas, texPos, 0).a == 0.0f) {
#endif #endif

View File

@@ -14,6 +14,8 @@ accessible field net/minecraft/world/level/chunk/PalettedContainer data Lnet/min
accessible field net/minecraft/world/level/chunk/PalettedContainer$Data palette Lnet/minecraft/world/level/chunk/Palette; accessible field net/minecraft/world/level/chunk/PalettedContainer$Data palette Lnet/minecraft/world/level/chunk/Palette;
accessible field net/minecraft/world/level/chunk/PalettedContainer$Data storage Lnet/minecraft/util/BitStorage; accessible field net/minecraft/world/level/chunk/PalettedContainer$Data storage Lnet/minecraft/util/BitStorage;
accessible field net/minecraft/client/renderer/texture/SpriteContents mipmapStrategy Lnet/minecraft/client/renderer/texture/MipmapStrategy;
accessible method net/minecraft/client/renderer/GameRenderer getFov (Lnet/minecraft/client/Camera;FZ)F accessible method net/minecraft/client/renderer/GameRenderer getFov (Lnet/minecraft/client/Camera;FZ)F
accessible method net/minecraft/client/multiplayer/ClientChunkCache$Storage getChunk (I)Lnet/minecraft/world/level/chunk/LevelChunk; accessible method net/minecraft/client/multiplayer/ClientChunkCache$Storage getChunk (I)Lnet/minecraft/world/level/chunk/LevelChunk;