mipping
This commit is contained in:
@@ -64,6 +64,6 @@ public class VoxyClient implements ClientModInitializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean disableSodiumChunkRender() {
|
public static boolean disableSodiumChunkRender() {
|
||||||
return getOcclusionDebugState() != 0;
|
return false;// getOcclusionDebugState() != 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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() {
|
||||||
|
|||||||
128
src/main/java/me/cortex/voxy/client/core/model/MipGen.java
Normal file
128
src/main/java/me/cortex/voxy/client/core/model/MipGen.java
Normal 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) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
g += ColorSRGB.srgbToLinear((C01 >> 8) & 0xFF);
|
||||||
|
b += ColorSRGB.srgbToLinear((C01 >> 16) & 0xFF);
|
||||||
|
a += darkend ? (C01 >>> 24) : ColorSRGB.srgbToLinear(C01 >>> 24);
|
||||||
|
}
|
||||||
|
if (darkend || (C10 >>> 24) != 0) {
|
||||||
|
r += ColorSRGB.srgbToLinear((C10 >> 0) & 0xFF);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ColorSRGB.linearToSrgb(
|
||||||
|
r / 4,
|
||||||
|
g / 4,
|
||||||
|
b / 4,
|
||||||
|
darkend ? ((int) a) / 4 : ARGB.linearToSrgbChannel(a / 4)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
//TODO: FIXME!!! ITS READING IT AS ABGR??? isnt the format RGBA??
|
|
||||||
private static int weightedAverageColor(int a, int b) {
|
|
||||||
//We specifically want the entire other component if the alpha is zero
|
|
||||||
// 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) {
|
|
||||||
//return (a&0x00FFFFFF)|((a>>>2)&0x3FC00000);
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((a^b)&0xFF000000)==0) {
|
|
||||||
return ColorSRGB.linearToSrgb(
|
|
||||||
addHalfLinear(0, a,b),
|
|
||||||
addHalfLinear(8, a,b),
|
|
||||||
addHalfLinear(16, a,b),
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user