God i hate opengl
This commit is contained in:
@@ -2,7 +2,7 @@ package me.cortex.zenith.client.core.model;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public record ColourDepthTextureData(int[] colour, int[] depth) {
|
||||
public record ColourDepthTextureData(int[] colour, int[] depth, int width, int height) {
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) return false;
|
||||
@@ -12,6 +12,6 @@ public record ColourDepthTextureData(int[] colour, int[] depth) {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Arrays.hashCode(this.colour) ^ Arrays.hashCode(this.depth);
|
||||
return (this.width * 312337173 * (Arrays.hashCode(this.colour) ^ Arrays.hashCode(this.depth))) ^ this.height;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import me.cortex.zenith.client.core.gl.GlBuffer;
|
||||
import me.cortex.zenith.client.core.gl.GlTexture;
|
||||
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;
|
||||
@@ -97,9 +98,9 @@ public class ModelManager {
|
||||
//TODO: so need a few things, per face sizes and offsets, the sizes should be computed from the pixels and find the minimum bounding pixel
|
||||
// while the depth is computed from the depth buffer data
|
||||
public int addEntry(int blockId, BlockState blockState) {
|
||||
if (this.idMappings[blockId] != -1) {
|
||||
throw new IllegalArgumentException("Trying to add entry for duplicate id");
|
||||
}
|
||||
//if (this.idMappings[blockId] != -1) {
|
||||
// throw new IllegalArgumentException("Trying to add entry for duplicate id");
|
||||
//}
|
||||
|
||||
int modelId = -1;
|
||||
var textureData = this.bakery.renderFaces(blockState, 123456);
|
||||
@@ -107,7 +108,8 @@ public class ModelManager {
|
||||
int possibleDuplicate = this.modelTexture2id.getInt(List.of(textureData));
|
||||
if (possibleDuplicate != -1) {//Duplicate found
|
||||
this.idMappings[blockId] = possibleDuplicate;
|
||||
return possibleDuplicate;
|
||||
modelId = possibleDuplicate;
|
||||
//return possibleDuplicate;
|
||||
} else {//Not a duplicate so create a new entry
|
||||
modelId = this.modelTexture2id.size();
|
||||
this.idMappings[blockId] = modelId;
|
||||
@@ -119,22 +121,15 @@ public class ModelManager {
|
||||
var colourProvider = MinecraftClient.getInstance().getBlockColors().providers.get(Registries.BLOCK.getRawId(blockState.getBlock()));
|
||||
|
||||
var blockRenderLayer = RenderLayers.getBlockLayer(blockState);
|
||||
int checkMode = blockRenderLayer==RenderLayer.getSolid()?TextureUtils.WRITE_CHECK_STENCIL:TextureUtils.WRITE_CHECK_ALPHA;
|
||||
|
||||
//If it is the solid layer, it is _always_ going to occlude fully for all written pixels, even if they are 100% translucent, this should save alot of resources
|
||||
// if it is cutout it might occlude might not, need to test
|
||||
// if it is translucent it will _never_ occlude
|
||||
|
||||
//NOTE: this is excluding fluid states
|
||||
|
||||
//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);
|
||||
|
||||
for (int face = 0; face < 6; face++) {
|
||||
if (sizes[face] == -1) {//Face is empty, so ignore
|
||||
continue;
|
||||
}
|
||||
//TODO: combine all the methods into a single
|
||||
//boolean fullyOccluding = TextureUtils.hasAlpha()
|
||||
}
|
||||
|
||||
|
||||
//Model data contains, the quad size and offset of each face and whether the face needs to be resolved with a colour modifier
|
||||
@@ -162,7 +157,20 @@ public class ModelManager {
|
||||
|
||||
|
||||
|
||||
//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
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -170,17 +178,30 @@ public class ModelManager {
|
||||
return modelId;
|
||||
}
|
||||
|
||||
private int[] computeModelDepth(ColourDepthTextureData[] textures) {
|
||||
int[] res = new int[6];
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private float[] computeModelDepth(ColourDepthTextureData[] textures, int checkMode) {
|
||||
float[] res = new float[6];
|
||||
for (var dir : Direction.values()) {
|
||||
var data = textures[dir.getId()];
|
||||
float fd = TextureUtils.computeDepth(data, TextureUtils.DEPTH_MODE_MIN);//Compute the min float depth, smaller means closer to the camera, range 0-1
|
||||
float fd = TextureUtils.computeDepth(data, TextureUtils.DEPTH_MODE_MIN, checkMode);//Compute the min float depth, smaller means closer to the camera, range 0-1
|
||||
int depth = Math.round(fd * this.modelTextureSize);
|
||||
//If fd is -1, it means that there was nothing rendered on that face and it should be discarded
|
||||
if (fd < -0.1) {
|
||||
res[dir.ordinal()] = -1;
|
||||
} else {
|
||||
res[dir.ordinal()] = depth;
|
||||
res[dir.ordinal()] = ((float) depth)/this.modelTextureSize;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
||||
@@ -90,7 +90,12 @@ public class ModelTextureBakery {
|
||||
var oldProjection = new Matrix4f(RenderSystem.getProjectionMatrix());
|
||||
GL11C.glViewport(0, 0, this.width, this.height);
|
||||
|
||||
RenderSystem.setProjectionMatrix(new Matrix4f().identity().scale(2,2,-1f).translate(-0.5f, -0.5f, 0.0f), VertexSorter.BY_Z);
|
||||
RenderSystem.setProjectionMatrix(new Matrix4f().identity().set(new float[]{
|
||||
2,0,0,0,
|
||||
0, 2,0,0,
|
||||
0,0, -1f,0,
|
||||
-1,-1,0,1,
|
||||
}), VertexSorter.BY_Z);
|
||||
|
||||
glClearColor(0,0,0,0);
|
||||
glClearDepth(1);
|
||||
@@ -100,6 +105,8 @@ public class ModelTextureBakery {
|
||||
var renderLayer = RenderLayers.getBlockLayer(state);
|
||||
|
||||
renderLayer.startDrawing();
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
glDepthRange(0, 1);
|
||||
RenderSystem.depthMask(true);
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.enableDepthTest();
|
||||
@@ -107,7 +114,10 @@ public class ModelTextureBakery {
|
||||
RenderSystem.depthFunc(GL_LESS);
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
//TODO: bind the required uniforms and
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
|
||||
glStencilFunc(GL_ALWAYS, 1, 0xFF);
|
||||
glStencilMask(0xFF);
|
||||
|
||||
this.rasterShader.bind();
|
||||
RenderSystem.bindTexture(RenderSystem.getShaderTexture(0));
|
||||
GlUniform.uniform1(0, 0);
|
||||
@@ -124,14 +134,18 @@ public class ModelTextureBakery {
|
||||
var faces = new ColourDepthTextureData[FACE_VIEWS.size()];
|
||||
for (int i = 0; i < faces.length; i++) {
|
||||
faces[i] = captureView(state, model, FACE_VIEWS.get(i), randomValue);
|
||||
//glBlitNamedFramebuffer(this.framebuffer.id, oldFB, 0,0,16,16,300*(i%3),300*(i/3),300*(i%3)+256,300*(i/3)+256, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
}
|
||||
|
||||
renderLayer.endDrawing();
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
|
||||
RenderSystem.setProjectionMatrix(oldProjection, VertexSorter.BY_DISTANCE);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, oldFB);
|
||||
GL11C.glViewport(GlStateManager.Viewport.getX(), GlStateManager.Viewport.getY(), GlStateManager.Viewport.getWidth(), GlStateManager.Viewport.getHeight());
|
||||
glBlitNamedFramebuffer(this.framebuffer.id, oldFB, 0,0,16,16,0,0,256,256, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
|
||||
//TODO: FIXME: fully revert the state of opengl
|
||||
|
||||
return faces;
|
||||
}
|
||||
|
||||
@@ -142,7 +156,7 @@ public class ModelTextureBakery {
|
||||
renderQuads(vc, state, model, stack, randomValue);
|
||||
|
||||
float[] mat = new float[4*4];
|
||||
new Matrix4f(RenderSystem.getModelViewMatrix()).mul(RenderSystem.getProjectionMatrix()).get(mat);
|
||||
RenderSystem.getProjectionMatrix().get(mat);
|
||||
glUniformMatrix4fv(1, false, mat);
|
||||
BufferRenderer.draw(vc.end());
|
||||
|
||||
@@ -151,7 +165,7 @@ public class ModelTextureBakery {
|
||||
int[] depthData = new int[this.width*this.height];
|
||||
glGetTextureImage(this.colourTex.id, 0, GL_RGBA, GL_UNSIGNED_BYTE, colourData);
|
||||
glGetTextureImage(this.depthTex.id, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, depthData);
|
||||
return new ColourDepthTextureData(colourData, depthData);
|
||||
return new ColourDepthTextureData(colourData, depthData, this.width, this.height);
|
||||
}
|
||||
|
||||
private static void renderQuads(BufferBuilder builder, BlockState state, BakedModel model, MatrixStack stack, long randomValue) {
|
||||
|
||||
@@ -22,7 +22,7 @@ public class TextureUtils {
|
||||
public static int getNonWrittenPixels(ColourDepthTextureData texture) {
|
||||
int count = 0;
|
||||
for (int pixel : texture.depth()) {
|
||||
count += (((pixel>>8)&0xFFFFFF) == 0xFFFFFF)?1:0;
|
||||
count += ((pixel&0xFF) == 0)?1:0;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
@@ -36,12 +36,27 @@ public class TextureUtils {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static final int WRITE_CHECK_STENCIL = 1;
|
||||
public static final int WRITE_CHECK_DEPTH = 2;
|
||||
public static final int WRITE_CHECK_ALPHA = 3;
|
||||
private static boolean wasPixelWritten(ColourDepthTextureData data, int mode, int index) {
|
||||
if (mode == WRITE_CHECK_STENCIL) {
|
||||
return (data.depth()[index]&0xFF)!=0;
|
||||
} else if (mode == WRITE_CHECK_DEPTH) {
|
||||
return (data.depth()[index]>>>8)!=((1<<24)-1);
|
||||
} else if (mode == WRITE_CHECK_ALPHA) {
|
||||
return ((data.colour()[index]>>>24)&0xff)!=0;
|
||||
}
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
public static final int DEPTH_MODE_AVG = 1;
|
||||
public static final int DEPTH_MODE_MAX = 2;
|
||||
public static final int DEPTH_MODE_MIN = 3;
|
||||
|
||||
|
||||
//Computes depth info based on written pixel data
|
||||
public static float computeDepth(ColourDepthTextureData texture, int mode) {
|
||||
public static float computeDepth(ColourDepthTextureData texture, int mode, int checkMode) {
|
||||
final var colourData = texture.colour();
|
||||
final var depthData = texture.depth();
|
||||
long a = 0;
|
||||
@@ -53,7 +68,7 @@ public class TextureUtils {
|
||||
a = Long.MIN_VALUE;
|
||||
}
|
||||
for (int i = 0; i < colourData.length; i++) {
|
||||
if ((colourData[i]&0xFF)==0) {
|
||||
if (!wasPixelWritten(texture, checkMode, i)) {
|
||||
continue;
|
||||
}
|
||||
int depth = depthData[i]>>>8;
|
||||
@@ -87,6 +102,74 @@ public class TextureUtils {
|
||||
}
|
||||
|
||||
private static float u2fdepth(int depth) {
|
||||
return (((float)depth)/(float)(1<<24));
|
||||
float depthF = (float) ((double)depth/((1<<24)-1));
|
||||
//https://registry.khronos.org/OpenGL-Refpages/gl4/html/glDepthRange.xhtml
|
||||
// due to this and the unsigned bullshit, i believe the depth value needs to get multiplied by 2
|
||||
depthF *= 2;
|
||||
if (depthF > 1.00001f) {
|
||||
throw new IllegalArgumentException("Depth greater than 1");
|
||||
}
|
||||
return depthF;
|
||||
}
|
||||
|
||||
|
||||
//NOTE: data goes from bottom left to top right (x first then y)
|
||||
public static int[] computeBounds(ColourDepthTextureData data, int checkMode) {
|
||||
final var depth = data.depth();
|
||||
//Compute x bounds first
|
||||
int minX = 0;
|
||||
minXCheck:
|
||||
do {
|
||||
for (int y = 0; y < data.height(); y++) {
|
||||
int idx = minX + (y * data.width());
|
||||
if (wasPixelWritten(data, checkMode, idx)) {
|
||||
break minXCheck;//pixel was written too so break from loop
|
||||
}
|
||||
}
|
||||
minX++;
|
||||
} while (minX != data.width());
|
||||
|
||||
int maxX = data.width()-1;
|
||||
maxXCheck:
|
||||
do {
|
||||
for (int y = data.height()-1; y!=-1; y--) {
|
||||
int idx = maxX + (y * data.width());
|
||||
if (wasPixelWritten(data, checkMode, idx)) {
|
||||
break maxXCheck;//pixel was written too so break from loop
|
||||
}
|
||||
}
|
||||
maxX--;
|
||||
} while (maxX != -1);
|
||||
maxX++;
|
||||
|
||||
|
||||
//Compute y bounds
|
||||
int minY = 0;
|
||||
minYCheck:
|
||||
do {
|
||||
for (int x = 0; x < data.width(); x++) {
|
||||
int idx = (minY * data.height()) + x;
|
||||
if (wasPixelWritten(data, checkMode, idx)) {
|
||||
break minYCheck;//pixel was written too
|
||||
}
|
||||
}
|
||||
minY++;
|
||||
} while (minY != data.height());
|
||||
|
||||
|
||||
int maxY = data.height()-1;
|
||||
maxYCheck:
|
||||
do {
|
||||
for (int x = data.width()-1; x!=-1; x--) {
|
||||
int idx = (maxY * data.height()) + x;
|
||||
if (wasPixelWritten(data, checkMode, idx)) {
|
||||
break maxYCheck;//pixel was written too so break from loop
|
||||
}
|
||||
}
|
||||
maxY--;
|
||||
} while (maxY != -1);
|
||||
maxY++;
|
||||
|
||||
return new int[]{minX, maxX, minY, maxY};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,11 @@ import me.cortex.zenith.client.core.gl.shader.ShaderType;
|
||||
import me.cortex.zenith.client.core.rendering.util.UploadStream;
|
||||
import me.cortex.zenith.client.mixin.joml.AccessFrustumIntersection;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.WallMountedBlock;
|
||||
import net.minecraft.block.enums.BlockFace;
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector3f;
|
||||
import org.lwjgl.opengl.GL11C;
|
||||
@@ -75,11 +78,13 @@ 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;
|
||||
}
|
||||
|
||||
//this.getModelManager().addEntry(this.frameId%(1<<15), Blocks.OAK_BUTTON.getDefaultState());
|
||||
|
||||
RenderLayer.getCutoutMipped().startDrawing();
|
||||
int oldActiveTexture = glGetInteger(GL_ACTIVE_TEXTURE);
|
||||
|
||||
Reference in New Issue
Block a user