diff --git a/buildscript/src/main/java/Buildscript.java b/buildscript/src/main/java/Buildscript.java index 0f1f481fff..1e66ee1b6c 100644 --- a/buildscript/src/main/java/Buildscript.java +++ b/buildscript/src/main/java/Buildscript.java @@ -100,6 +100,7 @@ public void getModDependencies(ModDependencyCollector d) { jij(d.addMaven(FabricMaven.URL, new MavenId(FabricMaven.GROUP_ID + ".fabric-api", "fabric-key-binding-api-v1", "1.0.23+aaaf9d332d"), ModDependencyFlag.COMPILE, ModDependencyFlag.RUNTIME)); jij(d.addMaven(Maven.MAVEN_CENTRAL, new MavenId("io.github.douira:glsl-transformer:2.0.0-pre13"), ModDependencyFlag.COMPILE, ModDependencyFlag.RUNTIME)); + jij(d.addMaven(Maven.MAVEN_CENTRAL, new MavenId("net.jodah:expiringmap:0.5.10"), ModDependencyFlag.COMPILE, ModDependencyFlag.RUNTIME)); jij(d.addMaven(Maven.MAVEN_CENTRAL, new MavenId("org.antlr:antlr4-runtime:4.11.1"), ModDependencyFlag.COMPILE, ModDependencyFlag.RUNTIME)); d.addMaven("https://api.modrinth.com/maven", new MavenId("maven.modrinth", "distanthorizons", "2.0.0-a-1.19.4"), ModDependencyFlag.COMPILE); diff --git a/src/main/java/net/coderbot/iris/gl/shader/ProgramCreator.java b/src/main/java/net/coderbot/iris/gl/shader/ProgramCreator.java index 5a18b09465..dd588dd469 100644 --- a/src/main/java/net/coderbot/iris/gl/shader/ProgramCreator.java +++ b/src/main/java/net/coderbot/iris/gl/shader/ProgramCreator.java @@ -21,6 +21,7 @@ public static int create(String name, GlShader... shaders) { GlStateManager._glBindAttribLocation(program, 12, "mc_midTexCoord"); GlStateManager._glBindAttribLocation(program, 13, "at_tangent"); GlStateManager._glBindAttribLocation(program, 14, "at_midBlock"); + GlStateManager._glBindAttribLocation(program, 14, "at_velocity"); GlStateManager._glBindAttribLocation(program, 0, "Position"); GlStateManager._glBindAttribLocation(program, 1, "UV0"); diff --git a/src/main/java/net/coderbot/iris/mixin/MixinLevelRenderer.java b/src/main/java/net/coderbot/iris/mixin/MixinLevelRenderer.java index 29e2273e12..283c3301cc 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinLevelRenderer.java +++ b/src/main/java/net/coderbot/iris/mixin/MixinLevelRenderer.java @@ -122,6 +122,9 @@ public class MixinLevelRenderer { private void iris$endLevelRender(PoseStack poseStack, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo callback) { HandRenderer.INSTANCE.renderTranslucent(poseStack, tickDelta, camera, gameRenderer, pipeline); Minecraft.getInstance().getProfiler().popPush("iris_final"); + CapturedRenderingState.INSTANCE.velocityInfoEdit = new PoseStack(); + CapturedRenderingState.INSTANCE.velocityInfoEdit.mulPose(Axis.XP.rotationDegrees(camera.getXRot())); + CapturedRenderingState.INSTANCE.velocityInfoEdit.mulPose(Axis.YP.rotationDegrees(camera.getYRot() + 180.0F)); pipeline.finalizeLevelRendering(); pipeline = null; diff --git a/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinBlockEntityRenderDispatcher.java b/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinBlockEntityRenderDispatcher.java index d0dcb19532..451314aeb4 100644 --- a/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinBlockEntityRenderDispatcher.java +++ b/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinBlockEntityRenderDispatcher.java @@ -57,6 +57,7 @@ public class MixinBlockEntityRenderDispatcher { int intId = blockStateIds.getOrDefault(state, -1); CapturedRenderingState.INSTANCE.setCurrentBlockEntity(intId); + CapturedRenderingState.INSTANCE.setUniqueEntityId(blockEntity.getBlockPos().getX() + blockEntity.getBlockPos().getY() + blockEntity.getType().hashCode()); return type -> bufferSource.getBuffer(OuterWrappedRenderType.wrapExactlyOnce("iris:is_block_entity", type, BlockEntityRenderStateShard.INSTANCE)); @@ -67,5 +68,7 @@ public class MixinBlockEntityRenderDispatcher { private void iris$afterRender(BlockEntity blockEntity, float tickDelta, PoseStack matrix, MultiBufferSource bufferSource, CallbackInfo ci) { CapturedRenderingState.INSTANCE.setCurrentBlockEntity(0); + CapturedRenderingState.INSTANCE.setUniqueEntityId(0); + } } diff --git a/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinEntityRenderDispatcher.java b/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinEntityRenderDispatcher.java index 319d3bcf23..8cc6dcb523 100644 --- a/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinEntityRenderDispatcher.java +++ b/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinEntityRenderDispatcher.java @@ -14,12 +14,15 @@ import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderStateShard; import net.minecraft.client.renderer.entity.EntityRenderDispatcher; +import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.monster.ZombieVillager; +import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyVariable; @@ -31,11 +34,27 @@ * rendered. */ @Mixin(EntityRenderDispatcher.class) -public class MixinEntityRenderDispatcher { +public abstract class MixinEntityRenderDispatcher { + @Shadow + public abstract EntityRenderer getRenderer(T pEntityRenderDispatcher0); + // Inject after MatrixStack#push since at this point we know that most cancellation checks have already passed. @ModifyVariable(method = "render", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;pushPose()V", shift = At.Shift.AFTER), allow = 1, require = 1) - private MultiBufferSource iris$beginEntityRender(MultiBufferSource bufferSource, Entity entity) { + private MultiBufferSource iris$beginEntityRender(MultiBufferSource bufferSource, Entity entity, + double pDouble1, + double pDouble2, + double pDouble3, + float pFloat4, + float pFloat5) { + + Vec3 lvVec314 = this.getRenderer(entity).getRenderOffset(entity, pFloat5); + double lvDouble15 = pDouble1 + lvVec314.x(); + double lvDouble17 = pDouble2 + lvVec314.y(); + double lvDouble19 = pDouble3 + lvVec314.z(); + CapturedRenderingState.INSTANCE.velocityInfoEdit.pushPose(); + CapturedRenderingState.INSTANCE.velocityInfoEdit.translate(lvDouble15, lvDouble17, lvDouble19); + if (!(bufferSource instanceof Groupable)) { // Fully batched entity rendering is not being used, do not use this wrapper!!! return bufferSource; @@ -43,6 +62,7 @@ public class MixinEntityRenderDispatcher { Object2IntFunction entityIds = BlockRenderingSettings.INSTANCE.getEntityIds(); + if (entityIds == null) { return bufferSource; } @@ -57,6 +77,7 @@ public class MixinEntityRenderDispatcher { } CapturedRenderingState.INSTANCE.setCurrentEntity(intId); + CapturedRenderingState.INSTANCE.setUniqueEntityId(entity.getId()); return type -> bufferSource.getBuffer(OuterWrappedRenderType.wrapExactlyOnce("iris:is_entity", type, EntityRenderStateShard.INSTANCE)); @@ -69,6 +90,8 @@ public class MixinEntityRenderDispatcher { PoseStack poseStack, MultiBufferSource bufferSource, int light, CallbackInfo ci) { CapturedRenderingState.INSTANCE.setCurrentEntity(0); + CapturedRenderingState.INSTANCE.setUniqueEntityId(0); + CapturedRenderingState.INSTANCE.velocityInfoEdit.popPose(); CapturedRenderingState.INSTANCE.setCurrentRenderedItem(0); } } diff --git a/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinEntityRenderer.java b/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinEntityRenderer.java new file mode 100644 index 0000000000..f40cef3e15 --- /dev/null +++ b/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinEntityRenderer.java @@ -0,0 +1,29 @@ +package net.coderbot.iris.mixin.entity_render_context; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.coderbot.iris.uniforms.CapturedRenderingState; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.EntityRenderDispatcher; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.Entity; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(EntityRenderer.class) +public class MixinEntityRenderer { + @Shadow + @Final + protected EntityRenderDispatcher entityRenderDispatcher; + + @Inject(method = "renderNameTag", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getNameTagOffsetY()F")) + private void iris$editVelocityInfo(Entity pEntityRenderer0, Component pComponent1, PoseStack pPoseStack2, MultiBufferSource pMultiBufferSource3, int pInt4, CallbackInfo ci) { + CapturedRenderingState.INSTANCE.velocityInfoEdit.translate(0.0F, pEntityRenderer0.getNameTagOffsetY(), 0.0F); + CapturedRenderingState.INSTANCE.velocityInfoEdit.mulPose(this.entityRenderDispatcher.cameraOrientation()); + CapturedRenderingState.INSTANCE.velocityInfoEdit.scale(-0.025F, -0.025F, 0.025F); + } +} diff --git a/src/main/java/net/coderbot/iris/mixin/vertices/MixinBufferBuilder.java b/src/main/java/net/coderbot/iris/mixin/vertices/MixinBufferBuilder.java index 5b8ae15471..0c23cf7359 100644 --- a/src/main/java/net/coderbot/iris/mixin/vertices/MixinBufferBuilder.java +++ b/src/main/java/net/coderbot/iris/mixin/vertices/MixinBufferBuilder.java @@ -43,6 +43,9 @@ public abstract class MixinBufferBuilder extends DefaultedVertexConsumer impleme @Unique private boolean iris$isTerrain = false; + @Unique + private boolean iris$isParticle = false; + @Unique private int vertexCount; @@ -103,6 +106,8 @@ public abstract class MixinBufferBuilder extends DefaultedVertexConsumer impleme @Shadow public abstract void nextElement(); + @Shadow public abstract void putFloat(int pBufferBuilder0, float pFloat1); + @Override public void iris$beginWithoutExtending(VertexFormat.Mode drawMode, VertexFormat vertexFormat) { iris$shouldNotExtend = true; @@ -113,7 +118,7 @@ public abstract class MixinBufferBuilder extends DefaultedVertexConsumer impleme @Inject(method = "begin", at = @At("HEAD")) private void iris$onBegin(VertexFormat.Mode drawMode, VertexFormat format, CallbackInfo ci) { boolean shouldExtend = (!iris$shouldNotExtend) && BlockRenderingSettings.INSTANCE.shouldUseExtendedVertexFormat(); - extending = shouldExtend && (format == DefaultVertexFormat.BLOCK || format == DefaultVertexFormat.NEW_ENTITY + extending = shouldExtend && (format == DefaultVertexFormat.BLOCK || format == DefaultVertexFormat.NEW_ENTITY || format == DefaultVertexFormat.PARTICLE || format == DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP); vertexCount = 0; @@ -128,12 +133,20 @@ public abstract class MixinBufferBuilder extends DefaultedVertexConsumer impleme if (format == DefaultVertexFormat.BLOCK) { this.switchFormat(IrisVertexFormats.TERRAIN); this.iris$isTerrain = true; + this.iris$isParticle = false; + } else if (format == DefaultVertexFormat.PARTICLE) { + this.switchFormat(IrisVertexFormats.PARTICLES); + this.iris$isTerrain = false; + this.iris$isParticle = true; } else if (format == DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP) { this.switchFormat(IrisVertexFormats.GLYPH); this.iris$isTerrain = false; + injectNormalAndUV1 = true; + this.iris$isParticle = false; } else { this.switchFormat(IrisVertexFormats.ENTITY); this.iris$isTerrain = false; + this.iris$isParticle = false; } this.currentElement = this.format.getElements().get(0); } @@ -151,12 +164,21 @@ public abstract class MixinBufferBuilder extends DefaultedVertexConsumer impleme if (format == DefaultVertexFormat.BLOCK) { this.switchFormat(IrisVertexFormats.TERRAIN); this.iris$isTerrain = true; + this.iris$isParticle = false; + } else if (format == DefaultVertexFormat.PARTICLE) { + this.switchFormat(IrisVertexFormats.PARTICLES); + this.iris$isTerrain = false; + this.iris$isParticle = true; } else if (format == DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP) { this.switchFormat(IrisVertexFormats.GLYPH); this.iris$isTerrain = false; + injectNormalAndUV1 = true; + + this.iris$isParticle = false; } else { this.switchFormat(IrisVertexFormats.ENTITY); this.iris$isTerrain = false; + this.iris$isParticle = false; } } return arg; @@ -187,6 +209,15 @@ public abstract class MixinBufferBuilder extends DefaultedVertexConsumer impleme return; } + if (iris$isParticle) { + this.putFloat(0, 0); + this.putFloat(4, 0); + this.putFloat(8, 0); + this.nextElement(); + vertexCount++; + return; + } + if (injectNormalAndUV1 && currentElement == DefaultVertexFormat.ELEMENT_NORMAL) { this.putInt(0, 0); this.nextElement(); @@ -206,20 +237,26 @@ public abstract class MixinBufferBuilder extends DefaultedVertexConsumer impleme this.nextElement(); // MID_TEXTURE_ELEMENT - this.putFloat(0, 0); - this.putFloat(4, 0); + this.putShort(0, (short) 0); + this.putShort(2, (short) 0); this.nextElement(); // TANGENT_ELEMENT this.putInt(0, 0); this.nextElement(); if (iris$isTerrain) { // MID_BLOCK_ELEMENT - int posIndex = this.nextElementByte - 48; + int posIndex = this.nextElementByte - 44; float x = buffer.getFloat(posIndex); float y = buffer.getFloat(posIndex + 4); float z = buffer.getFloat(posIndex + 8); this.putInt(0, ExtendedDataHelper.computeMidBlock(x, y, z, currentLocalPosX, currentLocalPosY, currentLocalPosZ)); this.nextElement(); + } else { + // VELOCITY_ELEMENT + this.putFloat(0, 0); + this.putFloat(4, 0); + this.putFloat(8, 0); + this.nextElement(); } vertexCount++; @@ -229,6 +266,11 @@ public abstract class MixinBufferBuilder extends DefaultedVertexConsumer impleme } } + @Unique + private static short encodeTexture(float value) { + return (short) (Math.min(0.99999997F, value) * 65536); + } + @Unique private void fillExtendedData(int vertexAmount) { vertexCount = 0; @@ -253,17 +295,20 @@ private void fillExtendedData(int vertexAmount) { int normalOffset; int tangentOffset; if (iris$isTerrain) { - midUOffset = 16; - midVOffset = 12; - normalOffset = 24; + midUOffset = 12; + midVOffset = 10; + normalOffset = 20; tangentOffset = 8; } else { - midUOffset = 14; - midVOffset = 10; - normalOffset = 24; - tangentOffset = 6; + midUOffset = 20; + midVOffset = 18; + normalOffset = 28; + tangentOffset = 16; } + short midUFinal = encodeTexture(midU); + short midVFinal = encodeTexture(midV); + if (vertexAmount == 3) { // NormalHelper.computeFaceNormalTri(normal, polygon); // Removed to enable smooth shaded triangles. Mods rendering triangles with bad normals need to recalculate their normals manually or otherwise shading might be inconsistent. @@ -272,8 +317,8 @@ private void fillExtendedData(int vertexAmount) { int tangent = NormalHelper.computeTangentSmooth(NormI8.unpackX(packedNormal), NormI8.unpackY(packedNormal), NormI8.unpackZ(packedNormal), polygon); - buffer.putFloat(nextElementByte - midUOffset - stride * vertex, midU); - buffer.putFloat(nextElementByte - midVOffset - stride * vertex, midV); + buffer.putShort(nextElementByte - midUOffset - stride * vertex, midUFinal); + buffer.putShort(nextElementByte - midVOffset - stride * vertex, midVFinal); buffer.putInt(nextElementByte - tangentOffset - stride * vertex, tangent); } } else { @@ -282,8 +327,8 @@ private void fillExtendedData(int vertexAmount) { int tangent = NormalHelper.computeTangent(normal.x, normal.y, normal.z, polygon); for (int vertex = 0; vertex < vertexAmount; vertex++) { - buffer.putFloat(nextElementByte - midUOffset - stride * vertex, midU); - buffer.putFloat(nextElementByte - midVOffset - stride * vertex, midV); + buffer.putShort(nextElementByte - midUOffset - stride * vertex, midUFinal); + buffer.putShort(nextElementByte - midVOffset - stride * vertex, midVFinal); buffer.putInt(nextElementByte - normalOffset - stride * vertex, packedNormal); buffer.putInt(nextElementByte - tangentOffset - stride * vertex, tangent); } diff --git a/src/main/java/net/coderbot/iris/mixin/vertices/MixinVertexFormat.java b/src/main/java/net/coderbot/iris/mixin/vertices/MixinVertexFormat.java index ce59b40cea..e35c016899 100644 --- a/src/main/java/net/coderbot/iris/mixin/vertices/MixinVertexFormat.java +++ b/src/main/java/net/coderbot/iris/mixin/vertices/MixinVertexFormat.java @@ -21,6 +21,10 @@ public class MixinVertexFormat { if ((Object) this == DefaultVertexFormat.BLOCK) { IrisVertexFormats.TERRAIN.setupBufferState(); + ci.cancel(); + } else if ((Object) this == DefaultVertexFormat.PARTICLE) { + IrisVertexFormats.PARTICLES.setupBufferState(); + ci.cancel(); } else if ((Object) this == DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP) { IrisVertexFormats.GLYPH.setupBufferState(); @@ -40,6 +44,10 @@ public class MixinVertexFormat { if ((Object) this == DefaultVertexFormat.BLOCK) { IrisVertexFormats.TERRAIN.clearBufferState(); + ci.cancel(); + } else if ((Object) this == DefaultVertexFormat.PARTICLE) { + IrisVertexFormats.PARTICLES.clearBufferState(); + ci.cancel(); } else if ((Object) this == DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP) { IrisVertexFormats.GLYPH.clearBufferState(); diff --git a/src/main/java/net/coderbot/iris/pipeline/HandRenderer.java b/src/main/java/net/coderbot/iris/pipeline/HandRenderer.java index adfda3b805..d9c78d28b5 100644 --- a/src/main/java/net/coderbot/iris/pipeline/HandRenderer.java +++ b/src/main/java/net/coderbot/iris/pipeline/HandRenderer.java @@ -87,6 +87,8 @@ public void renderSolid(PoseStack poseStack, float tickDelta, Camera camera, Gam renderingSolid = true; + CapturedRenderingState.INSTANCE.setUniqueEntityId(Minecraft.getInstance().player.getId()); + gameRenderer.itemInHandRenderer.renderHandsWithItems(tickDelta, poseStack, bufferSource.getUnflushableWrapper(), Minecraft.getInstance().player, Minecraft.getInstance().getEntityRenderDispatcher().getPackedLightCoords(camera.getEntity(), tickDelta)); Minecraft.getInstance().getProfiler().pop(); @@ -102,6 +104,8 @@ public void renderSolid(PoseStack poseStack, float tickDelta, Camera camera, Gam pipeline.setPhase(WorldRenderingPhase.NONE); + CapturedRenderingState.INSTANCE.setUniqueEntityId(0); + ACTIVE = false; } @@ -120,6 +124,8 @@ public void renderTranslucent(PoseStack poseStack, float tickDelta, Camera camer setupGlState(gameRenderer, camera, poseStack, tickDelta); + CapturedRenderingState.INSTANCE.setUniqueEntityId(Minecraft.getInstance().player.getId()); + gameRenderer.itemInHandRenderer.renderHandsWithItems(tickDelta, poseStack, bufferSource, Minecraft.getInstance().player, Minecraft.getInstance().getEntityRenderDispatcher().getPackedLightCoords(camera.getEntity(), tickDelta)); poseStack.popPose(); @@ -132,6 +138,8 @@ public void renderTranslucent(PoseStack poseStack, float tickDelta, Camera camer pipeline.setPhase(WorldRenderingPhase.NONE); + CapturedRenderingState.INSTANCE.setUniqueEntityId(0); + ACTIVE = false; } diff --git a/src/main/java/net/coderbot/iris/pipeline/newshader/ShaderKey.java b/src/main/java/net/coderbot/iris/pipeline/newshader/ShaderKey.java index 9044bdaac8..f37ae23a3b 100644 --- a/src/main/java/net/coderbot/iris/pipeline/newshader/ShaderKey.java +++ b/src/main/java/net/coderbot/iris/pipeline/newshader/ShaderKey.java @@ -45,9 +45,9 @@ public enum ShaderKey { LIGHTNING (ProgramId.Entities, AlphaTests.OFF, DefaultVertexFormat.POSITION_COLOR, FogMode.PER_VERTEX, LightingModel.FULLBRIGHT), LEASH (ProgramId.Basic, AlphaTests.OFF, DefaultVertexFormat.POSITION_COLOR_LIGHTMAP, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), TEXT_BG (ProgramId.EntitiesTrans,AlphaTests.ONE_TENTH_ALPHA,DefaultVertexFormat.POSITION_COLOR_LIGHTMAP, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), - PARTICLES (ProgramId.Particles, AlphaTests.ONE_TENTH_ALPHA, DefaultVertexFormat.PARTICLE, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), - PARTICLES_TRANS (ProgramId.ParticlesTrans,AlphaTests.ONE_TENTH_ALPHA,DefaultVertexFormat.PARTICLE, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), - WEATHER (ProgramId.Weather, AlphaTests.ONE_TENTH_ALPHA, DefaultVertexFormat.PARTICLE, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), + PARTICLES (ProgramId.Particles, AlphaTests.ONE_TENTH_ALPHA, IrisVertexFormats.PARTICLES, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), + PARTICLES_TRANS (ProgramId.ParticlesTrans,AlphaTests.ONE_TENTH_ALPHA,IrisVertexFormats.PARTICLES, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), + WEATHER (ProgramId.Weather, AlphaTests.ONE_TENTH_ALPHA, IrisVertexFormats.PARTICLES, FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), CRUMBLING (ProgramId.DamagedBlock,AlphaTests.ONE_TENTH_ALPHA, IrisVertexFormats.TERRAIN, FogMode.OFF, LightingModel.LIGHTMAP ), TEXT (ProgramId.EntitiesTrans,AlphaTests.ONE_TENTH_ALPHA,IrisVertexFormats.GLYPH , FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), TEXT_INTENSITY (ProgramId.EntitiesTrans,AlphaTests.ONE_TENTH_ALPHA,IrisVertexFormats.GLYPH , FogMode.PER_VERTEX, LightingModel.LIGHTMAP ), @@ -73,7 +73,7 @@ public enum ShaderKey { SHADOW_LINES (ProgramId.Shadow, AlphaTests.OFF, DefaultVertexFormat.POSITION_COLOR_NORMAL, FogMode.OFF, LightingModel.LIGHTMAP ), SHADOW_LEASH (ProgramId.Shadow, AlphaTests.OFF, DefaultVertexFormat.POSITION_COLOR_LIGHTMAP, FogMode.OFF, LightingModel.LIGHTMAP ), SHADOW_LIGHTNING (ProgramId.Shadow, AlphaTests.OFF, DefaultVertexFormat.POSITION_COLOR, FogMode.OFF, LightingModel.FULLBRIGHT), - SHADOW_PARTICLES (ProgramId.Shadow, AlphaTests.ONE_TENTH_ALPHA, DefaultVertexFormat.PARTICLE, FogMode.OFF, LightingModel.LIGHTMAP ), + SHADOW_PARTICLES (ProgramId.Shadow, AlphaTests.ONE_TENTH_ALPHA, IrisVertexFormats.PARTICLES, FogMode.OFF, LightingModel.LIGHTMAP ), SHADOW_TEXT (ProgramId.Shadow, AlphaTests.NON_ZERO_ALPHA, IrisVertexFormats.GLYPH , FogMode.OFF, LightingModel.LIGHTMAP ), SHADOW_TEXT_BG (ProgramId.Shadow, AlphaTests.NON_ZERO_ALPHA, DefaultVertexFormat.POSITION_COLOR_LIGHTMAP, FogMode.OFF , LightingModel.LIGHTMAP ), SHADOW_TEXT_INTENSITY (ProgramId.Shadow, AlphaTests.NON_ZERO_ALPHA, IrisVertexFormats.GLYPH , FogMode.OFF, LightingModel.LIGHTMAP ); diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/VanillaTransformer.java b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/VanillaTransformer.java index 460ab8c680..d99f26f003 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/VanillaTransformer.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/VanillaTransformer.java @@ -26,6 +26,8 @@ public static void transform( CommonTransformer.transform(t, tree, root, parameters, false); + SodiumTransformer.replaceMidTexCoord(t, tree, root, (1.0f / 65536)); + if (parameters.type.glShaderType == ShaderType.VERTEX) { // Alias of gl_MultiTexCoord1 on 1.15+ for OptiFine // See https://github.com/IrisShaders/Iris/issues/1149 diff --git a/src/main/java/net/coderbot/iris/uniforms/CapturedRenderingState.java b/src/main/java/net/coderbot/iris/uniforms/CapturedRenderingState.java index 40e0301ea7..1ecbaacc9f 100644 --- a/src/main/java/net/coderbot/iris/uniforms/CapturedRenderingState.java +++ b/src/main/java/net/coderbot/iris/uniforms/CapturedRenderingState.java @@ -1,5 +1,6 @@ package net.coderbot.iris.uniforms; +import com.mojang.blaze3d.vertex.PoseStack; import net.coderbot.iris.gl.state.ValueUpdateNotifier; import net.minecraft.client.Minecraft; import org.joml.Matrix4f; @@ -12,6 +13,7 @@ public class CapturedRenderingState { private Matrix4f gbufferModelView; private Matrix4f gbufferProjection; + public PoseStack velocityInfoEdit= new PoseStack(); private Vector3d fogColor; private float fogDensity; private float darknessLightFactor; @@ -19,6 +21,7 @@ public class CapturedRenderingState { private int currentRenderedBlockEntity; private int currentRenderedEntity = -1; + private int uniqueEntityId = -1; private int currentRenderedItem = -1; private float currentAlphaTest; @@ -118,4 +121,12 @@ public float getCloudTime() { public void setCloudTime(float cloudTime) { this.cloudTime = cloudTime; } + + public int getUniqueEntityId() { + return uniqueEntityId; + } + + public void setUniqueEntityId(int id) { + uniqueEntityId = id; + } } diff --git a/src/main/java/net/coderbot/iris/vertices/IrisVertexFormats.java b/src/main/java/net/coderbot/iris/vertices/IrisVertexFormats.java index ad21c5aaf8..4f909c8b11 100644 --- a/src/main/java/net/coderbot/iris/vertices/IrisVertexFormats.java +++ b/src/main/java/net/coderbot/iris/vertices/IrisVertexFormats.java @@ -13,23 +13,27 @@ public class IrisVertexFormats { public static final VertexFormatElement TANGENT_ELEMENT; public static final VertexFormatElement MID_BLOCK_ELEMENT; public static final VertexFormatElement PADDING_SHORT; + public static final VertexFormatElement VELOCITY_FLOAT; public static final VertexFormat TERRAIN; public static final VertexFormat ENTITY; public static final VertexFormat GLYPH; public static final VertexFormat CLOUDS; + public static final VertexFormat PARTICLES; static { ENTITY_ELEMENT = new VertexFormatElement(11, VertexFormatElement.Type.SHORT, VertexFormatElement.Usage.GENERIC, 2); - ENTITY_ID_ELEMENT = new VertexFormatElement(11, VertexFormatElement.Type.USHORT, VertexFormatElement.Usage.UV, 3); - MID_TEXTURE_ELEMENT = new VertexFormatElement(12, VertexFormatElement.Type.FLOAT, VertexFormatElement.Usage.GENERIC, 2); + ENTITY_ID_ELEMENT = new VertexFormatElement(11, VertexFormatElement.Type.USHORT, VertexFormatElement.Usage.UV, 4); + MID_TEXTURE_ELEMENT = new VertexFormatElement(12, VertexFormatElement.Type.USHORT, VertexFormatElement.Usage.GENERIC, 2); TANGENT_ELEMENT = new VertexFormatElement(13, VertexFormatElement.Type.BYTE, VertexFormatElement.Usage.GENERIC, 4); MID_BLOCK_ELEMENT = new VertexFormatElement(14, VertexFormatElement.Type.BYTE, VertexFormatElement.Usage.GENERIC, 3); PADDING_SHORT = new VertexFormatElement(1, VertexFormatElement.Type.SHORT, VertexFormatElement.Usage.PADDING, 1); + VELOCITY_FLOAT = new VertexFormatElement(14, VertexFormatElement.Type.FLOAT, VertexFormatElement.Usage.GENERIC, 3); ImmutableMap.Builder terrainElements = ImmutableMap.builder(); ImmutableMap.Builder entityElements = ImmutableMap.builder(); ImmutableMap.Builder glyphElements = ImmutableMap.builder(); + ImmutableMap.Builder particleElements = ImmutableMap.builder(); ImmutableMap.Builder cloudsElements = ImmutableMap.builder(); terrainElements.put("Position", DefaultVertexFormat.ELEMENT_POSITION); // 12 @@ -39,10 +43,10 @@ public class IrisVertexFormats { terrainElements.put("Normal", DefaultVertexFormat.ELEMENT_NORMAL); // 31 terrainElements.put("Padding", DefaultVertexFormat.ELEMENT_PADDING); // 32 terrainElements.put("mc_Entity", ENTITY_ELEMENT); // 36 - terrainElements.put("mc_midTexCoord", MID_TEXTURE_ELEMENT); // 44 - terrainElements.put("at_tangent", TANGENT_ELEMENT); // 48 - terrainElements.put("at_midBlock", MID_BLOCK_ELEMENT); // 51 - terrainElements.put("Padding2", DefaultVertexFormat.ELEMENT_PADDING); // 52 + terrainElements.put("mc_midTexCoord", MID_TEXTURE_ELEMENT); // 40 + terrainElements.put("at_tangent", TANGENT_ELEMENT); // 44 + terrainElements.put("at_midBlock", MID_BLOCK_ELEMENT); // 47 + terrainElements.put("Padding2", DefaultVertexFormat.ELEMENT_PADDING); // 48 entityElements.put("Position", DefaultVertexFormat.ELEMENT_POSITION); // 12 entityElements.put("Color", DefaultVertexFormat.ELEMENT_COLOR); // 16 @@ -52,9 +56,15 @@ public class IrisVertexFormats { entityElements.put("Normal", DefaultVertexFormat.ELEMENT_NORMAL); // 35 entityElements.put("Padding", DefaultVertexFormat.ELEMENT_PADDING); // 36 entityElements.put("iris_Entity", ENTITY_ID_ELEMENT); // 40 - entityElements.put("mc_midTexCoord", MID_TEXTURE_ELEMENT); // 48 - entityElements.put("at_tangent", TANGENT_ELEMENT); // 52 - entityElements.put("Padding2", PADDING_SHORT); // 52 + entityElements.put("mc_midTexCoord", MID_TEXTURE_ELEMENT); // 44 + entityElements.put("at_tangent", TANGENT_ELEMENT); // 48 + entityElements.put("at_velocity", VELOCITY_FLOAT); // 60 + + particleElements.put("Position", DefaultVertexFormat.ELEMENT_POSITION); // 12 + particleElements.put("UV0", DefaultVertexFormat.ELEMENT_UV0); // 16 + particleElements.put("Color", DefaultVertexFormat.ELEMENT_COLOR); // 24 + particleElements.put("UV2", DefaultVertexFormat.ELEMENT_UV2); // 28 + particleElements.put("at_velocity", VELOCITY_FLOAT); // 40 glyphElements.put("Position", DefaultVertexFormat.ELEMENT_POSITION); // 12 glyphElements.put("Color", DefaultVertexFormat.ELEMENT_COLOR); // 16 @@ -65,7 +75,8 @@ public class IrisVertexFormats { glyphElements.put("iris_Entity", ENTITY_ID_ELEMENT); // 38 glyphElements.put("mc_midTexCoord", MID_TEXTURE_ELEMENT); // 46 glyphElements.put("at_tangent", TANGENT_ELEMENT); // 50 - glyphElements.put("Padding2", PADDING_SHORT); // 52 + glyphElements.put("at_velocity", VELOCITY_FLOAT); // 60 + cloudsElements.put("Position", DefaultVertexFormat.ELEMENT_POSITION); // 12 cloudsElements.put("Color", DefaultVertexFormat.ELEMENT_COLOR); // 16 @@ -74,8 +85,12 @@ public class IrisVertexFormats { TERRAIN = new VertexFormat(terrainElements.build()); ENTITY = new VertexFormat(entityElements.build()); + PARTICLES = new VertexFormat(particleElements.build()); GLYPH = new VertexFormat(glyphElements.build()); CLOUDS = new VertexFormat(cloudsElements.build()); + + debug(ENTITY); + debug(GLYPH); } private static void debug(VertexFormat format) { diff --git a/src/main/java/net/coderbot/iris/vertices/NormalHelper.java b/src/main/java/net/coderbot/iris/vertices/NormalHelper.java index 44aca7fff9..ea912b67ac 100644 --- a/src/main/java/net/coderbot/iris/vertices/NormalHelper.java +++ b/src/main/java/net/coderbot/iris/vertices/NormalHelper.java @@ -184,6 +184,77 @@ public static void computeFaceNormalTri(@NotNull Vector3f saveTo, TriView t) { saveTo.set(normX, normY, normZ); } + public 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); + } + public static int computeTangentSmooth(float normalX, float normalY, float normalZ, TriView t) { // Capture all of the relevant vertex positions float x0 = t.x(0); diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 92cdbd4bd0..a6f8586021 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -65,7 +65,9 @@ "sodium:options": { "mixin.features.render.world.sky": false, "mixin.features.render.entity": false, - "mixin.features.render.gui.font": false + "mixin.features.render.particle": false, + "mixin.features.render.gui.font": false, + "mixin.features.render.model.item": false } } } diff --git a/src/main/resources/iris.accesswidener b/src/main/resources/iris.accesswidener index 6d3e780aea..8f087dac76 100644 --- a/src/main/resources/iris.accesswidener +++ b/src/main/resources/iris.accesswidener @@ -32,3 +32,4 @@ accessible field net/minecraft/client/renderer/ShaderInstance uniforms Ljava/uti mutable field net/minecraft/client/renderer/LevelRenderer renderBuffers Lnet/minecraft/client/renderer/RenderBuffers; accessible class net/minecraft/client/gui/components/AbstractSelectionList$Entry accessible field com/mojang/blaze3d/platform/GlStateManager$BooleanState enabled Z +accessible field net/minecraft/client/gui/font/glyphs/BakedGlyph$Effect x0 F diff --git a/src/main/resources/mixins.iris.json b/src/main/resources/mixins.iris.json index 99e154acc0..fc27dea9c9 100644 --- a/src/main/resources/mixins.iris.json +++ b/src/main/resources/mixins.iris.json @@ -58,6 +58,7 @@ "entity_render_context.MixinCapeLayer", "entity_render_context.MixinElytraLayer", "entity_render_context.MixinEntityRenderDispatcher", + "entity_render_context.MixinEntityRenderer", "entity_render_context.MixinHorseArmorLayer", "entity_render_context.MixinHumanoidArmorLayer", "entity_render_context.MixinItemRenderer", diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/entities/IrisBakedQuad.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/entities/IrisBakedQuad.java new file mode 100644 index 0000000000..15fe1cae20 --- /dev/null +++ b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/entities/IrisBakedQuad.java @@ -0,0 +1,7 @@ +package net.coderbot.iris.compat.sodium.impl.entities; + +import org.joml.Vector3f; + +public interface IrisBakedQuad { + VertexHistory getPrevious(); +} diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/entities/IrisModelCuboid.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/entities/IrisModelCuboid.java new file mode 100644 index 0000000000..825a69de42 --- /dev/null +++ b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/entities/IrisModelCuboid.java @@ -0,0 +1,170 @@ +package net.coderbot.iris.compat.sodium.impl.entities; + +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import net.caffeinemc.mods.sodium.api.math.MatrixHelper; +import net.coderbot.iris.Iris; +import net.coderbot.iris.shadows.ShadowRenderingState; +import net.coderbot.iris.uniforms.CapturedRenderingState; +import net.coderbot.iris.uniforms.SystemTimeUniforms; +import net.jodah.expiringmap.ExpiringMap; +import net.minecraft.core.Direction; +import org.joml.*; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +public class IrisModelCuboid { + public final Quad[] quads; + + private final Vector3f[] vertices; + private final Vector3f[] shared; + private final Vector3f[] previous; + private final ExpiringMap idToHistory = ExpiringMap.builder().maxSize(10000).expiration(30, TimeUnit.SECONDS).build(); + + public IrisModelCuboid(int u, int v, float x1, float y1, float z1, float sizeX, float sizeY, float sizeZ, float extraX, float extraY, float extraZ, boolean mirror, float textureWidth, float textureHeight, Set renderDirections) { + float x2 = x1 + sizeX; + float y2 = y1 + sizeY; + float z2 = z1 + sizeZ; + + x1 -= extraX; + y1 -= extraY; + z1 -= extraZ; + + x2 += extraX; + y2 += extraY; + z2 += extraZ; + + if (mirror) { + float i = x2; + x2 = x1; + x1 = i; + } + + Vector3f[] vertices = new Vector3f[8]; + vertices[0] = new Vector3f(x1, y1, z1); + vertices[1] = new Vector3f(x2, y1, z1); + vertices[2] = new Vector3f(x2, y2, z1); + vertices[3] = new Vector3f(x1, y2, z1); + vertices[4] = new Vector3f(x1, y1, z2); + vertices[5] = new Vector3f(x2, y1, z2); + vertices[6] = new Vector3f(x2, y2, z2); + vertices[7] = new Vector3f(x1, y2, z2); + + Vector3f[] shared = new Vector3f[8]; + Vector3f[] previous = new Vector3f[8]; + + for (int i = 0; i < 8; i++) { + vertices[i].div(16.0f); + shared[i] = new Vector3f(Float.NaN); + previous[i] = new Vector3f(Float.NaN); + } + + float u0 = (float) u; + float u1 = (float) u + sizeZ; + float u2 = (float) u + sizeZ + sizeX; + float u3 = (float) u + sizeZ + sizeX + sizeX; + float u4 = (float) u + sizeZ + sizeX + sizeZ; + float u5 = (float) u + sizeZ + sizeX + sizeZ + sizeX; + + float v0 = (float) v; + float v1 = (float) v + sizeZ; + float v2 = (float) v + sizeZ + sizeY; + + var sides = new Quad[6]; + + if (renderDirections.contains(Direction.DOWN)) { + sides[2] = new Quad(new Vector3f[] { shared[5], shared[4], shared[0], shared[1] }, new Vector3f[] { previous[5], previous[4], previous[0], previous[1] }, u1, v0, u2, v1, textureWidth, textureHeight, mirror, Direction.DOWN); + } + + if (renderDirections.contains(Direction.UP)) { + sides[3] = new Quad(new Vector3f[] { shared[2], shared[3], shared[7], shared[6] }, new Vector3f[] { previous[2], previous[3], previous[7], previous[6] }, u2, v1, u3, v0, textureWidth, textureHeight, mirror, Direction.UP); + } + + if (renderDirections.contains(Direction.WEST)) { + sides[1] = new Quad(new Vector3f[] { shared[0], shared[4], shared[7], shared[3] }, new Vector3f[] { previous[0], previous[4], previous[7], previous[3] }, u0, v1, u1, v2, textureWidth, textureHeight, mirror, Direction.WEST); + } + + if (renderDirections.contains(Direction.NORTH)) { + sides[4] = new Quad(new Vector3f[] { shared[1], shared[0], shared[3], shared[2] }, new Vector3f[] { previous[1], previous[0], previous[3], previous[2] }, u1, v1, u2, v2, textureWidth, textureHeight, mirror, Direction.NORTH); + } + + if (renderDirections.contains(Direction.EAST)) { + sides[0] = new Quad(new Vector3f[] { shared[5], shared[1], shared[2], shared[6] }, new Vector3f[] { previous[5], previous[1], previous[2], previous[6] }, u2, v1, u4, v2, textureWidth, textureHeight, mirror, Direction.EAST); + } + + if (renderDirections.contains(Direction.SOUTH)) { + sides[5] = new Quad(new Vector3f[] { shared[4], shared[5], shared[6], shared[7] }, new Vector3f[] { previous[4], previous[5], previous[6], previous[7] }, u4, v1, u5, v2, textureWidth, textureHeight, mirror, Direction.SOUTH); + } + this.quads = sides; + + this.vertices = vertices; + this.shared = shared; + this.previous = previous; + } + + public void updateVertices(Matrix4f mat) { + VertexHistory history = idToHistory.computeIfAbsent(CapturedRenderingState.INSTANCE.getUniqueEntityId(), id -> new VertexHistory(id, 8)); + for (int i = 0; i < 8; i++) { + var src = this.vertices[i]; + var dst = this.shared[i]; + + src.mulPosition(mat, dst); + + if (!ShadowRenderingState.areShadowsCurrentlyBeingRendered()) { + previous[i].set(history.storedPositions[i]); + history.storedPositions[i].set(dst); + history.lastFrame = SystemTimeUniforms.COUNTER.getAsInt(); + + } + } + + } + + public static class Quad { + public final Vector3f[] positions; + public final Vector2f[] textures; + public final Vector3f[] prevPositions; + + public final Vector3f direction; + + public Quad(Vector3f[] positions, Vector3f[] prevPositions, float u1, float v1, float u2, float v2, float textureWidth, float textureHeight, boolean flip, Direction direction) { + var textures = new Vector2f[4]; + textures[0] = new Vector2f(u2 / textureWidth, v1 / textureHeight); + textures[1] = new Vector2f(u1 / textureWidth, v1 / textureHeight); + textures[2] = new Vector2f(u1 / textureWidth, v2 / textureHeight); + textures[3] = new Vector2f(u2 / textureWidth, v2 / textureHeight); + + if (flip) { + int len = positions.length; + + for (int i = 0; i < len / 2; ++i) { + var pos = positions[i]; + positions[i] = positions[len - 1 - i]; + positions[len - 1 - i] = pos; + + var pos2 = prevPositions[i]; + prevPositions[i] = prevPositions[len - 1 - i]; + prevPositions[len - 1 - i] = pos2; + + var tex = textures[i]; + textures[i] = textures[len - 1 - i]; + textures[len - 1 - i] = tex; + } + } + + this.positions = positions; + this.prevPositions = prevPositions; + this.textures = textures; + + this.direction = direction.step(); + + if (flip) { + this.direction.mul(-1.0F, 1.0F, 1.0F); + } + } + + public int getNormal(Matrix3f mat) { + return MatrixHelper.transformNormal(mat, this.direction.x, this.direction.y, this.direction.z); + } + } +} diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/entities/IrisModelCuboidAccessor.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/entities/IrisModelCuboidAccessor.java new file mode 100644 index 0000000000..b575c59169 --- /dev/null +++ b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/entities/IrisModelCuboidAccessor.java @@ -0,0 +1,5 @@ +package net.coderbot.iris.compat.sodium.impl.entities; + +public interface IrisModelCuboidAccessor { + IrisModelCuboid iris$copy(); +} diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/entities/VertexHistory.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/entities/VertexHistory.java new file mode 100644 index 0000000000..027d9610f3 --- /dev/null +++ b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/entities/VertexHistory.java @@ -0,0 +1,15 @@ +package net.coderbot.iris.compat.sodium.impl.entities; + +import org.joml.Vector3f; + +public class VertexHistory { + public Vector3f[] storedPositions; + public int lastFrame; + + public VertexHistory(int id, int size) { + storedPositions = new Vector3f[size]; + for (int i = 0; i < size; i++) { + storedPositions[i] = new Vector3f(); + } + } +} diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/vertex_format/ModelToEntityVertexSerializer.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/vertex_format/ModelToEntityVertexSerializer.java index b833dcd0ba..74507c39b5 100644 --- a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/vertex_format/ModelToEntityVertexSerializer.java +++ b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/vertex_format/ModelToEntityVertexSerializer.java @@ -38,6 +38,9 @@ public void serialize(long src, long dst, int vertexCount) { MemoryUtil.memPutFloat(dst + 46, midV); MemoryUtil.memPutInt(dst + 50, tangent); + MemoryUtil.memPutFloat(dst + 52, 0); + MemoryUtil.memPutFloat(dst + 56, 0); + MemoryUtil.memPutFloat(dst + 60, 0); src += ModelVertex.STRIDE; dst += IrisVertexFormats.ENTITY.getVertexSize(); } diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/EntityVertex.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/EntityVertex.java index 99dc7ed331..735599c797 100644 --- a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/EntityVertex.java +++ b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/EntityVertex.java @@ -7,6 +7,7 @@ import net.caffeinemc.mods.sodium.api.vertex.buffer.VertexBufferWriter; import net.caffeinemc.mods.sodium.api.vertex.format.VertexFormatDescription; import net.caffeinemc.mods.sodium.api.vertex.format.VertexFormatRegistry; +import net.coderbot.iris.Iris; import net.coderbot.iris.uniforms.CapturedRenderingState; import net.coderbot.iris.vertices.IrisVertexFormats; import net.coderbot.iris.vertices.NormalHelper; @@ -25,16 +26,16 @@ public final class EntityVertex { private static final int OFFSET_POSITION = 0; private static final int OFFSET_COLOR = 12; private static final int OFFSET_TEXTURE = 16; - private static final int OFFSET_MID_TEXTURE = 42; + private static final int OFFSET_MID_TEXTURE = 44; private static final int OFFSET_OVERLAY = 24; private static final int OFFSET_LIGHT = 28; private static final int OFFSET_NORMAL = 32; - private static final int OFFSET_TANGENT = 50; + private static final int OFFSET_TANGENT = 48; private static Vector3f lastNormal = new Vector3f(); public static void write(long ptr, - float x, float y, float z, int color, float u, float v, float midU, float midV, int light, int overlay, int normal, int tangent) { + float x, float y, float z, int color, float u, float v, short midU, short midV, int light, int overlay, int normal, int tangent) { MemoryUtil.memPutFloat(ptr + OFFSET_POSITION + 0, x); MemoryUtil.memPutFloat(ptr + OFFSET_POSITION + 4, y); MemoryUtil.memPutFloat(ptr + OFFSET_POSITION + 8, z); @@ -51,13 +52,39 @@ public static void write(long ptr, MemoryUtil.memPutInt(ptr + OFFSET_NORMAL, normal); MemoryUtil.memPutInt(ptr + OFFSET_TANGENT, tangent); - MemoryUtil.memPutFloat(ptr + OFFSET_MID_TEXTURE, midU); - MemoryUtil.memPutFloat(ptr + OFFSET_MID_TEXTURE + 4, midV); + MemoryUtil.memPutShort(ptr + OFFSET_MID_TEXTURE, midU); + MemoryUtil.memPutShort(ptr + OFFSET_MID_TEXTURE + 2, midV); MemoryUtil.memPutShort(ptr + 36, (short) CapturedRenderingState.INSTANCE.getCurrentRenderedEntity()); MemoryUtil.memPutShort(ptr + 38, (short) CapturedRenderingState.INSTANCE.getCurrentRenderedBlockEntity()); MemoryUtil.memPutShort(ptr + 40, (short) CapturedRenderingState.INSTANCE.getCurrentRenderedItem()); + MemoryUtil.memPutFloat(ptr + 52, 0); + MemoryUtil.memPutFloat(ptr + 56, 0); + MemoryUtil.memPutFloat(ptr + 60, 0); + } + + public static void writeWithVelocity(long ptr, + float x, float y, float z, float prevX, float prevY, float prevZ, int color, float u, float v, short midU, short midV, int light, int overlay, int normal, int tangent) { + write(ptr, x, y, z, color, u, v, midU, midV, light, overlay, normal, tangent); + + MemoryUtil.memPutFloat(ptr + 52, x - prevX); + MemoryUtil.memPutFloat(ptr + 56, y - prevY); + MemoryUtil.memPutFloat(ptr + 60, z - prevZ); + } + + public static void writeUnknownTangentWithVelocity(long ptr, + float x, float y, float z, float prevX, float prevY, float prevZ, int color, float u, float v, short midU, short midV, int light, int overlay, int normal) { + write(ptr, x, y, z, color, u, v, midU, midV, light, overlay, normal, 0); + MemoryUtil.memPutFloat(ptr + 52, x - prevX); + MemoryUtil.memPutFloat(ptr + 56, y - prevY); + MemoryUtil.memPutFloat(ptr + 60, z - prevZ); + + endQuad(ptr, NormI8.unpackX(normal), NormI8.unpackY(normal), NormI8.unpackZ(normal)); + } + + private static short encodeTexture(float value) { + return (short) (Math.min(0.99999997F, value) * 65536); } public static void write2(long ptr, diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/GlyphVertexExt.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/GlyphVertexExt.java index 618d9d7fc8..64e2767526 100644 --- a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/GlyphVertexExt.java +++ b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/GlyphVertexExt.java @@ -23,10 +23,10 @@ public final class GlyphVertexExt { private static final int OFFSET_POSITION = 0; private static final int OFFSET_COLOR = 12; private static final int OFFSET_TEXTURE = 16; - private static final int OFFSET_MID_TEXTURE = 38; + private static final int OFFSET_MID_TEXTURE = 40; private static final int OFFSET_LIGHT = 24; private static final int OFFSET_NORMAL = 28; - private static final int OFFSET_TANGENT = 46; + private static final int OFFSET_TANGENT = 44; private static final QuadViewEntity.QuadViewEntityUnsafe quad = new QuadViewEntity.QuadViewEntityUnsafe(); @@ -38,7 +38,7 @@ public final class GlyphVertexExt { private static Vector3f lastNormal = new Vector3f(); - public static void write(long ptr, float x, float y, float z, int color, float u, float v, int light) { + public static void write(long ptr, float x, float y, float z, float prevX, float prevY, float prevZ, int color, float u, float v, int light) { long i = ptr; vertexCount++; @@ -60,6 +60,12 @@ public static void write(long ptr, float x, float y, float z, int color, float u MemoryUtil.memPutShort(ptr + 34, (short) CapturedRenderingState.INSTANCE.getCurrentRenderedBlockEntity()); MemoryUtil.memPutShort(ptr + 36, (short) CapturedRenderingState.INSTANCE.getCurrentRenderedItem()); + // 38 empty + + MemoryUtil.memPutFloat(ptr + 48, x - prevX); + MemoryUtil.memPutFloat(ptr + 52, y - prevY); + MemoryUtil.memPutFloat(ptr + 56, z - prevZ); + if (vertexCount == 4) { endQuad(ptr); } @@ -128,7 +134,7 @@ public static void writeQuadVertices(VertexBufferWriter writer, PoseStack.Pose m float yt = (matPosition.m01() * x) + (matPosition.m11() * y) + (matPosition.m21() * z) + matPosition.m31(); float zt = (matPosition.m02() * x) + (matPosition.m12() * y) + (matPosition.m22() * z) + matPosition.m32(); - write(ptr, xt, yt, zt, color, quad.getTexU(i), quad.getTexV(i), light); + write(ptr, xt, yt, zt, 0, 0, 0, color, quad.getTexU(i), quad.getTexV(i), light); ptr += STRIDE; } diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/IrisParticleVertex.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/IrisParticleVertex.java new file mode 100644 index 0000000000..2db73c7d6d --- /dev/null +++ b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/vertex_format/entity_xhfp/IrisParticleVertex.java @@ -0,0 +1,32 @@ +package net.coderbot.iris.compat.sodium.impl.vertex_format.entity_xhfp; + +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import net.caffeinemc.mods.sodium.api.vertex.attributes.common.ColorAttribute; +import net.caffeinemc.mods.sodium.api.vertex.attributes.common.LightAttribute; +import net.caffeinemc.mods.sodium.api.vertex.attributes.common.PositionAttribute; +import net.caffeinemc.mods.sodium.api.vertex.format.VertexFormatDescription; +import net.caffeinemc.mods.sodium.api.vertex.format.VertexFormatRegistry; +import net.caffeinemc.mods.sodium.api.vertex.attributes.common.TextureAttribute; +import net.coderbot.iris.vertices.IrisVertexFormats; + +public final class IrisParticleVertex { + public static final VertexFormatDescription FORMAT = VertexFormatRegistry.instance() + .get(IrisVertexFormats.PARTICLES); + + public static final int STRIDE = IrisVertexFormats.PARTICLES.getVertexSize(); + + private static final int OFFSET_POSITION = 0; + private static final int OFFSET_TEXTURE = 12; + private static final int OFFSET_COLOR = 20; + private static final int OFFSET_LIGHT = 24; + private static final int OFFSET_VELOCITY = 28; + + public static void put(long ptr, + float x, float y, float z, float prevX, float prevY, float prevZ, float u, float v, int color, int light) { + PositionAttribute.put(ptr + OFFSET_POSITION, x, y, z); + TextureAttribute.put(ptr + OFFSET_TEXTURE, u, v); + ColorAttribute.set(ptr + OFFSET_COLOR, color); + LightAttribute.set(ptr + OFFSET_LIGHT, light); + PositionAttribute.put(ptr + OFFSET_VELOCITY, x - prevX, y - prevY, z - prevZ); + } +} diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/copyEntity/BillboardParticleMixin.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/copyEntity/BillboardParticleMixin.java new file mode 100644 index 0000000000..f31daebb8e --- /dev/null +++ b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/copyEntity/BillboardParticleMixin.java @@ -0,0 +1,159 @@ +package net.coderbot.iris.compat.sodium.mixin.copyEntity; + +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.caffeinemc.mods.sodium.api.vertex.format.common.ParticleVertex; +import net.caffeinemc.mods.sodium.api.vertex.buffer.VertexBufferWriter; +import net.caffeinemc.mods.sodium.api.util.ColorABGR; +import net.coderbot.iris.compat.sodium.impl.vertex_format.entity_xhfp.IrisParticleVertex; +import net.coderbot.iris.vertices.ImmediateState; +import net.irisshaders.iris.api.v0.IrisApi; +import net.minecraft.client.Camera; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.Particle; +import net.minecraft.client.particle.SingleQuadParticle; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.Vec3; +import org.joml.Quaternionf; +import org.joml.Vector3f; +import org.lwjgl.system.MemoryStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(SingleQuadParticle.class) +public abstract class BillboardParticleMixin extends Particle { + @Shadow + public abstract float getQuadSize(float tickDelta); + + @Shadow + protected abstract float getU0(); + + @Shadow + protected abstract float getU1(); + + @Shadow + protected abstract float getV0(); + + @Shadow + protected abstract float getV1(); + + @Unique + private Vector3f[] lastPositions = new Vector3f[] { + new Vector3f(), new Vector3f(), new Vector3f(), new Vector3f() + }; + + protected BillboardParticleMixin(ClientLevel world, double x, double y, double z) { + super(world, x, y, z); + } + + private boolean extend() { + return IrisApi.getInstance().isShaderPackInUse() && ImmediateState.renderWithExtendedVertexFormat; + } + + /** + * @reason Optimize function + * @author JellySquid + */ + @Overwrite + public void render(VertexConsumer vertexConsumer, Camera camera, float tickDelta) { + Vec3 vec3d = camera.getPosition(); + + float x = (float) (Mth.lerp(tickDelta, this.xo, this.x) - vec3d.x()); + float y = (float) (Mth.lerp(tickDelta, this.yo, this.y) - vec3d.y()); + float z = (float) (Mth.lerp(tickDelta, this.zo, this.z) - vec3d.z()); + + boolean extend = extend(); + int stride = extend ? IrisParticleVertex.STRIDE : ParticleVertex.STRIDE; + + Quaternionf quaternion; + + if (this.roll == 0.0F) { + quaternion = camera.rotation(); + } else { + float angle = Mth.lerp(tickDelta, this.oRoll, this.roll); + + quaternion = new Quaternionf(camera.rotation()); + quaternion.rotateZ(angle); + } + + float size = this.getQuadSize(tickDelta); + int light = this.getLightColor(tickDelta); + + float minU = this.getU0(); + float maxU = this.getU1(); + float minV = this.getV0(); + float maxV = this.getV1(); + + int color = ColorABGR.pack(this.rCol , this.gCol, this.bCol, this.alpha); + + var writer = VertexBufferWriter.of(vertexConsumer); + + try (MemoryStack stack = MemoryStack.stackPush()) { + long buffer = stack.nmalloc(4 * stride); + long ptr = buffer; + + writeVertex(ptr, extend, 0, quaternion,-1.0F, -1.0F, x, y, z, maxU, maxV, color, light, size); + ptr += stride; + + writeVertex(ptr, extend, 1, quaternion,-1.0F, 1.0F, x, y, z, maxU, minV, color, light, size); + ptr += stride; + + writeVertex(ptr, extend, 2, quaternion,1.0F, 1.0F, x, y, z, minU, minV, color, light, size); + ptr += stride; + + writeVertex(ptr, extend, 3, quaternion,1.0F, -1.0F, x, y, z, minU, maxV, color, light, size); + ptr += stride; + + writer.push(stack, buffer, 4, extend ? IrisParticleVertex.FORMAT : ParticleVertex.FORMAT); + } + + } + + @Unique + @SuppressWarnings("UnnecessaryLocalVariable") + private void writeVertex(long buffer, boolean extend, int vertex, + Quaternionf rotation, + float posX, float posY, + float originX, float originY, float originZ, + float u, float v, int color, int light, float size) { + // Quaternion q0 = new Quaternion(rotation); + float q0x = rotation.x(); + float q0y = rotation.y(); + float q0z = rotation.z(); + float q0w = rotation.w(); + + // q0.hamiltonProduct(x, y, 0.0f, 0.0f) + float q1x = (q0w * posX) - (q0z * posY); + float q1y = (q0w * posY) + (q0z * posX); + float q1w = (q0x * posY) - (q0y * posX); + float q1z = -(q0x * posX) - (q0y * posY); + + // Quaternion q2 = new Quaternion(rotation); + // q2.conjugate() + float q2x = -q0x; + float q2y = -q0y; + float q2z = -q0z; + float q2w = q0w; + + // q2.hamiltonProduct(q1) + float q3x = q1z * q2x + q1x * q2w + q1y * q2z - q1w * q2y; + float q3y = q1z * q2y - q1x * q2z + q1y * q2w + q1w * q2x; + float q3z = q1z * q2z + q1x * q2y - q1y * q2x + q1w * q2w; + + // Vector3f f = new Vector3f(q2.getX(), q2.getY(), q2.getZ()) + // f.multiply(size) + // f.add(pos) + float fx = (q3x * size) + originX; + float fy = (q3y * size) + originY; + float fz = (q3z * size) + originZ; + + if (extend) { + IrisParticleVertex.put(buffer, fx, fy, fz, lastPositions[vertex].x, lastPositions[vertex].y, lastPositions[vertex].z, u, v, color, light); + } else { + ParticleVertex.put(buffer, fx, fy, fz, u, v, color, light); + } + + lastPositions[vertex].set(fx, fy, fz); + } +} diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/copyEntity/CuboidMixin.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/copyEntity/CuboidMixin.java index 59e46b063f..fabadf296c 100644 --- a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/copyEntity/CuboidMixin.java +++ b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/copyEntity/CuboidMixin.java @@ -1,7 +1,7 @@ package net.coderbot.iris.compat.sodium.mixin.copyEntity; -import me.jellysquid.mods.sodium.client.model.ModelCuboidAccessor; -import me.jellysquid.mods.sodium.client.render.immediate.model.ModelCuboid; +import net.coderbot.iris.compat.sodium.impl.entities.IrisModelCuboid; +import net.coderbot.iris.compat.sodium.impl.entities.IrisModelCuboidAccessor; import net.minecraft.client.model.geom.ModelPart; import net.minecraft.core.Direction; import org.objectweb.asm.Opcodes; @@ -14,18 +14,18 @@ import java.util.Set; @Mixin(ModelPart.Cube.class) -public class CuboidMixin implements ModelCuboidAccessor { +public class CuboidMixin implements IrisModelCuboidAccessor { @Unique - private ModelCuboid sodium$cuboid; + private IrisModelCuboid iris$cuboid; // Inject at the start of the function, so we don't capture modified locals @Inject(method = "", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lnet/minecraft/client/model/geom/ModelPart$Cube;polygons:[Lnet/minecraft/client/model/geom/ModelPart$Polygon;", ordinal = 0)) private void onInit(int u, int v, float x, float y, float z, float sizeX, float sizeY, float sizeZ, float extraX, float extraY, float extraZ, boolean mirror, float textureWidth, float textureHeight, Set renderDirections, CallbackInfo ci) { - this.sodium$cuboid = new ModelCuboid(u, v, x, y, z, sizeX, sizeY, sizeZ, extraX, extraY, extraZ, mirror, textureWidth, textureHeight, renderDirections); + this.iris$cuboid = new IrisModelCuboid(u, v, x, y, z, sizeX, sizeY, sizeZ, extraX, extraY, extraZ, mirror, textureWidth, textureHeight, renderDirections); } @Override - public ModelCuboid sodium$copy() { - return this.sodium$cuboid; + public IrisModelCuboid iris$copy() { + return this.iris$cuboid; } } diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/copyEntity/ModelPartMixin.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/copyEntity/ModelPartMixin.java index a5c2885e0f..a16c905afe 100644 --- a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/copyEntity/ModelPartMixin.java +++ b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/copyEntity/ModelPartMixin.java @@ -8,6 +8,13 @@ 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.entities.IrisModelCuboid; +import net.coderbot.iris.compat.sodium.impl.entities.IrisModelCuboidAccessor; +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.model.geom.ModelPart; import org.lwjgl.system.MemoryStack; import org.spongepowered.asm.mixin.Mixin; @@ -36,20 +43,27 @@ public class ModelPartMixin { @Shadow public float zScale; @Unique - private ModelCuboid[] sodium$cuboids; + private IrisModelCuboid[] sodium$cuboids; @Inject(method = "", at = @At("RETURN")) private void onInit(List cuboids, Map children, CallbackInfo ci) { - var copies = new ModelCuboid[cuboids.size()]; + var copies = new IrisModelCuboid[cuboids.size()]; for (int i = 0; i < cuboids.size(); i++) { - var accessor = (ModelCuboidAccessor) cuboids.get(i); - copies[i] = accessor.sodium$copy(); + var accessor = (IrisModelCuboidAccessor) cuboids.get(i); + copies[i] = accessor.iris$copy(); } this.sodium$cuboids = copies; } + private boolean extend() { + return IrisApi.getInstance().isShaderPackInUse() && ImmediateState.renderWithExtendedVertexFormat; + } + private static short encodeTexture(float value) { + return (short) (Math.min(0.99999997F, value) * 65536); + } + /** * @author JellySquid * @reason Use optimized vertex writer, avoid allocations, use quick matrix transformations @@ -65,33 +79,67 @@ private void renderCuboidsFast(PoseStack.Pose matrices, VertexConsumer vertexCon int color = ColorABGR.pack(red, green, blue, alpha); - for (ModelCuboid cuboid : this.sodium$cuboids) { + for (IrisModelCuboid cuboid : this.sodium$cuboids) { cuboid.updateVertices(matrices.pose()); + boolean extend = extend(); + try (MemoryStack stack = MemoryStack.stackPush()) { - long buffer = stack.nmalloc(4 * 6 * ModelVertex.STRIDE); + long buffer = stack.nmalloc(4 * 6 * (extend ? EntityVertex.STRIDE : ModelVertex.STRIDE)); long ptr = buffer; int count = 0; - for (ModelCuboid.Quad quad : cuboid.quads) { + for (IrisModelCuboid.Quad quad : cuboid.quads) { if (quad == null) continue; var normal = quad.getNormal(matrices.normal()); - for (int i = 0; i < 4; i++) { - var pos = quad.positions[i]; - var tex = quad.textures[i]; + float midU = 0, midV = 0; + int tangent = 0; + + if (extend) { + for (int i = 0; i < 4; i++) { + midU += quad.textures[i].x; + midV += quad.textures[i].y; + } + + midU *= 0.25; + midV *= 0.25; + + tangent = NormalHelper.computeTangent(NormI8.unpackX(normal), NormI8.unpackY(normal), NormI8.unpackZ(normal), quad.positions[0].x, quad.positions[0].y, quad.positions[0].z, quad.textures[0].x, quad.textures[0].y, + quad.positions[1].x, quad.positions[1].y, quad.positions[1].z, quad.textures[1].x, quad.textures[1].y, + quad.positions[2].x, quad.positions[2].y, quad.positions[2].z, quad.textures[2].x, quad.textures[2].y + ); + } + + if (extend) { + short midUFinal = encodeTexture(midU); + short midVFinal = encodeTexture(midV); + for (int i = 0; i < 4; i++) { + var pos = quad.positions[i]; + var pos2 = quad.prevPositions[i]; + var tex = quad.textures[i]; + + EntityVertex.writeWithVelocity(ptr, pos.x, pos.y, pos.z, pos2.x, pos2.y, pos2.z, color, tex.x, tex.y, midUFinal, midVFinal, light, overlay, normal, tangent); + + ptr += EntityVertex.STRIDE; + } + } else { + for (int i = 0; i < 4; i++) { + var pos = quad.positions[i]; + var tex = quad.textures[i]; - ModelVertex.write(ptr, pos.x, pos.y, pos.z, color, tex.x, tex.y, overlay, light, normal); + ModelVertex.write(ptr, pos.x, pos.y, pos.z, color, tex.x, tex.y, overlay, light, normal); - ptr += ModelVertex.STRIDE; + ptr += ModelVertex.STRIDE; + } } count += 4; } - writer.push(stack, buffer, count, ModelVertex.FORMAT); + writer.push(stack, buffer, count, extend ? EntityVertex.FORMAT : ModelVertex.FORMAT); } } } 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 b7add70524..b96c30b827 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 @@ -106,8 +106,8 @@ private static void renderShadowPart(PoseStack.Pose matrices, VertexConsumer ver ); } - float midU = (u1 + u2) / 2; - float midV = (v1 + v2) / 2; + short midU = encodeTexture((u1 + u2) / 2); + short midV = encodeTexture((v1 + v2) / 2); int stride = extended ? EntityVertex.STRIDE : ModelVertex.STRIDE; @@ -146,7 +146,11 @@ private static void renderShadowPart(PoseStack.Pose matrices, VertexConsumer ver } } - @Unique + private static short encodeTexture(float value) { + return (short) (Math.min(0.99999997F, value) * 65536); + } + + @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); @@ -157,7 +161,7 @@ private static void writeShadowVertex(long ptr, Matrix4f matPosition, float x, f } @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 writeShadowVertexIris(long ptr, Matrix4f matPosition, float x, float y, float z, float u, float v, int color, short midU, short midV, int normal, int tangent) { // The transformed position vector float xt = MatrixHelper.transformPositionX(matPosition, x, y, z); float yt = MatrixHelper.transformPositionY(matPosition, x, y, z); diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/fast_render/MixinCube.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/fast_render/MixinCube.java deleted file mode 100644 index 00dda413b4..0000000000 --- a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/fast_render/MixinCube.java +++ /dev/null @@ -1,28 +0,0 @@ -package net.coderbot.iris.compat.sodium.mixin.fast_render; - -import me.jellysquid.mods.sodium.client.model.ModelCuboidAccessor; -import me.jellysquid.mods.sodium.client.render.immediate.model.ModelCuboid; -import net.minecraft.client.model.geom.ModelPart; -import net.minecraft.core.Direction; -import org.objectweb.asm.Opcodes; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.Set; - -@Mixin(ModelPart.Cube.class) -public class MixinCube implements ModelCuboidAccessor { - private ModelCuboid sodium$cuboid; - - @Inject(method = "", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lnet/minecraft/client/model/geom/ModelPart$Cube;polygons:[Lnet/minecraft/client/model/geom/ModelPart$Polygon;", ordinal = 0)) - private void onInit(int u, int v, float x, float y, float z, float sizeX, float sizeY, float sizeZ, float extraX, float extraY, float extraZ, boolean mirror, float textureWidth, float textureHeight, Set directions, CallbackInfo ci) { - this.sodium$cuboid = new ModelCuboid(u, v, x, y, z, sizeX, sizeY, sizeZ, extraX, extraY, extraZ, mirror, textureWidth, textureHeight, directions); - } - - @Override - public ModelCuboid sodium$copy() { - return this.sodium$cuboid; - } -} diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/fast_render/MixinModelPart.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/fast_render/MixinModelPart.java deleted file mode 100644 index 4d833e7d34..0000000000 --- a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/fast_render/MixinModelPart.java +++ /dev/null @@ -1,184 +0,0 @@ -package net.coderbot.iris.compat.sodium.mixin.fast_render; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import me.jellysquid.mods.sodium.client.model.ModelCuboidAccessor; -import me.jellysquid.mods.sodium.client.render.immediate.model.ModelCuboid; -import net.caffeinemc.mods.sodium.api.util.ColorABGR; -import net.caffeinemc.mods.sodium.api.vertex.buffer.VertexBufferWriter; -import net.caffeinemc.mods.sodium.api.vertex.format.common.ModelVertex; -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.irisshaders.iris.api.v0.IrisApi; -import net.minecraft.client.model.geom.ModelPart; -import org.lwjgl.system.MemoryStack; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.List; -import java.util.Map; - -@Mixin(ModelPart.class) -public class MixinModelPart { - private ModelCuboid[] sodium$cuboids; - - 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)); - } - } - - private static boolean shouldExtend() { - return IrisApi.getInstance().isShaderPackInUse() && ImmediateState.renderWithExtendedVertexFormat; - } - - @Inject(method = "", at = @At("RETURN")) - private void onInit(List cuboids, Map children, CallbackInfo ci) { - var copies = new ModelCuboid[cuboids.size()]; - - for (int i = 0; i < cuboids.size(); i++) { - var accessor = (ModelCuboidAccessor) cuboids.get(i); - copies[i] = accessor.sodium$copy(); - } - - this.sodium$cuboids = copies; - } - - /** - * @author JellySquid - * @reason Use optimized vertex writer, avoid allocations, use quick matrix transformations - */ - @Overwrite - private void compile(PoseStack.Pose matrices, VertexConsumer vertexConsumer, int light, int overlay, float red, float green, float blue, float alpha) { - var writer = VertexBufferWriter.of(vertexConsumer); - int color = ColorABGR.pack(red, green, blue, alpha); - - boolean extend = shouldExtend(); - for (ModelCuboid cuboid : this.sodium$cuboids) { - cuboid.updateVertices(matrices.pose()); - - - try (MemoryStack stack = MemoryStack.stackPush()) { - long buffer = stack.nmalloc(4 * 6 * (extend ? EntityVertex.STRIDE : ModelVertex.STRIDE)); - long ptr = buffer; - - for (ModelCuboid.Quad quad : cuboid.quads) { - if (quad == null) continue; - var normal = quad.getNormal(matrices.normal()); - - float midU = 0, midV = 0; - int tangent = 0; - - if (extend) { - for (int i = 0; i < 4; i++) { - midU += quad.textures[i].x; - midV += quad.textures[i].y; - } - - midU *= 0.25; - midV *= 0.25; - - tangent = getTangent(normal, quad.positions[0].x, quad.positions[0].y, quad.positions[0].z, quad.textures[0].x, quad.textures[0].y, - quad.positions[1].x, quad.positions[1].y, quad.positions[1].z, quad.textures[1].x, quad.textures[1].y, - quad.positions[2].x, quad.positions[2].y, quad.positions[2].z, quad.textures[2].x, quad.textures[2].y - ); - } - - for (int i = 0; i < 4; i++) { - var pos = quad.positions[i]; - var tex = quad.textures[i]; - - if (extend) { - EntityVertex.write(ptr, pos.x, pos.y, pos.z, color, tex.x, tex.y, midU, midV, light, overlay, normal, tangent); - } else { - ModelVertex.write(ptr, pos.x, pos.y, pos.z, color, tex.x, tex.y, light, overlay, normal); - } - - ptr += extend ? EntityVertex.STRIDE : ModelVertex.STRIDE; - } - } - - writer.push(stack, buffer, 4 * 6, extend ? EntityVertex.FORMAT : ModelVertex.FORMAT); - } - } - } - - private 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); - } -} diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/font/MixinGlyphRenderer.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/font/MixinGlyphRenderer.java index eb36d14635..81eb948e25 100644 --- a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/font/MixinGlyphRenderer.java +++ b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/font/MixinGlyphRenderer.java @@ -5,6 +5,7 @@ import net.caffeinemc.mods.sodium.api.vertex.buffer.VertexBufferWriter; import net.caffeinemc.mods.sodium.api.vertex.format.common.GlyphVertex; import net.coderbot.iris.compat.sodium.impl.vertex_format.entity_xhfp.GlyphVertexExt; +import net.coderbot.iris.uniforms.CapturedRenderingState; import net.coderbot.iris.vertices.ImmediateState; import net.irisshaders.iris.api.v0.IrisApi; import net.minecraft.client.gui.font.glyphs.BakedGlyph; @@ -91,6 +92,7 @@ public void render(boolean italic, float x, float y, Matrix4f matrix, VertexCons } } + private boolean extend() { return IrisApi.getInstance().isShaderPackInUse() && ImmediateState.renderWithExtendedVertexFormat; } @@ -100,9 +102,13 @@ private static void write(boolean ext, long buffer, float x2 = Math.fma(matrix.m00(), x, Math.fma(matrix.m10(), y, Math.fma(matrix.m20(), z, matrix.m30()))); float y2 = Math.fma(matrix.m01(), x, Math.fma(matrix.m11(), y, Math.fma(matrix.m21(), z, matrix.m31()))); float z2 = Math.fma(matrix.m02(), x, Math.fma(matrix.m12(), y, Math.fma(matrix.m22(), z, matrix.m32()))); + Matrix4f mat2 = CapturedRenderingState.INSTANCE.velocityInfoEdit.last().pose(); + float x3 = Math.fma(mat2.m00(), x, Math.fma(mat2.m10(), y, Math.fma(mat2.m20(), z, mat2.m30()))); + float y3 = Math.fma(mat2.m01(), x, Math.fma(mat2.m11(), y, Math.fma(mat2.m21(), z, mat2.m31()))); + float z3 = Math.fma(mat2.m02(), x, Math.fma(mat2.m12(), y, Math.fma(mat2.m22(), z, mat2.m32()))); if (ext) { - GlyphVertexExt.write(buffer, x2, y2, z2, color, u, v, light); + GlyphVertexExt.write(buffer, x2, y2, z2, x3, y3, z3, color, u, v, light); } else { GlyphVertex.put(buffer, x2, y2, z2, color, u, v, light); } diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/item/MixinBakedQuad.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/item/MixinBakedQuad.java new file mode 100644 index 0000000000..2cdc666b88 --- /dev/null +++ b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/item/MixinBakedQuad.java @@ -0,0 +1,21 @@ +package net.coderbot.iris.compat.sodium.mixin.item; + +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import net.coderbot.iris.compat.sodium.impl.entities.IrisBakedQuad; +import net.coderbot.iris.compat.sodium.impl.entities.VertexHistory; +import net.coderbot.iris.uniforms.CapturedRenderingState; +import net.minecraft.client.renderer.block.model.BakedQuad; +import org.joml.Vector3f; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(BakedQuad.class) +public class MixinBakedQuad implements IrisBakedQuad { + @Unique + private Int2ObjectOpenHashMap idToHistory = new Int2ObjectOpenHashMap<>(); + + @Override + public VertexHistory getPrevious() { + return idToHistory.computeIfAbsent(CapturedRenderingState.INSTANCE.getUniqueEntityId(), (i) -> new VertexHistory(i, 4)); + } +} diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/item/MixinItemRenderer.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/item/MixinItemRenderer.java new file mode 100644 index 0000000000..7983fb4e25 --- /dev/null +++ b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/item/MixinItemRenderer.java @@ -0,0 +1,180 @@ +package net.coderbot.iris.compat.sodium.mixin.item; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import me.jellysquid.mods.sodium.client.model.color.interop.ItemColorsExtended; +import me.jellysquid.mods.sodium.client.model.quad.BakedQuadView; +import me.jellysquid.mods.sodium.client.model.quad.ModelQuadView; +import me.jellysquid.mods.sodium.client.render.immediate.model.BakedModelEncoder; +import me.jellysquid.mods.sodium.client.render.texture.SpriteUtil; +import me.jellysquid.mods.sodium.client.render.vertex.VertexConsumerUtils; +import me.jellysquid.mods.sodium.client.util.DirectionUtil; +import net.caffeinemc.mods.sodium.api.math.MatrixHelper; +import net.caffeinemc.mods.sodium.api.util.ColorARGB; +import net.caffeinemc.mods.sodium.api.vertex.buffer.VertexBufferWriter; +import net.caffeinemc.mods.sodium.api.vertex.format.common.ModelVertex; +import net.coderbot.iris.compat.sodium.impl.entities.IrisBakedQuad; +import net.coderbot.iris.compat.sodium.impl.entities.VertexHistory; +import net.coderbot.iris.compat.sodium.impl.vertex_format.entity_xhfp.EntityVertex; +import net.coderbot.iris.shadows.ShadowRenderingState; +import net.coderbot.iris.uniforms.SystemTimeUniforms; +import net.coderbot.iris.vertices.ImmediateState; +import net.coderbot.iris.vertices.NormalHelper; +import net.irisshaders.iris.api.v0.IrisApi; +import net.minecraft.client.color.item.ItemColor; +import net.minecraft.client.color.item.ItemColors; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.levelgen.LegacyRandomSource; +import org.joml.Matrix3f; +import org.joml.Matrix4f; +import org.joml.Vector3f; +import org.lwjgl.system.MemoryStack; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +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; + +import java.util.List; + +@Mixin(value = ItemRenderer.class, priority = 1010) +public class MixinItemRenderer { + @Unique + private static short encodeTexture(float value) { + return (short) (Math.min(0.99999997F, value) * 65536); + } + + @Unique + private static void writeQuadVerticesIris(VertexBufferWriter writer, PoseStack.Pose matrices, ModelQuadView quad, int color, int light, int overlay) { + Matrix3f matNormal = matrices.normal(); + Matrix4f matPosition = matrices.pose(); + + try (MemoryStack stack = MemoryStack.stackPush()) { + long buffer = stack.nmalloc(4 * EntityVertex.STRIDE); + long ptr = buffer; + + // The packed transformed normal vector + var normal = MatrixHelper.transformNormal(matNormal, quad.getNormal()); + + float midUTemp = 0.0f, midVTemp = 0.0f; + + for (int i = 0; i < 4; i++) { + midUTemp += quad.getTexU(i); + midVTemp += quad.getTexV(i); + } + + midUTemp *= 0.25f; + midVTemp *= 0.25f; + + short midU = encodeTexture(midUTemp); + short midV = encodeTexture(midVTemp); + + VertexHistory lastPos = ((IrisBakedQuad) quad).getPrevious(); + + for (int i = 0; i < 4; i++) { + // The position vector + float x = quad.getX(i); + float y = quad.getY(i); + float z = quad.getZ(i); + + // 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.writeUnknownTangentWithVelocity(ptr, xt, yt, zt, lastPos.storedPositions[i].x, lastPos.storedPositions[i].y, lastPos.storedPositions[i].z, color, quad.getTexU(i), quad.getTexV(i), midU, midV, light, overlay, normal); + ptr += EntityVertex.STRIDE; + + if (!ShadowRenderingState.areShadowsCurrentlyBeingRendered()) lastPos.storedPositions[i].set(xt, yt, zt); + } + lastPos.lastFrame = SystemTimeUniforms.COUNTER.getAsInt(); + + writer.push(stack, buffer, 4, EntityVertex.FORMAT); + } + } + + @Unique + private final RandomSource random = new LegacyRandomSource(42L); + + @Shadow + @Final + private ItemColors itemColors; + + /** + * @reason Avoid allocations + * @author JellySquid + */ + @Inject(method = "renderModelLists", at = @At("HEAD"), cancellable = true) + private void renderModelFast(BakedModel model, ItemStack itemStack, int light, int overlay, PoseStack matrixStack, VertexConsumer vertexConsumer, CallbackInfo ci) { + var writer = VertexConsumerUtils.convertOrLog(vertexConsumer); + + if (writer == null) { + return; + } + + ci.cancel(); + + RandomSource random = this.random; + PoseStack.Pose matrices = matrixStack.last(); + + ItemColor colorProvider = null; + + if (!itemStack.isEmpty()) { + colorProvider = ((ItemColorsExtended) this.itemColors).sodium$getColorProvider(itemStack); + } + + for (Direction direction : DirectionUtil.ALL_DIRECTIONS) { + random.setSeed(42L); + List quads = model.getQuads(null, direction, random); + + if (!quads.isEmpty()) { + this.renderBakedItemQuads(matrices, writer, quads, itemStack, colorProvider, light, overlay); + } + } + + random.setSeed(42L); + List quads = model.getQuads(null, null, random); + + if (!quads.isEmpty()) { + this.renderBakedItemQuads(matrices, writer, quads, itemStack, colorProvider, light, overlay); + } + } + + @Unique + private boolean extend() { + return IrisApi.getInstance().isShaderPackInUse() && ImmediateState.renderWithExtendedVertexFormat; + } + + @Unique + @SuppressWarnings("ForLoopReplaceableByForEach") + private void renderBakedItemQuads(PoseStack.Pose matrices, VertexBufferWriter writer, List quads, ItemStack itemStack, ItemColor colorProvider, int light, int overlay) { + boolean extend = extend(); + for (int i = 0; i < quads.size(); i++) { + BakedQuad bakedQuad = quads.get(i); + BakedQuadView quad = (BakedQuadView) bakedQuad; + + int color = 0xFFFFFFFF; + + if (colorProvider != null && quad.hasColor()) { + color = ColorARGB.toABGR((colorProvider.getColor(itemStack, quad.getColorIndex())), 255); + } + + if (extend) { + writeQuadVerticesIris(writer, matrices, quad, color, light, overlay); + } else { + BakedModelEncoder.writeQuadVertices(writer, matrices, quad, color, light, overlay); + } + + + SpriteUtil.markSpriteActive(quad.getSprite()); + } + } +} diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/vertex_format/entity/MixinEntityRenderDispatcher.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/vertex_format/entity/MixinEntityRenderDispatcher.java index f100803fd9..c05af9938f 100644 --- a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/vertex_format/entity/MixinEntityRenderDispatcher.java +++ b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/vertex_format/entity/MixinEntityRenderDispatcher.java @@ -55,8 +55,8 @@ private static void renderShadowPart(PoseStack.Pose matrices, VertexConsumer ver ); } - float midU = (u1 + u2) / 2; - float midV = (v1 + v2) / 2; + short midU = encodeTexture((u1 + u2) / 2); + short midV = encodeTexture((v1 + v2) / 2); int stride = extended ? EntityVertex.STRIDE : ModelVertex.STRIDE; try (MemoryStack stack = MemoryStack.stackPush()) { @@ -93,8 +93,14 @@ private static void renderShadowPart(PoseStack.Pose matrices, VertexConsumer ver .push(stack, buffer, 4, extended ? EntityVertex.FORMAT : ModelVertex.FORMAT); } } + private static short encodeTexture(float value) { + return (short) (Math.min(0.99999997F, value) * 65536); + } + + @Unique + private static short encodedMid = encodeTexture(0.25f); - 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 writeShadowVertexIris(long ptr, Matrix4f matPosition, float x, float y, float z, float u, float v, int color, short midU, short midV, int normal, int tangent) { // The transformed position vector float xt = MatrixHelper.transformPositionX(matPosition, x, y, z); float yt = MatrixHelper.transformPositionY(matPosition, x, y, z); diff --git a/src/sodiumCompatibility/resources/mixins.iris.compat.sodium.json b/src/sodiumCompatibility/resources/mixins.iris.compat.sodium.json index 85dd77b9c2..9876fbe2ac 100644 --- a/src/sodiumCompatibility/resources/mixins.iris.compat.sodium.json +++ b/src/sodiumCompatibility/resources/mixins.iris.compat.sodium.json @@ -24,9 +24,12 @@ "options.MixinSodiumOptionsGUI", "copyEntity.CuboidMixin", "copyEntity.ModelPartMixin", + "copyEntity.BillboardParticleMixin", "copyEntity.cull.EntityRendererMixin", "copyEntity.shadows.EntityRenderDispatcherMixin", "font.MixinGlyphRenderer", + "item.MixinBakedQuad", + "item.MixinItemRenderer", "pbr_animation.MixinSpriteContents", "shader_overrides.MixinGlProgram", "shader_overrides.MixinGlRenderDevice",