diff --git a/build.gradle b/build.gradle index 3ed9804..32c48c9 100644 --- a/build.gradle +++ b/build.gradle @@ -3,14 +3,11 @@ plugins { id 'maven-publish' id "com.github.breadmoirai.github-release" version "2.4.1" - id "org.ajoberstar.grgit" version "4.1.0" + id "org.ajoberstar.grgit" version "4.1.1" id "com.modrinth.minotaur" version "2.+" id "com.matthewprenger.cursegradle" version "1.4.0" } -sourceCompatibility = JavaVersion.VERSION_21 -targetCompatibility = JavaVersion.VERSION_21 - String getGitVersion(Project project) { if (grgit != null) { var dirty = grgit.status().clean ? "" : "-dirty" @@ -36,10 +33,13 @@ String getChangelog(String githubUrl) { }.join("\n") + (githubUrl == null ? "" : "\n\nSee the full changes on Github: ${githubUrl}commits/${getGitVersion(project)}") } -archivesBaseName = project.archives_base_name version = getGitVersion(project) group = project.maven_group +base { + archivesName = project.archives_base_name +} + repositories { maven { url = "https://api.modrinth.com/maven" @@ -59,9 +59,6 @@ dependencies { // For testing in dev environment modRuntimeOnly "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - // PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs. - // You may need to force-disable transitiveness on them. - modImplementation "maven.modrinth:sodium:mc${project.sodium_minecraft_version}-${project.sodium_version}" } @@ -89,6 +86,9 @@ java { // if it is present. // If you remove this line, sources will not be generated. withSourcesJar() + + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 } jar { diff --git a/gradle.properties b/gradle.properties index 01f6f28..e1b9c7f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ maven_group=link.infra archives_base_name=indium # Dependencies # check this on https://fabricmc.net/develop/ -fabric_version=0.100.1+1.21 +fabric_version=0.102.0+1.21 sodium_version=0.5.11 sodium_minecraft_version=1.21 # Publishing metadata diff --git a/src/main/java/link/infra/indium/mixin/renderer/MixinBakedModel.java b/src/main/java/link/infra/indium/mixin/renderer/MixinBakedModel.java deleted file mode 100644 index 92d8141..0000000 --- a/src/main/java/link/infra/indium/mixin/renderer/MixinBakedModel.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 2018, 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package link.infra.indium.mixin.renderer; - -import link.infra.indium.renderer.render.AbstractBlockRenderContext; -import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel; -import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; -import net.fabricmc.fabric.impl.renderer.VanillaModelEncoder; -import net.minecraft.block.BlockState; -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.random.Random; -import net.minecraft.world.BlockRenderView; -import org.spongepowered.asm.mixin.Mixin; - -import java.util.function.Supplier; - -@Mixin(BakedModel.class) -public interface MixinBakedModel extends FabricBakedModel { - /** - * Override the fallback path to shade vanilla quads differently. - */ - @Override - default void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, RenderContext context) { - VanillaModelEncoder.emitBlockQuads((BakedModel) this, state, randomSupplier, context, ((AbstractBlockRenderContext) context).getVanillaModelEmitter()); - } -} \ No newline at end of file diff --git a/src/main/java/link/infra/indium/mixin/renderer/MixinBlockModelRenderer.java b/src/main/java/link/infra/indium/mixin/renderer/MixinBlockModelRenderer.java index 91907dd..da1049b 100644 --- a/src/main/java/link/infra/indium/mixin/renderer/MixinBlockModelRenderer.java +++ b/src/main/java/link/infra/indium/mixin/renderer/MixinBlockModelRenderer.java @@ -26,7 +26,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import link.infra.indium.renderer.accessor.AccessBlockModelRenderer; -import link.infra.indium.renderer.aocalc.VanillaAoHelper; import link.infra.indium.renderer.render.NonTerrainBlockRenderContext; import net.minecraft.block.BlockState; import net.minecraft.client.render.VertexConsumer; @@ -55,11 +54,6 @@ private void hookRender(BlockRenderView blockView, BakedModel model, BlockState } } - @Inject(at = @At("RETURN"), method = "*") - private void onInit(CallbackInfo ci) { - VanillaAoHelper.initialize((BlockModelRenderer) (Object) this); - } - @Override public void indium$getQuadDimensions(BlockRenderView blockView, BlockState blockState, BlockPos pos, int[] vertexData, Direction face, float[] aoData, BitSet controlBits) { getQuadDimensions(blockView, blockState, pos, vertexData, face, aoData, controlBits); diff --git a/src/main/java/link/infra/indium/renderer/IndiumRenderer.java b/src/main/java/link/infra/indium/renderer/IndiumRenderer.java index f178d63..6368b4d 100644 --- a/src/main/java/link/infra/indium/renderer/IndiumRenderer.java +++ b/src/main/java/link/infra/indium/renderer/IndiumRenderer.java @@ -19,6 +19,7 @@ import java.util.HashMap; import link.infra.indium.renderer.material.MaterialFinderImpl; +import link.infra.indium.renderer.material.RenderMaterialImpl; import link.infra.indium.renderer.mesh.MeshBuilderImpl; import net.fabricmc.fabric.api.renderer.v1.Renderer; import net.fabricmc.fabric.api.renderer.v1.material.MaterialFinder; @@ -59,7 +60,7 @@ public boolean registerMaterial(Identifier id, RenderMaterial material) { if (materialMap.containsKey(id)) return false; // cast to prevent acceptance of impostor implementations - materialMap.put(id, material); + materialMap.put(id, (RenderMaterialImpl) material); return true; } } diff --git a/src/main/java/link/infra/indium/renderer/aocalc/AoCalculator.java b/src/main/java/link/infra/indium/renderer/aocalc/AoCalculator.java index 992d6bd..f00a440 100644 --- a/src/main/java/link/infra/indium/renderer/aocalc/AoCalculator.java +++ b/src/main/java/link/infra/indium/renderer/aocalc/AoCalculator.java @@ -40,7 +40,6 @@ import link.infra.indium.mixin.renderer.AccessAmbientOcclusionCalculator; import link.infra.indium.renderer.aocalc.AoFace.WeightFunction; import link.infra.indium.renderer.mesh.EncodingFormat; -import link.infra.indium.renderer.mesh.MutableQuadViewImpl; import link.infra.indium.renderer.mesh.QuadViewImpl; import link.infra.indium.renderer.render.BlockRenderInfo; import me.jellysquid.mods.sodium.client.model.light.data.LightDataAccess; @@ -88,7 +87,7 @@ public class AoCalculator { public AoCalculator(BlockRenderInfo blockInfo, LightDataAccess lightCache) { this.blockInfo = blockInfo; this.lightCache = lightCache; - this.vanillaCalc = VanillaAoHelper.get(); + this.vanillaCalc = VanillaAoHelper.createCalc(); for (int i = 0; i < 24; i++) { faceData[i] = new AoFaceData(); @@ -100,41 +99,21 @@ public void clear() { completionFlags = 0; } - public void compute(MutableQuadViewImpl quad, boolean isVanilla) { + public void compute(QuadViewImpl quad, boolean vanillaShade) { final AoConfig config = Indium.AMBIENT_OCCLUSION_MODE; switch (config) { - case VANILLA: - // prevent NPE in error case of failed reflection for vanilla calculator access - if (vanillaCalc == null) { - calcFastVanilla(quad); - } else { - calcVanilla(quad); - } - - break; - - case EMULATE: - calcFastVanilla(quad); - break; - - case HYBRID: - default: - if (isVanilla) { + case VANILLA -> calcVanilla(quad); + case EMULATE -> calcFastVanilla(quad); + case HYBRID -> { + if (vanillaShade) { calcFastVanilla(quad); } else { calcEnhanced(quad); } - - break; - - case ENHANCED: - calcEnhanced(quad); } - } - - private void calcVanilla(MutableQuadViewImpl quad) { - calcVanilla(quad, ao, light); + case ENHANCED -> calcEnhanced(quad); + } } // These are what vanilla AO calc wants, per its usage in vanilla code @@ -144,7 +123,12 @@ private void calcVanilla(MutableQuadViewImpl quad) { private final BitSet vanillaAoControlBits = new BitSet(3); private final int[] vertexData = new int[EncodingFormat.QUAD_STRIDE]; - private void calcVanilla(MutableQuadViewImpl quad, float[] aoDest, int[] lightDest) { + private void calcVanilla(QuadViewImpl quad) { + if (vanillaCalc == null) { + calcFastVanilla(quad); + return; + } + vanillaAoControlBits.clear(); final Direction lightFace = quad.lightFace(); quad.toVanilla(vertexData, 0); @@ -152,11 +136,11 @@ private void calcVanilla(MutableQuadViewImpl quad, float[] aoDest, int[] lightDe VanillaAoHelper.getQuadDimensions(blockInfo.blockView, blockInfo.blockState, blockInfo.blockPos, vertexData, lightFace, vanillaAoData, vanillaAoControlBits); vanillaCalc.indium$apply(blockInfo.blockView, blockInfo.blockState, blockInfo.blockPos, lightFace, vanillaAoData, vanillaAoControlBits, quad.hasShade()); - System.arraycopy(vanillaCalc.indium$brightness(), 0, aoDest, 0, 4); - System.arraycopy(vanillaCalc.indium$light(), 0, lightDest, 0, 4); + System.arraycopy(vanillaCalc.indium$brightness(), 0, ao, 0, 4); + System.arraycopy(vanillaCalc.indium$light(), 0, light, 0, 4); } - private void calcFastVanilla(MutableQuadViewImpl quad) { + private void calcFastVanilla(QuadViewImpl quad) { int flags = quad.geometryFlags(); // force to block face if shape is full cube - matches vanilla logic @@ -171,7 +155,7 @@ private void calcFastVanilla(MutableQuadViewImpl quad) { } } - private void calcEnhanced(MutableQuadViewImpl quad) { + private void calcEnhanced(QuadViewImpl quad) { switch (quad.geometryFlags()) { case AXIS_ALIGNED_FLAG | CUBIC_FLAG | LIGHT_FACE_FLAG: case AXIS_ALIGNED_FLAG | LIGHT_FACE_FLAG: @@ -246,7 +230,7 @@ private void blendedPartialFace(QuadViewImpl quad, Direction lightFace, boolean /** used exclusively in irregular face to avoid new heap allocations each call. */ private final Vector3f vertexNormal = new Vector3f(); - private void irregularFace(MutableQuadViewImpl quad, boolean shade) { + private void irregularFace(QuadViewImpl quad, boolean shade) { final Vector3f faceNorm = quad.faceNormal(); Vector3f normal; final float[] w = this.w; diff --git a/src/main/java/link/infra/indium/renderer/aocalc/VanillaAoHelper.java b/src/main/java/link/infra/indium/renderer/aocalc/VanillaAoHelper.java index cbd06a5..d16b515 100644 --- a/src/main/java/link/infra/indium/renderer/aocalc/VanillaAoHelper.java +++ b/src/main/java/link/infra/indium/renderer/aocalc/VanillaAoHelper.java @@ -27,38 +27,36 @@ import link.infra.indium.renderer.accessor.AccessBlockModelRenderer; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.block.BlockState; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.block.BlockModelRenderer; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.BlockRenderView; public class VanillaAoHelper { - private static Supplier factory; - // Renderer method we call isn't declared as static, but uses no // instance data and is called from multiple threads in vanilla also. - private static AccessBlockModelRenderer blockRenderer; - - public static void initialize(BlockModelRenderer instance) { - blockRenderer = (AccessBlockModelRenderer) instance; + private static final AccessBlockModelRenderer BLOCK_RENDERER = (AccessBlockModelRenderer) MinecraftClient.getInstance().getBlockRenderManager().getModelRenderer(); + @Nullable + private static final Supplier FACTORY; + static { final String target = FabricLoader.getInstance().getMappingResolver() .mapClassName("intermediary", "net.minecraft.class_778$class_780"); + Supplier factory = null; + for (Class innerClass : BlockModelRenderer.class.getDeclaredClasses()) { if (innerClass.getName().equals(target)) { Constructor constructor = innerClass.getDeclaredConstructors()[0]; constructor.setAccessible(true); - factory = new Supplier() { - @Override - public AccessAmbientOcclusionCalculator get() { - try { - return (AccessAmbientOcclusionCalculator) constructor.newInstance(); - } catch (Exception e) { - Indium.LOGGER.warn("[Indium] Exception accessing vanilla smooth lighter", e); - return null; - } + factory = () -> { + try { + return (AccessAmbientOcclusionCalculator) constructor.newInstance(); + } catch (Exception e) { + Indium.LOGGER.warn("[Indium] Exception creating vanilla smooth lighter", e); + return null; } }; break; @@ -72,14 +70,16 @@ public AccessAmbientOcclusionCalculator get() { if (factory == null) { Indium.LOGGER.warn("[Indium] Vanilla smooth lighter unavailable. Indium lighter will be used even if not configured."); } + + FACTORY = factory; } @Nullable - public static AccessAmbientOcclusionCalculator get() { - return factory == null ? null : factory.get(); + public static AccessAmbientOcclusionCalculator createCalc() { + return FACTORY == null ? null : FACTORY.get(); } public static void getQuadDimensions(BlockRenderView blockRenderView, BlockState blockState, BlockPos pos, int[] vertexData, Direction face, float[] aoData, BitSet controlBits) { - blockRenderer.indium$getQuadDimensions(blockRenderView, blockState, pos, vertexData, face, aoData, controlBits); + BLOCK_RENDERER.indium$getQuadDimensions(blockRenderView, blockState, pos, vertexData, face, aoData, controlBits); } } diff --git a/src/main/java/link/infra/indium/renderer/helper/VanillaModelEncoder.java b/src/main/java/link/infra/indium/renderer/helper/VanillaModelEncoder.java new file mode 100644 index 0000000..ee37fe0 --- /dev/null +++ b/src/main/java/link/infra/indium/renderer/helper/VanillaModelEncoder.java @@ -0,0 +1,70 @@ +package link.infra.indium.renderer.helper; + +import java.util.List; +import java.util.function.Supplier; + +import org.jetbrains.annotations.Nullable; + +import net.fabricmc.fabric.api.renderer.v1.Renderer; +import net.fabricmc.fabric.api.renderer.v1.RendererAccess; +import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; +import net.fabricmc.fabric.api.renderer.v1.material.ShadeMode; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; +import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper; +import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; +import net.fabricmc.fabric.api.util.TriState; +import net.minecraft.block.BlockState; +import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.render.model.BakedQuad; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.random.Random; + +/** + * Routines for adaptation of vanilla {@link BakedModel}s to FRAPI pipelines. + * Copy of {@link net.fabricmc.fabric.impl.renderer.VanillaModelEncoder} to avoid issues if the Fabric impl class receives changes. + */ +public class VanillaModelEncoder { + private static final Renderer RENDERER = RendererAccess.INSTANCE.getRenderer(); + private static final RenderMaterial STANDARD_MATERIAL = RENDERER.materialFinder().shadeMode(ShadeMode.VANILLA).find(); + private static final RenderMaterial NO_AO_MATERIAL = RENDERER.materialFinder().shadeMode(ShadeMode.VANILLA).ambientOcclusion(TriState.FALSE).find(); + + public static void emitBlockQuads(BakedModel model, @Nullable BlockState state, Supplier randomSupplier, RenderContext context) { + QuadEmitter emitter = context.getEmitter(); + final RenderMaterial defaultMaterial = model.useAmbientOcclusion() ? STANDARD_MATERIAL : NO_AO_MATERIAL; + + for (int i = 0; i <= ModelHelper.NULL_FACE_ID; i++) { + final Direction cullFace = ModelHelper.faceFromIndex(i); + + if (!context.hasTransform() && context.isFaceCulled(cullFace)) { + // Skip entire quad list if possible. + continue; + } + + final List quads = model.getQuads(state, cullFace, randomSupplier.get()); + final int count = quads.size(); + + for (int j = 0; j < count; j++) { + final BakedQuad q = quads.get(j); + emitter.fromVanilla(q, defaultMaterial, cullFace); + emitter.emit(); + } + } + } + + public static void emitItemQuads(BakedModel model, @Nullable BlockState state, Supplier randomSupplier, RenderContext context) { + QuadEmitter emitter = context.getEmitter(); + + for (int i = 0; i <= ModelHelper.NULL_FACE_ID; i++) { + final Direction cullFace = ModelHelper.faceFromIndex(i); + final List quads = model.getQuads(state, cullFace, randomSupplier.get()); + final int count = quads.size(); + + for (int j = 0; j < count; j++) { + final BakedQuad q = quads.get(j); + emitter.fromVanilla(q, STANDARD_MATERIAL, cullFace); + emitter.emit(); + } + } + } +} + diff --git a/src/main/java/link/infra/indium/renderer/material/MaterialFinderImpl.java b/src/main/java/link/infra/indium/renderer/material/MaterialFinderImpl.java index 2797f8d..6bd64db 100644 --- a/src/main/java/link/infra/indium/renderer/material/MaterialFinderImpl.java +++ b/src/main/java/link/infra/indium/renderer/material/MaterialFinderImpl.java @@ -22,6 +22,7 @@ import net.fabricmc.fabric.api.renderer.v1.material.MaterialFinder; import net.fabricmc.fabric.api.renderer.v1.material.MaterialView; import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; +import net.fabricmc.fabric.api.renderer.v1.material.ShadeMode; import net.fabricmc.fabric.api.util.TriState; public class MaterialFinderImpl extends MaterialViewImpl implements MaterialFinder { @@ -84,6 +85,14 @@ public MaterialFinder glint(TriState mode) { return this; } + @Override + public MaterialFinder shadeMode(ShadeMode mode) { + Objects.requireNonNull(mode, "ShadeMode may not be null"); + + bits = (bits & ~SHADE_MODE_MASK) | (mode.ordinal() << SHADE_MODE_BIT_OFFSET); + return this; + } + @Override public MaterialFinder copyFrom(MaterialView material) { bits = ((MaterialViewImpl) material).bits; diff --git a/src/main/java/link/infra/indium/renderer/material/MaterialViewImpl.java b/src/main/java/link/infra/indium/renderer/material/MaterialViewImpl.java index fa7f583..40d614f 100644 --- a/src/main/java/link/infra/indium/renderer/material/MaterialViewImpl.java +++ b/src/main/java/link/infra/indium/renderer/material/MaterialViewImpl.java @@ -16,8 +16,11 @@ package link.infra.indium.renderer.material; +import static link.infra.indium.renderer.mesh.EncodingFormat.bitMask; + import net.fabricmc.fabric.api.renderer.v1.material.BlendMode; import net.fabricmc.fabric.api.renderer.v1.material.MaterialView; +import net.fabricmc.fabric.api.renderer.v1.material.ShadeMode; import net.fabricmc.fabric.api.util.TriState; import net.minecraft.util.math.MathHelper; @@ -32,6 +35,8 @@ public class MaterialViewImpl implements MaterialView { private static final int BLEND_MODE_COUNT = BLEND_MODES.length; private static final TriState[] TRI_STATES = TriState.values(); private static final int TRI_STATE_COUNT = TRI_STATES.length; + private static final ShadeMode[] SHADE_MODES = ShadeMode.values(); + private static final int SHADE_MODE_COUNT = SHADE_MODES.length; protected static final int BLEND_MODE_BIT_LENGTH = MathHelper.ceilLog2(BLEND_MODE_COUNT); protected static final int COLOR_DISABLE_BIT_LENGTH = 1; @@ -39,6 +44,7 @@ public class MaterialViewImpl implements MaterialView { protected static final int DIFFUSE_BIT_LENGTH = 1; protected static final int AO_BIT_LENGTH = MathHelper.ceilLog2(TRI_STATE_COUNT); protected static final int GLINT_BIT_LENGTH = MathHelper.ceilLog2(TRI_STATE_COUNT); + protected static final int SHADE_MODE_BIT_LENGTH = MathHelper.ceilLog2(SHADE_MODE_COUNT); protected static final int BLEND_MODE_BIT_OFFSET = 0; protected static final int COLOR_DISABLE_BIT_OFFSET = BLEND_MODE_BIT_OFFSET + BLEND_MODE_BIT_LENGTH; @@ -46,7 +52,8 @@ public class MaterialViewImpl implements MaterialView { protected static final int DIFFUSE_BIT_OFFSET = EMISSIVE_BIT_OFFSET + EMISSIVE_BIT_LENGTH; protected static final int AO_BIT_OFFSET = DIFFUSE_BIT_OFFSET + DIFFUSE_BIT_LENGTH; protected static final int GLINT_BIT_OFFSET = AO_BIT_OFFSET + AO_BIT_LENGTH; - protected static final int TOTAL_BIT_LENGTH = GLINT_BIT_OFFSET + GLINT_BIT_LENGTH; + protected static final int SHADE_MODE_BIT_OFFSET = GLINT_BIT_OFFSET + GLINT_BIT_LENGTH; + public static final int TOTAL_BIT_LENGTH = SHADE_MODE_BIT_OFFSET + SHADE_MODE_BIT_LENGTH; protected static final int BLEND_MODE_MASK = bitMask(BLEND_MODE_BIT_LENGTH, BLEND_MODE_BIT_OFFSET); protected static final int COLOR_DISABLE_FLAG = bitMask(COLOR_DISABLE_BIT_LENGTH, COLOR_DISABLE_BIT_OFFSET); @@ -54,19 +61,18 @@ public class MaterialViewImpl implements MaterialView { protected static final int DIFFUSE_FLAG = bitMask(DIFFUSE_BIT_LENGTH, DIFFUSE_BIT_OFFSET); protected static final int AO_MASK = bitMask(AO_BIT_LENGTH, AO_BIT_OFFSET); protected static final int GLINT_MASK = bitMask(GLINT_BIT_LENGTH, GLINT_BIT_OFFSET); - - protected static int bitMask(int bitLength, int bitOffset) { - return ((1 << bitLength) - 1) << bitOffset; - } + protected static final int SHADE_MODE_MASK = bitMask(SHADE_MODE_BIT_LENGTH, SHADE_MODE_BIT_OFFSET); protected static boolean areBitsValid(int bits) { int blendMode = (bits & BLEND_MODE_MASK) >>> BLEND_MODE_BIT_OFFSET; int ao = (bits & AO_MASK) >>> AO_BIT_OFFSET; int glint = (bits & GLINT_MASK) >>> GLINT_BIT_OFFSET; + int shadeMode = (bits & SHADE_MODE_MASK) >>> SHADE_MODE_BIT_OFFSET; return blendMode < BLEND_MODE_COUNT && ao < TRI_STATE_COUNT - && glint < TRI_STATE_COUNT; + && glint < TRI_STATE_COUNT + && shadeMode < SHADE_MODE_COUNT; } protected int bits; @@ -104,4 +110,9 @@ public TriState ambientOcclusion() { public TriState glint() { return TRI_STATES[(bits & GLINT_MASK) >>> GLINT_BIT_OFFSET]; } + + @Override + public ShadeMode shadeMode() { + return SHADE_MODES[(bits & SHADE_MODE_MASK) >>> SHADE_MODE_BIT_OFFSET]; + } } diff --git a/src/main/java/link/infra/indium/renderer/mesh/EncodingFormat.java b/src/main/java/link/infra/indium/renderer/mesh/EncodingFormat.java index a16627f..6be395d 100644 --- a/src/main/java/link/infra/indium/renderer/mesh/EncodingFormat.java +++ b/src/main/java/link/infra/indium/renderer/mesh/EncodingFormat.java @@ -16,8 +16,12 @@ package link.infra.indium.renderer.mesh; +import org.jetbrains.annotations.Nullable; + import com.google.common.base.Preconditions; + import link.infra.indium.renderer.helper.GeometryHelper; +import link.infra.indium.renderer.material.MaterialViewImpl; import link.infra.indium.renderer.material.RenderMaterialImpl; import me.jellysquid.mods.sodium.client.model.quad.properties.ModelQuadFacing; import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView; @@ -77,78 +81,87 @@ private EncodingFormat() { } /** used for quick clearing of quad buffers. */ static final int[] EMPTY = new int[TOTAL_STRIDE]; - private static final int DIRECTION_MASK = MathHelper.smallestEncompassingPowerOfTwo(ModelHelper.NULL_FACE_ID + 1) - 1; - private static final int DIRECTION_BIT_COUNT = Integer.bitCount(DIRECTION_MASK); - private static final int FACING_MASK = MathHelper.smallestEncompassingPowerOfTwo(ModelQuadFacing.COUNT) - 1; - private static final int FACING_BIT_COUNT = Integer.bitCount(FACING_MASK); - private static final int CULL_SHIFT = 0; - private static final int CULL_INVERSE_MASK = ~(DIRECTION_MASK << CULL_SHIFT); - private static final int LIGHT_SHIFT = CULL_SHIFT + DIRECTION_BIT_COUNT; - private static final int LIGHT_INVERSE_MASK = ~(DIRECTION_MASK << LIGHT_SHIFT); - private static final int NORMAL_FACE_SHIFT = LIGHT_SHIFT + DIRECTION_BIT_COUNT; - private static final int NORMAL_FACE_INVERSE_MASK = ~(FACING_MASK << NORMAL_FACE_SHIFT); - private static final int NORMALS_SHIFT = NORMAL_FACE_SHIFT + FACING_BIT_COUNT; - private static final int NORMALS_COUNT = 4; - private static final int NORMALS_MASK = (1 << NORMALS_COUNT) - 1; - private static final int NORMALS_INVERSE_MASK = ~(NORMALS_MASK << NORMALS_SHIFT); - private static final int GEOMETRY_SHIFT = NORMALS_SHIFT + NORMALS_COUNT; - private static final int GEOMETRY_MASK = (1 << GeometryHelper.FLAG_BIT_COUNT) - 1; - private static final int GEOMETRY_INVERSE_MASK = ~(GEOMETRY_MASK << GEOMETRY_SHIFT); - private static final int MATERIAL_SHIFT = GEOMETRY_SHIFT + GeometryHelper.FLAG_BIT_COUNT; - private static final int MATERIAL_MASK = MathHelper.smallestEncompassingPowerOfTwo(RenderMaterialImpl.VALUE_COUNT) - 1; - private static final int MATERIAL_BIT_COUNT = Integer.bitCount(MATERIAL_MASK); - private static final int MATERIAL_INVERSE_MASK = ~(MATERIAL_MASK << MATERIAL_SHIFT); + private static final int DIRECTION_COUNT = Direction.values().length; + private static final int NULLABLE_DIRECTION_COUNT = DIRECTION_COUNT + 1; + private static final int MODEL_QUAD_FACING_COUNT = ModelQuadFacing.COUNT; + + private static final int CULL_BIT_LENGTH = MathHelper.ceilLog2(NULLABLE_DIRECTION_COUNT); + private static final int LIGHT_BIT_LENGTH = MathHelper.ceilLog2(DIRECTION_COUNT); + private static final int NORMAL_FACE_BIT_LENGTH = MathHelper.ceilLog2(MODEL_QUAD_FACING_COUNT); + private static final int NORMALS_BIT_LENGTH = 4; + private static final int GEOMETRY_BIT_LENGTH = GeometryHelper.FLAG_BIT_COUNT; + private static final int MATERIAL_BIT_LENGTH = MaterialViewImpl.TOTAL_BIT_LENGTH; + + private static final int CULL_BIT_OFFSET = 0; + private static final int LIGHT_BIT_OFFSET = CULL_BIT_OFFSET + CULL_BIT_LENGTH; + private static final int NORMAL_FACE_BIT_OFFSET = LIGHT_BIT_OFFSET + LIGHT_BIT_LENGTH; + private static final int NORMALS_BIT_OFFSET = NORMAL_FACE_BIT_OFFSET + NORMAL_FACE_BIT_LENGTH; + private static final int GEOMETRY_BIT_OFFSET = NORMALS_BIT_OFFSET + NORMALS_BIT_LENGTH; + private static final int MATERIAL_BIT_OFFSET = GEOMETRY_BIT_OFFSET + GEOMETRY_BIT_LENGTH; + private static final int TOTAL_BIT_LENGTH = MATERIAL_BIT_OFFSET + MATERIAL_BIT_LENGTH; + + private static final int CULL_MASK = bitMask(CULL_BIT_LENGTH, CULL_BIT_OFFSET); + private static final int LIGHT_MASK = bitMask(LIGHT_BIT_LENGTH, LIGHT_BIT_OFFSET); + private static final int NORMAL_FACE_MASK = bitMask(NORMAL_FACE_BIT_LENGTH, NORMAL_FACE_BIT_OFFSET); + private static final int NORMALS_MASK = bitMask(NORMALS_BIT_LENGTH, NORMALS_BIT_OFFSET); + private static final int GEOMETRY_MASK = bitMask(GEOMETRY_BIT_LENGTH, GEOMETRY_BIT_OFFSET); + private static final int MATERIAL_MASK = bitMask(MATERIAL_BIT_LENGTH, MATERIAL_BIT_OFFSET); static { - Preconditions.checkArgument(MATERIAL_SHIFT + MATERIAL_BIT_COUNT <= 32, "Indium header encoding bit count (%s) exceeds integer bit length)", TOTAL_STRIDE); + Preconditions.checkArgument(TOTAL_BIT_LENGTH <= 32, "Indium header encoding bit count (%s) exceeds integer bit length)", TOTAL_STRIDE); + } + + public static int bitMask(int bitLength, int bitOffset) { + return ((1 << bitLength) - 1) << bitOffset; } + @Nullable static Direction cullFace(int bits) { - return ModelHelper.faceFromIndex((bits >>> CULL_SHIFT) & DIRECTION_MASK); + return ModelHelper.faceFromIndex((bits & CULL_MASK) >>> CULL_BIT_OFFSET); } - static int cullFace(int bits, Direction face) { - return (bits & CULL_INVERSE_MASK) | (ModelHelper.toFaceIndex(face) << CULL_SHIFT); + static int cullFace(int bits, @Nullable Direction face) { + return (bits & ~CULL_MASK) | (ModelHelper.toFaceIndex(face) << CULL_BIT_OFFSET); } static Direction lightFace(int bits) { - return ModelHelper.faceFromIndex((bits >>> LIGHT_SHIFT) & DIRECTION_MASK); + return ModelHelper.faceFromIndex((bits & LIGHT_MASK) >>> LIGHT_BIT_OFFSET); } static int lightFace(int bits, Direction face) { - return (bits & LIGHT_INVERSE_MASK) | (ModelHelper.toFaceIndex(face) << LIGHT_SHIFT); + return (bits & ~LIGHT_MASK) | (ModelHelper.toFaceIndex(face) << LIGHT_BIT_OFFSET); } static ModelQuadFacing normalFace(int bits) { - return ModelQuadFacing.VALUES[(bits >>> NORMAL_FACE_SHIFT) & FACING_MASK]; + return ModelQuadFacing.VALUES[(bits & NORMAL_FACE_MASK) >>> NORMAL_FACE_BIT_OFFSET]; } static int normalFace(int bits, ModelQuadFacing face) { - return (bits & NORMAL_FACE_INVERSE_MASK) | (face.ordinal() << NORMAL_FACE_SHIFT); + return (bits & ~NORMAL_FACE_MASK) | (face.ordinal() << NORMAL_FACE_BIT_OFFSET); } /** indicate if vertex normal has been set - bits correspond to vertex ordinals. */ static int normalFlags(int bits) { - return (bits >>> NORMALS_SHIFT) & NORMALS_MASK; + return (bits & NORMALS_MASK) >>> NORMALS_BIT_OFFSET; } static int normalFlags(int bits, int normalFlags) { - return (bits & NORMALS_INVERSE_MASK) | ((normalFlags & NORMALS_MASK) << NORMALS_SHIFT); + return (bits & ~NORMALS_MASK) | ((normalFlags << NORMALS_BIT_OFFSET) & NORMALS_MASK); } static int geometryFlags(int bits) { - return (bits >>> GEOMETRY_SHIFT) & GEOMETRY_MASK; + return (bits & GEOMETRY_MASK) >>> GEOMETRY_BIT_OFFSET; } static int geometryFlags(int bits, int geometryFlags) { - return (bits & GEOMETRY_INVERSE_MASK) | ((geometryFlags & GEOMETRY_MASK) << GEOMETRY_SHIFT); + return (bits & ~GEOMETRY_MASK) | ((geometryFlags << GEOMETRY_BIT_OFFSET) & GEOMETRY_MASK); } static RenderMaterialImpl material(int bits) { - return RenderMaterialImpl.byIndex((bits >>> MATERIAL_SHIFT) & MATERIAL_MASK); + return RenderMaterialImpl.byIndex((bits & MATERIAL_MASK) >>> MATERIAL_BIT_OFFSET); } static int material(int bits, RenderMaterialImpl material) { - return (bits & MATERIAL_INVERSE_MASK) | (material.index() << MATERIAL_SHIFT); + return (bits & ~MATERIAL_MASK) | (material.index() << MATERIAL_BIT_OFFSET); } } diff --git a/src/main/java/link/infra/indium/renderer/render/AbstractBlockRenderContext.java b/src/main/java/link/infra/indium/renderer/render/AbstractBlockRenderContext.java index 38daacc..4fac4ed 100644 --- a/src/main/java/link/infra/indium/renderer/render/AbstractBlockRenderContext.java +++ b/src/main/java/link/infra/indium/renderer/render/AbstractBlockRenderContext.java @@ -16,19 +16,26 @@ package link.infra.indium.renderer.render; +import static link.infra.indium.renderer.helper.GeometryHelper.AXIS_ALIGNED_FLAG; +import static link.infra.indium.renderer.helper.GeometryHelper.LIGHT_FACE_FLAG; + +import org.jetbrains.annotations.Nullable; +import org.joml.Vector3f; + import link.infra.indium.Indium; import link.infra.indium.renderer.aocalc.AoCalculator; import link.infra.indium.renderer.aocalc.AoConfig; import link.infra.indium.renderer.helper.ColorHelper; +import link.infra.indium.renderer.helper.VanillaModelEncoder; import link.infra.indium.renderer.mesh.EncodingFormat; import link.infra.indium.renderer.mesh.MutableQuadViewImpl; import me.jellysquid.mods.sodium.client.model.light.data.LightDataAccess; import me.jellysquid.mods.sodium.client.render.chunk.terrain.material.DefaultMaterials; import me.jellysquid.mods.sodium.client.render.chunk.terrain.material.Material; import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; +import net.fabricmc.fabric.api.renderer.v1.material.ShadeMode; import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; import net.fabricmc.fabric.api.util.TriState; -import net.fabricmc.fabric.impl.renderer.VanillaModelEncoder; import net.minecraft.block.BlockState; import net.minecraft.client.render.LightmapTextureManager; import net.minecraft.client.render.RenderLayer; @@ -38,11 +45,6 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.BlockRenderView; -import org.jetbrains.annotations.Nullable; -import org.joml.Vector3f; - -import static link.infra.indium.renderer.helper.GeometryHelper.AXIS_ALIGNED_FLAG; -import static link.infra.indium.renderer.helper.GeometryHelper.LIGHT_FACE_FLAG; /** * Subclasses must set the {@link #blockInfo} and {@link #aoCalc} fields in their constructor. @@ -59,19 +61,7 @@ public abstract class AbstractBlockRenderContext extends AbstractRenderContext { @Override public void emitDirectly() { - renderQuad(this, false); - } - }; - - private final MutableQuadViewImpl vanillaModelEditorQuad = new MutableQuadViewImpl() { - { - data = new int[EncodingFormat.TOTAL_STRIDE]; - clear(); - } - - @Override - public void emitDirectly() { - renderQuad(this, true); + renderQuad(this); } }; @@ -87,11 +77,6 @@ public QuadEmitter getEmitter() { return editorQuad; } - public QuadEmitter getVanillaModelEmitter() { - // Do not clear the editorQuad since it is not accessible to API users. - return vanillaModelEditorQuad; - } - @Override public boolean isFaceCulled(@Nullable Direction face) { return !blockInfo.shouldDrawFace(face); @@ -107,7 +92,7 @@ public BakedModelConsumer bakedModelConsumer() { return vanillaModelConsumer; } - private void renderQuad(MutableQuadViewImpl quad, boolean isVanilla) { + private void renderQuad(MutableQuadViewImpl quad) { if (!transform(quad)) { return; } @@ -121,11 +106,12 @@ private void renderQuad(MutableQuadViewImpl quad, boolean isVanilla) { final TriState aoMode = mat.ambientOcclusion(); final boolean ao = blockInfo.useAo && (aoMode == TriState.TRUE || (aoMode == TriState.DEFAULT && blockInfo.defaultAo)); final boolean emissive = mat.emissive(); + final boolean vanillaShade = mat.shadeMode() == ShadeMode.VANILLA; final RenderLayer renderLayer = blockInfo.effectiveRenderLayer(mat.blendMode()); final Material sodiumMaterial = DefaultMaterials.forRenderLayer(renderLayer); colorizeQuad(quad, colorIndex); - shadeQuad(quad, isVanilla, ao, emissive); + shadeQuad(quad, ao, emissive, vanillaShade); bufferQuad(quad, sodiumMaterial); } @@ -140,10 +126,10 @@ private void colorizeQuad(MutableQuadViewImpl quad, int colorIndex) { } } - protected void shadeQuad(MutableQuadViewImpl quad, boolean isVanilla, boolean ao, boolean emissive) { + protected void shadeQuad(MutableQuadViewImpl quad, boolean ao, boolean emissive, boolean vanillaShade) { // routines below have a bit of copy-paste code reuse to avoid conditional execution inside a hot loop if (ao) { - aoCalc.compute(quad, isVanilla); + aoCalc.compute(quad, vanillaShade); if (emissive) { for (int i = 0; i < 4; i++) { @@ -157,7 +143,7 @@ protected void shadeQuad(MutableQuadViewImpl quad, boolean isVanilla, boolean ao } } } else { - shadeFlatQuad(quad, isVanilla); + shadeFlatQuad(quad, vanillaShade); if (emissive) { for (int i = 0; i < 4; i++) { @@ -177,11 +163,11 @@ protected void shadeQuad(MutableQuadViewImpl quad, boolean isVanilla, boolean ao * Starting in 1.16 flat shading uses dimension-specific diffuse factors that can be < 1.0 * even for un-shaded quads. These are also applied with AO shading but that is done in AO calculator. */ - private void shadeFlatQuad(MutableQuadViewImpl quad, boolean isVanilla) { + private void shadeFlatQuad(MutableQuadViewImpl quad, boolean vanillaShade) { final boolean hasShade = quad.hasShade(); // Check the AO mode to match how shade is applied during smooth lighting - if ((Indium.AMBIENT_OCCLUSION_MODE == AoConfig.HYBRID && !isVanilla) || Indium.AMBIENT_OCCLUSION_MODE == AoConfig.ENHANCED) { + if ((Indium.AMBIENT_OCCLUSION_MODE == AoConfig.HYBRID && !vanillaShade) || Indium.AMBIENT_OCCLUSION_MODE == AoConfig.ENHANCED) { if (quad.hasAllVertexNormals()) { for (int i = 0; i < 4; i++) { float shade = normalShade(quad.normalX(i), quad.normalY(i), quad.normalZ(i), hasShade); @@ -326,7 +312,7 @@ public void accept(BakedModel model) { @Override public void accept(BakedModel model, @Nullable BlockState state) { - VanillaModelEncoder.emitBlockQuads(model, state, blockInfo.randomSupplier, AbstractBlockRenderContext.this, vanillaModelEditorQuad); + VanillaModelEncoder.emitBlockQuads(model, state, blockInfo.randomSupplier, AbstractBlockRenderContext.this); } } } diff --git a/src/main/java/link/infra/indium/renderer/render/ItemRenderContext.java b/src/main/java/link/infra/indium/renderer/render/ItemRenderContext.java index 2db9f8e..80751ce 100644 --- a/src/main/java/link/infra/indium/renderer/render/ItemRenderContext.java +++ b/src/main/java/link/infra/indium/renderer/render/ItemRenderContext.java @@ -16,19 +16,28 @@ package link.infra.indium.renderer.render; +import java.util.function.Supplier; + +import org.jetbrains.annotations.Nullable; + import link.infra.indium.mixin.renderer.ItemRendererAccessor; import link.infra.indium.renderer.helper.ColorHelper; +import link.infra.indium.renderer.helper.VanillaModelEncoder; import link.infra.indium.renderer.mesh.EncodingFormat; import link.infra.indium.renderer.mesh.MutableQuadViewImpl; import net.fabricmc.fabric.api.renderer.v1.material.BlendMode; import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; import net.fabricmc.fabric.api.util.TriState; -import net.fabricmc.fabric.impl.renderer.VanillaModelEncoder; import net.minecraft.block.BlockState; import net.minecraft.client.MinecraftClient; import net.minecraft.client.color.item.ItemColors; -import net.minecraft.client.render.*; +import net.minecraft.client.render.LightmapTextureManager; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.RenderLayers; +import net.minecraft.client.render.TexturedRenderLayers; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.item.ItemRenderer; import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.json.ModelTransformationMode; @@ -40,9 +49,6 @@ import net.minecraft.util.math.MatrixUtil; import net.minecraft.util.math.random.LocalRandom; import net.minecraft.util.math.random.Random; -import org.jetbrains.annotations.Nullable; - -import java.util.function.Supplier; /** * The render context used for item rendering. diff --git a/src/main/java/link/infra/indium/renderer/render/TerrainRenderContext.java b/src/main/java/link/infra/indium/renderer/render/TerrainRenderContext.java index 86b3ff1..fc51146 100644 --- a/src/main/java/link/infra/indium/renderer/render/TerrainRenderContext.java +++ b/src/main/java/link/infra/indium/renderer/render/TerrainRenderContext.java @@ -98,8 +98,8 @@ protected void bufferQuad(MutableQuadViewImpl quad, Material material) { } @Override - protected void shadeQuad(MutableQuadViewImpl quad, boolean isVanilla, boolean ao, boolean emissive) { - super.shadeQuad(quad, isVanilla, ao, emissive); + protected void shadeQuad(MutableQuadViewImpl quad, boolean ao, boolean emissive, boolean vanillaShade) { + super.shadeQuad(quad, ao, emissive, vanillaShade); if (ao) { // Assumes aoCalc.ao / aoCalc.light holds the correct values for the current quad. diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index c1747e3..c2af37b 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -30,7 +30,7 @@ "fabricloader": ">=0.8.0", "minecraft": "~1.21.0", "sodium": "0.5.11", - "fabric-renderer-api-v1": ">=3.2.0", + "fabric-renderer-api-v1": ">=3.4.0", "fabric-resource-loader-v0": ">=0.4.0" } } diff --git a/src/main/resources/indium.mixins.json b/src/main/resources/indium.mixins.json index 615f984..eb8a554 100644 --- a/src/main/resources/indium.mixins.json +++ b/src/main/resources/indium.mixins.json @@ -6,7 +6,6 @@ "renderer.AccessAmbientOcclusionCalculator", "renderer.MixinBlockModelRenderer", "renderer.MixinItemRenderer", - "renderer.MixinBakedModel", "renderer.ItemRendererAccessor", "sodium.AccessBlockRenderer", "sodium.MixinBlockRenderCache",