From 75344defe3d346e5dfb07d947609e641e782e982 Mon Sep 17 00:00:00 2001 From: IMS212 Date: Thu, 7 Dec 2023 08:43:09 -0800 Subject: [PATCH] Fix entity shadows --- .../shadows/EntityRenderDispatcherMixin.java | 266 +++++------------- 1 file changed, 73 insertions(+), 193 deletions(-) diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/copyEntity/shadows/EntityRenderDispatcherMixin.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/copyEntity/shadows/EntityRenderDispatcherMixin.java index 93d46e7306..4d78b1de07 100644 --- a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/copyEntity/shadows/EntityRenderDispatcherMixin.java +++ b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/copyEntity/shadows/EntityRenderDispatcherMixin.java @@ -2,15 +2,11 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; +import me.jellysquid.mods.sodium.client.render.vertex.VertexConsumerUtils; import net.caffeinemc.mods.sodium.api.vertex.buffer.VertexBufferWriter; import net.caffeinemc.mods.sodium.api.vertex.format.common.ModelVertex; import net.caffeinemc.mods.sodium.api.util.ColorABGR; import net.caffeinemc.mods.sodium.api.math.MatrixHelper; -import net.coderbot.iris.compat.sodium.impl.vertex_format.entity_xhfp.EntityVertex; -import net.coderbot.iris.vertices.ImmediateState; -import net.coderbot.iris.vertices.NormI8; -import net.coderbot.iris.vertices.NormalHelper; -import net.irisshaders.iris.api.v0.IrisApi; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.client.renderer.texture.OverlayTexture; @@ -25,230 +21,114 @@ import org.joml.Matrix4f; import org.lwjgl.system.MemoryStack; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(EntityRenderDispatcher.class) public class EntityRenderDispatcherMixin { - @Unique - private static final int SHADOW_COLOR = ColorABGR.pack(1.0f, 1.0f, 1.0f); - - /** - * @author JellySquid - * @reason Reduce vertex assembly overhead for shadow rendering - */ - @Overwrite - private static void renderBlockShadow(PoseStack.Pose entry, VertexConsumer vertices, ChunkAccess chunk, LevelReader world, BlockPos pos, double x, double y, double z, float radius, float opacity) { - BlockPos blockPos = pos.below(); - BlockState blockState = world.getBlockState(blockPos); - - if (blockState.getRenderShape() == RenderShape.INVISIBLE || !blockState.isCollisionShapeFullBlock(world, blockPos)) { - return; - } - - var light = world.getMaxLocalRawBrightness(pos); - - if (light <= 3) { - return; - } - - VoxelShape voxelShape = blockState.getShape(world, blockPos); - - if (voxelShape.isEmpty()) { - return; - } - - float brightness = LightTexture.getBrightness(world.dimensionType(), light); - float alpha = (float) (((double) opacity - ((y - (double) pos.getY()) / 2.0)) * 0.5 * (double) brightness); + @Unique + private static final int SHADOW_COLOR = ColorABGR.pack(1.0f, 1.0f, 1.0f); + + /** + * @author JellySquid + * @reason Reduce vertex assembly overhead for shadow rendering + */ + @Inject(method = "renderBlockShadow", at = @At("HEAD"), cancellable = true) + private static void renderShadowPartFast(PoseStack.Pose entry, VertexConsumer vertices, ChunkAccess chunk, LevelReader world, BlockPos pos, double x, double y, double z, float radius, float opacity, CallbackInfo ci) { + var writer = VertexConsumerUtils.convertOrLog(vertices); + + if (writer == null) { + return; + } - if (alpha >= 0.0F) { - if (alpha > 1.0F) { - alpha = 1.0F; - } + ci.cancel(); - AABB box = voxelShape.bounds(); + BlockPos blockPos = pos.below(); + BlockState blockState = world.getBlockState(blockPos); - float minX = (float) ((pos.getX() + box.minX) - x); - float maxX = (float) ((pos.getX() + box.maxX) - x); + if (blockState.getRenderShape() == RenderShape.INVISIBLE || !blockState.isCollisionShapeFullBlock(world, blockPos)) { + return; + } - float minY = (float) ((pos.getY() + box.minY) - y); + var light = world.getMaxLocalRawBrightness(pos); - float minZ = (float) ((pos.getZ() + box.minZ) - z); - float maxZ = (float) ((pos.getZ() + box.maxZ) - z); + if (light <= 3) { + return; + } - renderShadowPart(entry, vertices, radius, alpha, minX, maxX, minY, minZ, maxZ); - } - } + VoxelShape voxelShape = blockState.getShape(world, blockPos); - @Unique - private static void renderShadowPart(PoseStack.Pose matrices, VertexConsumer vertices, float radius, float alpha, float minX, float maxX, float minY, float minZ, float maxZ) { - float size = 0.5F * (1.0F / radius); + if (voxelShape.isEmpty()) { + return; + } - float u1 = (-minX * size) + 0.5F; - float u2 = (-maxX * size) + 0.5F; + float brightness = LightTexture.getBrightness(world.dimensionType(), light); + float alpha = (float) (((double) opacity - ((y - (double) pos.getY()) / 2.0)) * 0.5 * (double) brightness); - float v1 = (-minZ * size) + 0.5F; - float v2 = (-maxZ * size) + 0.5F; + if (alpha >= 0.0F) { + if (alpha > 1.0F) { + alpha = 1.0F; + } - var matNormal = matrices.normal(); - var matPosition = matrices.pose(); + AABB box = voxelShape.bounds(); - var color = ColorABGR.withAlpha(SHADOW_COLOR, alpha); - var normal = MatrixHelper.transformNormal(matNormal, Direction.UP); + float minX = (float) ((pos.getX() + box.minX) - x); + float maxX = (float) ((pos.getX() + box.maxX) - x); - boolean extended = shouldBeExtended(); + float minY = (float) ((pos.getY() + box.minY) - y); - int tangent = 0; + float minZ = (float) ((pos.getZ() + box.minZ) - z); + float maxZ = (float) ((pos.getZ() + box.maxZ) - z); - if (extended) { - tangent = getTangent(normal, minX, minY, minZ, u1, v1, - minX, minY, maxZ, u1, v2, - maxX, minY, maxZ, u2, v2 - ); + renderShadowPart(entry, writer, radius, alpha, minX, maxX, minY, minZ, maxZ); } + } - float midU = (u1 + u2) / 2; - float midV = (v1 + v2) / 2; - - int stride = extended ? EntityVertex.STRIDE : ModelVertex.STRIDE; - - try (MemoryStack stack = MemoryStack.stackPush()) { - long buffer = stack.nmalloc(4 * stride); - long ptr = buffer; + @Unique + private static void renderShadowPart(PoseStack.Pose matrices, VertexBufferWriter writer, float radius, float alpha, float minX, float maxX, float minY, float minZ, float maxZ) { + float size = 0.5F * (1.0F / radius); - if (extended) { - writeShadowVertexIris(ptr, matPosition, minX, minY, minZ, u1, v1, color, midU, midV, normal, tangent); - ptr += stride; + float u1 = (-minX * size) + 0.5F; + float u2 = (-maxX * size) + 0.5F; - writeShadowVertexIris(ptr, matPosition, minX, minY, maxZ, u1, v2, color, midU, midV, normal, tangent); - ptr += stride; + float v1 = (-minZ * size) + 0.5F; + float v2 = (-maxZ * size) + 0.5F; - writeShadowVertexIris(ptr, matPosition, maxX, minY, maxZ, u2, v2, color, midU, midV, normal, tangent); - ptr += stride; + var matNormal = matrices.normal(); + var matPosition = matrices.pose(); - writeShadowVertexIris(ptr, matPosition, maxX, minY, minZ, u2, v1, color, midU, midV, normal, tangent); - ptr += stride; - } else { - writeShadowVertex(ptr, matPosition, minX, minY, minZ, u1, v1, color, normal); - ptr += stride; + var color = ColorABGR.withAlpha(SHADOW_COLOR, alpha); + var normal = MatrixHelper.transformNormal(matNormal, Direction.UP); - writeShadowVertex(ptr, matPosition, minX, minY, maxZ, u1, v2, color, normal); - ptr += stride; + try (MemoryStack stack = MemoryStack.stackPush()) { + long buffer = stack.nmalloc(4 * ModelVertex.STRIDE); + long ptr = buffer; - writeShadowVertex(ptr, matPosition, maxX, minY, maxZ, u2, v2, color, normal); - ptr += stride; + writeShadowVertex(ptr, matPosition, minX, minY, minZ, u1, v1, color, normal); + ptr += ModelVertex.STRIDE; - writeShadowVertex(ptr, matPosition, maxX, minY, minZ, u2, v1, color, normal); - ptr += stride; - } + writeShadowVertex(ptr, matPosition, minX, minY, maxZ, u1, v2, color, normal); + ptr += ModelVertex.STRIDE; - VertexBufferWriter.of(vertices) - .push(stack, buffer, 4, ModelVertex.FORMAT); - } - } + writeShadowVertex(ptr, matPosition, maxX, minY, maxZ, u2, v2, color, normal); + ptr += ModelVertex.STRIDE; - @Unique - private static void writeShadowVertex(long ptr, Matrix4f matPosition, float x, float y, float z, float u, float v, int color, int normal) { - // The transformed position vector - float xt = MatrixHelper.transformPositionX(matPosition, x, y, z); - float yt = MatrixHelper.transformPositionY(matPosition, x, y, z); - float zt = MatrixHelper.transformPositionZ(matPosition, x, y, z); + writeShadowVertex(ptr, matPosition, maxX, minY, minZ, u2, v1, color, normal); + ptr += ModelVertex.STRIDE; - ModelVertex.write(ptr, xt, yt, zt, color, u, v, LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, normal); - } + writer.push(stack, buffer, 4, ModelVertex.FORMAT); + } + } @Unique - private static void writeShadowVertexIris(long ptr, Matrix4f matPosition, float x, float y, float z, float u, float v, int color, float midU, float midV, int normal, int tangent) { + private static void writeShadowVertex(long ptr, Matrix4f matPosition, float x, float y, float z, float u, float v, int color, int normal) { // The transformed position vector float xt = MatrixHelper.transformPositionX(matPosition, x, y, z); float yt = MatrixHelper.transformPositionY(matPosition, x, y, z); float zt = MatrixHelper.transformPositionZ(matPosition, x, y, z); - EntityVertex.write(ptr, xt, yt, zt, color, u, v, midU, midV, OverlayTexture.NO_OVERLAY, LightTexture.FULL_BRIGHT, normal, tangent); - } - - private static boolean shouldBeExtended() { - return IrisApi.getInstance().isShaderPackInUse() && ImmediateState.renderWithExtendedVertexFormat; - } - - private static int getTangent(int normal, float x0, float y0, float z0, float u0, float v0, float x1, float y1, float z1, float u1, float v1, float x2, float y2, float z2, float u2, float v2) { - // Capture all of the relevant vertex positions - - float normalX = NormI8.unpackX(normal); - float normalY = NormI8.unpackY(normal); - float normalZ = NormI8.unpackZ(normal); - - float edge1x = x1 - x0; - float edge1y = y1 - y0; - float edge1z = z1 - z0; - - float edge2x = x2 - x0; - float edge2y = y2 - y0; - float edge2z = z2 - z0; - - float deltaU1 = u1 - u0; - float deltaV1 = v1 - v0; - float deltaU2 = u2 - u0; - float deltaV2 = v2 - v0; - - float fdenom = deltaU1 * deltaV2 - deltaU2 * deltaV1; - float f; - - if (fdenom == 0.0) { - f = 1.0f; - } else { - f = 1.0f / fdenom; - } - - float tangentx = f * (deltaV2 * edge1x - deltaV1 * edge2x); - float tangenty = f * (deltaV2 * edge1y - deltaV1 * edge2y); - float tangentz = f * (deltaV2 * edge1z - deltaV1 * edge2z); - float tcoeff = rsqrt(tangentx * tangentx + tangenty * tangenty + tangentz * tangentz); - tangentx *= tcoeff; - tangenty *= tcoeff; - tangentz *= tcoeff; - - float bitangentx = f * (-deltaU2 * edge1x + deltaU1 * edge2x); - float bitangenty = f * (-deltaU2 * edge1y + deltaU1 * edge2y); - float bitangentz = f * (-deltaU2 * edge1z + deltaU1 * edge2z); - float bitcoeff = rsqrt(bitangentx * bitangentx + bitangenty * bitangenty + bitangentz * bitangentz); - bitangentx *= bitcoeff; - bitangenty *= bitcoeff; - bitangentz *= bitcoeff; - - // predicted bitangent = tangent × normal - // Compute the determinant of the following matrix to get the cross product - // i j k - // tx ty tz - // nx ny nz - - // Be very careful when writing out complex multi-step calculations - // such as vector cross products! The calculation for pbitangentz - // used to be broken because it multiplied values in the wrong order. - - float pbitangentx = tangenty * normalZ - tangentz * normalY; - float pbitangenty = tangentz * normalX - tangentx * normalZ; - float pbitangentz = tangentx * normalY - tangenty * normalX; - - float dot = (bitangentx * pbitangentx) + (bitangenty * pbitangenty) + (bitangentz * pbitangentz); - float tangentW; - - if (dot < 0) { - tangentW = -1.0F; - } else { - tangentW = 1.0F; - } - - return NormI8.pack(tangentx, tangenty, tangentz, tangentW); - } - - private static float rsqrt(float value) { - if (value == 0.0f) { - // You heard it here first, folks: 1 divided by 0 equals 1 - // In actuality, this is a workaround for normalizing a zero length vector (leaving it as zero length) - return 1.0f; - } else { - return (float) (1.0 / Math.sqrt(value)); - } + ModelVertex.write(ptr, xt, yt, zt, color, u, v, LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, normal); } }