From c705a49cc5703f4e9e476e1165cc6dfcb812cd33 Mon Sep 17 00:00:00 2001 From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com> Date: Sun, 4 Aug 2024 06:52:02 -0600 Subject: [PATCH] Add `ShadeMode` to FRAPI (#3937) * Add ShadeMode to the API - Update material documentation - Use ShadeMode in VanillaModelEncoder * Add ShadeMode support to Indigo - Rewrite header packing constants in EncodingFormat to match material packing constants - Pass buffer Function to TerrainRenderContext instead of allocators and buffer map - Restore functionality of ChunkRenderInfo#release - Set captured terrain context to null after releasing it - Bump mixin compatibility level to Java 21 - Remove unused AWs * Add test for ShadeMode - Fix RiverstoneUnbakedModel not calling setParents on models that it will bake * Clarify documentation of inverted material properties --- .../api/renderer/v1/material/BlendMode.java | 6 +- .../renderer/v1/material/MaterialFinder.java | 59 ++++++++++++---- .../renderer/v1/material/MaterialView.java | 9 +++ .../api/renderer/v1/material/ShadeMode.java | 36 ++++++++++ .../renderer/v1/model/FabricBakedModel.java | 2 +- .../api/renderer/v1/model/ModelHelper.java | 4 +- .../impl/renderer/VanillaModelEncoder.java | 13 ++-- .../fabric-renderer-api-v1.mixins.json | 2 +- .../test/renderer/OctagonalColumnBlock.java | 36 ++++++++++ .../fabric/test/renderer/Registration.java | 2 +- .../renderer/client/ModelResolverImpl.java | 11 ++- .../client/OctagonalColumnUnbakedModel.java | 11 ++- .../client/RiverstoneUnbakedModel.java | 2 + .../blockstates/octagonal_column.json | 3 +- .../indigo/renderer/IndigoRenderer.java | 3 +- .../indigo/renderer/aocalc/AoCalculator.java | 45 ++++-------- .../renderer/material/MaterialFinderImpl.java | 9 +++ .../renderer/material/MaterialViewImpl.java | 23 +++++-- .../indigo/renderer/mesh/EncodingFormat.java | 69 +++++++++++-------- .../render/AbstractBlockRenderContext.java | 36 +++------- .../renderer/render/ChunkRenderInfo.java | 34 +++------ .../renderer/render/TerrainRenderContext.java | 9 ++- .../indigo/renderer/BakedModelMixin.java | 43 ------------ .../indigo/renderer/SectionBuilderMixin.java | 31 ++++----- .../fabric-renderer-indigo.accesswidener | 4 -- .../fabric-renderer-indigo.mixins.json | 3 +- 26 files changed, 288 insertions(+), 217 deletions(-) create mode 100644 fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/material/ShadeMode.java create mode 100644 fabric-renderer-api-v1/src/testmod/java/net/fabricmc/fabric/test/renderer/OctagonalColumnBlock.java delete mode 100644 fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/BakedModelMixin.java diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/material/BlendMode.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/material/BlendMode.java index 4ee361c04..feab8ae7f 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/material/BlendMode.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/material/BlendMode.java @@ -17,13 +17,15 @@ package net.fabricmc.fabric.api.renderer.v1.material; import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.RenderLayers; /** - * Defines how sprite pixels will be blended with the scene. + * Controls how sprite pixels will be blended with the scene. */ public enum BlendMode { /** - * Emulate blending behavior of {@code BlockRenderLayer} associated with the block. + * Emulate blending behavior of the {@link RenderLayer} associated with the block state through + * {@link RenderLayers}. */ DEFAULT(null), diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/material/MaterialFinder.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/material/MaterialFinder.java index 25c157ae6..636bd5583 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/material/MaterialFinder.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/material/MaterialFinder.java @@ -17,6 +17,7 @@ package net.fabricmc.fabric.api.renderer.v1.material; import net.minecraft.block.BlockState; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.model.BakedModel; import net.minecraft.item.ItemStack; @@ -34,33 +35,42 @@ import net.fabricmc.fabric.api.util.TriState; */ public interface MaterialFinder extends MaterialView { /** - * Defines how sprite pixels will be blended with the scene. + * Controls how sprite pixels should be blended with the scene. * - *

See {@link BlendMode} for more information. + *

The default value is {@link BlendMode#DEFAULT}. + * + * @see BlendMode */ MaterialFinder blendMode(BlendMode blendMode); /** - * Vertex color(s) will be modified for quad color index unless disabled. + * Controls whether vertex colors should be modified for quad coloring. This property + * is inverted, so a value of {@code false} means that quad coloring will be applied. + * + *

The default value is {@code false}. */ MaterialFinder disableColorIndex(boolean disable); /** * When true, sprite texture and color will be rendered at full brightness. * Lightmap values provided via {@link QuadEmitter#lightmap(int)} will be ignored. - * False by default * - *

This is the preferred method for emissive lighting effects. Some renderers - * with advanced lighting models may not use block lightmaps and this method will + *

This is the preferred method for emissive lighting effects. Some renderers + * with advanced lighting pipelines may not use block lightmaps and this method will * allow per-sprite emissive lighting in future extensions that support overlay sprites. * *

Note that color will still be modified by diffuse shading and ambient occlusion, * unless disabled via {@link #disableDiffuse(boolean)} and {@link #ambientOcclusion(TriState)}. + * + *

The default value is {@code false}. */ MaterialFinder emissive(boolean isEmissive); /** - * Vertex color(s) will be modified for diffuse shading unless disabled. + * Controls whether vertex colors should be modified for diffuse shading. This property + * is inverted, so a value of {@code false} means that diffuse shading will be applied. + * + *

The default value is {@code false}. * *

This property is guaranteed to be respected in block contexts. Some renderers may also respect it in item * contexts, but this is not guaranteed. @@ -68,11 +78,15 @@ public interface MaterialFinder extends MaterialView { MaterialFinder disableDiffuse(boolean disable); /** - * Controls whether vertex color(s) will be modified for ambient occlusion. + * Controls whether vertex colors should be modified for ambient occlusion. * - *

By default, ambient occlusion will be used if {@link BakedModel#useAmbientOcclusion() the model uses ambient occlusion} - * and the block state has {@link BlockState#getLuminance() a luminance} of 0. - * Set to {@link TriState#TRUE} or {@link TriState#FALSE} to override this behavior. + *

If set to {@link TriState#DEFAULT}, ambient occlusion will be used if + * {@linkplain BakedModel#useAmbientOcclusion() the model uses ambient occlusion} and the block state has + * {@linkplain BlockState#getLuminance() a luminance} of 0. Set to {@link TriState#TRUE} or {@link TriState#FALSE} + * to override this behavior. {@link TriState#TRUE} will not have an effect if + * {@linkplain MinecraftClient#isAmbientOcclusionEnabled() ambient occlusion is disabled globally}. + * + *

The default value is {@link TriState#DEFAULT}. * *

This property is respected only in block contexts. It will not have an effect in other contexts. */ @@ -81,14 +95,33 @@ public interface MaterialFinder extends MaterialView { /** * Controls whether glint should be applied. * - *

By default, glint will be applied in item contexts if {@link ItemStack#hasGlint() the item stack has glint}. - * Set to {@link TriState#TRUE} or {@link TriState#FALSE} to override this behavior. + *

If set to {@link TriState#DEFAULT}, glint will be applied in item contexts if + * {@linkplain ItemStack#hasGlint() the item stack has glint}. Set to {@link TriState#TRUE} or + * {@link TriState#FALSE} to override this behavior. + * + *

The default value is {@link TriState#DEFAULT}. * *

This property is guaranteed to be respected in item contexts. Some renderers may also respect it in block * contexts, but this is not guaranteed. */ MaterialFinder glint(TriState mode); + /** + * A hint to the renderer about how the quad is intended to be shaded, for example through ambient occlusion and + * diffuse shading. The renderer is free to ignore this hint. + * + *

The default value is {@link ShadeMode#ENHANCED}. + * + *

This property is respected only in block contexts. It will not have an effect in other contexts. + * + * @see ShadeMode + * + * @apiNote The default implementation will be removed in the next breaking release. + */ + default MaterialFinder shadeMode(ShadeMode mode) { + return this; + } + /** * Copies all properties from the given {@link MaterialView} to this material finder. */ diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/material/MaterialView.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/material/MaterialView.java index 31bb0c8b2..36b90ac32 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/material/MaterialView.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/material/MaterialView.java @@ -54,4 +54,13 @@ public interface MaterialView { * @see MaterialFinder#glint(TriState) */ TriState glint(); + + /** + * @see MaterialFinder#shadeMode(ShadeMode) + * + * @apiNote The default implementation will be removed in the next breaking release. + */ + default ShadeMode shadeMode() { + return ShadeMode.ENHANCED; + } } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/material/ShadeMode.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/material/ShadeMode.java new file mode 100644 index 000000000..e83c91d88 --- /dev/null +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/material/ShadeMode.java @@ -0,0 +1,36 @@ +/* + * 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 net.fabricmc.fabric.api.renderer.v1.material; + +/** + * A hint to the renderer about how the quad is intended to be shaded, for example through ambient occlusion and + * diffuse shading. The renderer is free to ignore this hint. + */ +public enum ShadeMode { + /** + * Conveys the intent that shading should be generally consistent, lack edge cases, and produce visually pleasing + * results, even for quads that are not used by vanilla or are not possible to create through resource packs in + * vanilla. + */ + ENHANCED, + + /** + * Conveys the intent that shading should mimic vanilla results, potentially to preserve certain visuals produced + * by resource packs that modify models. + */ + VANILLA; +} diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/FabricBakedModel.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/FabricBakedModel.java index 40b497d72..0015121b1 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/FabricBakedModel.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/FabricBakedModel.java @@ -94,7 +94,7 @@ public interface FabricBakedModel { * @param context Accepts model output. */ default void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, RenderContext context) { - VanillaModelEncoder.emitBlockQuads((BakedModel) this, state, randomSupplier, context, context.getEmitter()); + VanillaModelEncoder.emitBlockQuads((BakedModel) this, state, randomSupplier, context); } /** diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/ModelHelper.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/ModelHelper.java index 5d58406c2..acd6589d1 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/ModelHelper.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/ModelHelper.java @@ -20,6 +20,7 @@ import java.util.Arrays; import java.util.List; import com.google.common.collect.ImmutableList; +import org.jetbrains.annotations.Nullable; import org.joml.Vector3f; import net.minecraft.client.MinecraftClient; @@ -46,7 +47,7 @@ public final class ModelHelper { * Null is returned as {@link #NULL_FACE_ID}. * Use {@link #faceFromIndex(int)} to retrieve encoded face. */ - public static int toFaceIndex(Direction face) { + public static int toFaceIndex(@Nullable Direction face) { return face == null ? NULL_FACE_ID : face.getId(); } @@ -57,6 +58,7 @@ public final class ModelHelper { * optionally including the null face. (Use < or <= {@link #NULL_FACE_ID} * to exclude or include the null value, respectively.) */ + @Nullable public static Direction faceFromIndex(int faceIndex) { return FACES[faceIndex]; } diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/impl/renderer/VanillaModelEncoder.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/impl/renderer/VanillaModelEncoder.java index af2a817ca..73cf27200 100644 --- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/impl/renderer/VanillaModelEncoder.java +++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/impl/renderer/VanillaModelEncoder.java @@ -30,6 +30,7 @@ import net.minecraft.util.math.random.Random; 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; @@ -41,12 +42,12 @@ import net.fabricmc.fabric.api.util.TriState; */ public class VanillaModelEncoder { private static final Renderer RENDERER = RendererAccess.INSTANCE.getRenderer(); - private static final RenderMaterial MATERIAL_STANDARD = RENDERER.materialFinder().find(); - private static final RenderMaterial MATERIAL_NO_AO = RENDERER.materialFinder().ambientOcclusion(TriState.FALSE).find(); + 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(); - // Separate QuadEmitter parameter so that Indigo can pass its own emitter that handles vanilla quads differently. - public static void emitBlockQuads(BakedModel model, @Nullable BlockState state, Supplier randomSupplier, RenderContext context, QuadEmitter emitter) { - final RenderMaterial defaultMaterial = model.useAmbientOcclusion() ? MATERIAL_STANDARD : MATERIAL_NO_AO; + 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); @@ -77,7 +78,7 @@ public class VanillaModelEncoder { for (int j = 0; j < count; j++) { final BakedQuad q = quads.get(j); - emitter.fromVanilla(q, MATERIAL_STANDARD, cullFace); + emitter.fromVanilla(q, STANDARD_MATERIAL, cullFace); emitter.emit(); } } diff --git a/fabric-renderer-api-v1/src/client/resources/fabric-renderer-api-v1.mixins.json b/fabric-renderer-api-v1/src/client/resources/fabric-renderer-api-v1.mixins.json index 76bb95700..ab5ea7a97 100644 --- a/fabric-renderer-api-v1/src/client/resources/fabric-renderer-api-v1.mixins.json +++ b/fabric-renderer-api-v1/src/client/resources/fabric-renderer-api-v1.mixins.json @@ -1,7 +1,7 @@ { "required": true, "package": "net.fabricmc.fabric.mixin.renderer", - "compatibilityLevel": "JAVA_17", + "compatibilityLevel": "JAVA_21", "client": [ "client.BakedModelMixin", "client.MultipartBakedModelMixin", diff --git a/fabric-renderer-api-v1/src/testmod/java/net/fabricmc/fabric/test/renderer/OctagonalColumnBlock.java b/fabric-renderer-api-v1/src/testmod/java/net/fabricmc/fabric/test/renderer/OctagonalColumnBlock.java new file mode 100644 index 000000000..5a3615bba --- /dev/null +++ b/fabric-renderer-api-v1/src/testmod/java/net/fabricmc/fabric/test/renderer/OctagonalColumnBlock.java @@ -0,0 +1,36 @@ +/* + * 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 net.fabricmc.fabric.test.renderer; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.state.StateManager; +import net.minecraft.state.property.BooleanProperty; + +public class OctagonalColumnBlock extends Block { + public static final BooleanProperty VANILLA_SHADE_MODE = BooleanProperty.of("vanilla_shade_mode"); + + public OctagonalColumnBlock(Settings settings) { + super(settings); + setDefaultState(getDefaultState().with(VANILLA_SHADE_MODE, false)); + } + + @Override + protected void appendProperties(StateManager.Builder builder) { + builder.add(VANILLA_SHADE_MODE); + } +} diff --git a/fabric-renderer-api-v1/src/testmod/java/net/fabricmc/fabric/test/renderer/Registration.java b/fabric-renderer-api-v1/src/testmod/java/net/fabricmc/fabric/test/renderer/Registration.java index 9463c25af..7778d2b17 100644 --- a/fabric-renderer-api-v1/src/testmod/java/net/fabricmc/fabric/test/renderer/Registration.java +++ b/fabric-renderer-api-v1/src/testmod/java/net/fabricmc/fabric/test/renderer/Registration.java @@ -32,7 +32,7 @@ public final class Registration { public static final FrameBlock FRAME_MULTIPART_BLOCK = register("frame_multipart", new FrameBlock(AbstractBlock.Settings.copy(Blocks.IRON_BLOCK).nonOpaque())); public static final FrameBlock FRAME_VARIANT_BLOCK = register("frame_variant", new FrameBlock(AbstractBlock.Settings.copy(Blocks.IRON_BLOCK).nonOpaque())); public static final Block PILLAR_BLOCK = register("pillar", new Block(AbstractBlock.Settings.create())); - public static final Block OCTAGONAL_COLUMN_BLOCK = register("octagonal_column", new Block(AbstractBlock.Settings.create().nonOpaque().strength(1.8F))); + public static final Block OCTAGONAL_COLUMN_BLOCK = register("octagonal_column", new OctagonalColumnBlock(AbstractBlock.Settings.create().nonOpaque().strength(1.8F))); public static final Block RIVERSTONE_BLOCK = register("riverstone", new Block(AbstractBlock.Settings.copy(Blocks.STONE))); public static final FrameBlock[] FRAME_BLOCKS = new FrameBlock[] { diff --git a/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/ModelResolverImpl.java b/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/ModelResolverImpl.java index 6cb8950f2..625d0b96f 100644 --- a/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/ModelResolverImpl.java +++ b/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/ModelResolverImpl.java @@ -24,6 +24,7 @@ import net.minecraft.client.render.model.UnbakedModel; import net.minecraft.util.Identifier; import net.fabricmc.fabric.api.client.model.loading.v1.ModelResolver; +import net.fabricmc.fabric.api.renderer.v1.material.ShadeMode; import net.fabricmc.fabric.test.renderer.RendererTest; public class ModelResolverImpl implements ModelResolver { @@ -44,6 +45,10 @@ public class ModelResolverImpl implements ModelResolver { RendererTest.id("item/octagonal_column") ); + private static final Set OCTAGONAL_COLUMN_VANILLA_MODEL_LOCATIONS = Set.of( + RendererTest.id("block/octagonal_column_vanilla") + ); + private static final Set RIVERSTONE_MODEL_LOCATIONS = Set.of( RendererTest.id("block/riverstone"), RendererTest.id("item/riverstone") @@ -63,7 +68,11 @@ public class ModelResolverImpl implements ModelResolver { } if (OCTAGONAL_COLUMN_MODEL_LOCATIONS.contains(id)) { - return new OctagonalColumnUnbakedModel(); + return new OctagonalColumnUnbakedModel(ShadeMode.ENHANCED); + } + + if (OCTAGONAL_COLUMN_VANILLA_MODEL_LOCATIONS.contains(id)) { + return new OctagonalColumnUnbakedModel(ShadeMode.VANILLA); } if (RIVERSTONE_MODEL_LOCATIONS.contains(id)) { diff --git a/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/OctagonalColumnUnbakedModel.java b/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/OctagonalColumnUnbakedModel.java index 8cc487930..10c4f81dd 100644 --- a/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/OctagonalColumnUnbakedModel.java +++ b/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/OctagonalColumnUnbakedModel.java @@ -36,6 +36,7 @@ import net.fabricmc.fabric.api.renderer.v1.Renderer; import net.fabricmc.fabric.api.renderer.v1.RendererAccess; import net.fabricmc.fabric.api.renderer.v1.material.MaterialFinder; 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.MeshBuilder; import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView; import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; @@ -49,6 +50,12 @@ public class OctagonalColumnUnbakedModel implements UnbakedModel { private static final float A = (float) (1 - Math.sqrt(2) / 2); private static final float B = (float) (Math.sqrt(2) / 2); + private final ShadeMode shadeMode; + + public OctagonalColumnUnbakedModel(ShadeMode shadeMode) { + this.shadeMode = shadeMode; + } + @Override public Collection getModelDependencies() { return Collections.emptySet(); @@ -58,8 +65,8 @@ public class OctagonalColumnUnbakedModel implements UnbakedModel { public void setParents(Function modelLoader) { } - @Nullable @Override + @Nullable public BakedModel bake(Baker baker, Function textureGetter, ModelBakeSettings rotationContainer) { if (!RendererAccess.INSTANCE.hasRenderer()) { return null; @@ -69,7 +76,7 @@ public class OctagonalColumnUnbakedModel implements UnbakedModel { Renderer renderer = RendererAccess.INSTANCE.getRenderer(); MaterialFinder finder = renderer.materialFinder(); - RenderMaterial glintMaterial = finder.glint(TriState.TRUE).find(); + RenderMaterial glintMaterial = finder.glint(TriState.TRUE).shadeMode(shadeMode).find(); MeshBuilder builder = renderer.meshBuilder(); QuadEmitter emitter = builder.getEmitter(); diff --git a/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/RiverstoneUnbakedModel.java b/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/RiverstoneUnbakedModel.java index 26c0d9324..30a291e08 100644 --- a/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/RiverstoneUnbakedModel.java +++ b/fabric-renderer-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/renderer/client/RiverstoneUnbakedModel.java @@ -41,6 +41,8 @@ public class RiverstoneUnbakedModel implements UnbakedModel { @Override public void setParents(Function modelLoader) { + modelLoader.apply(STONE_MODEL_ID).setParents(modelLoader); + modelLoader.apply(GOLD_BLOCK_MODEL_ID).setParents(modelLoader); } @Nullable diff --git a/fabric-renderer-api-v1/src/testmodClient/resources/assets/fabric-renderer-api-v1-testmod/blockstates/octagonal_column.json b/fabric-renderer-api-v1/src/testmodClient/resources/assets/fabric-renderer-api-v1-testmod/blockstates/octagonal_column.json index f62ea8ad6..064068a7b 100644 --- a/fabric-renderer-api-v1/src/testmodClient/resources/assets/fabric-renderer-api-v1-testmod/blockstates/octagonal_column.json +++ b/fabric-renderer-api-v1/src/testmodClient/resources/assets/fabric-renderer-api-v1-testmod/blockstates/octagonal_column.json @@ -1,5 +1,6 @@ { "variants": { - "": { "model": "fabric-renderer-api-v1-testmod:block/octagonal_column" } + "vanilla_shade_mode=false": { "model": "fabric-renderer-api-v1-testmod:block/octagonal_column" }, + "vanilla_shade_mode=true": { "model": "fabric-renderer-api-v1-testmod:block/octagonal_column_vanilla" } } } diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/IndigoRenderer.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/IndigoRenderer.java index d1eb246bc..b29945548 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/IndigoRenderer.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/IndigoRenderer.java @@ -25,6 +25,7 @@ import net.fabricmc.fabric.api.renderer.v1.material.MaterialFinder; import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder; import net.fabricmc.fabric.impl.client.indigo.renderer.material.MaterialFinderImpl; +import net.fabricmc.fabric.impl.client.indigo.renderer.material.RenderMaterialImpl; import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MeshBuilderImpl; /** @@ -64,7 +65,7 @@ public class IndigoRenderer implements Renderer { 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/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/aocalc/AoCalculator.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/aocalc/AoCalculator.java index 2481a3a8a..bc37983e9 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/aocalc/AoCalculator.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/aocalc/AoCalculator.java @@ -45,7 +45,6 @@ import net.minecraft.world.LightType; import net.fabricmc.fabric.impl.client.indigo.Indigo; import net.fabricmc.fabric.impl.client.indigo.renderer.aocalc.AoFace.WeightFunction; import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.EncodingFormat; -import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MutableQuadViewImpl; import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.QuadViewImpl; import net.fabricmc.fabric.impl.client.indigo.renderer.render.BlockRenderInfo; @@ -105,41 +104,23 @@ public abstract class AoCalculator { completionFlags = 0; } - public void compute(MutableQuadViewImpl quad, boolean isVanilla) { + public void compute(QuadViewImpl quad, boolean vanillaShade) { final AoConfig config = Indigo.AMBIENT_OCCLUSION_MODE; - final boolean shouldCompare; switch (config) { - case VANILLA: - calcVanilla(quad); - - // no point in comparing vanilla with itself - shouldCompare = false; - break; - - case EMULATE: - calcFastVanilla(quad); - shouldCompare = Indigo.DEBUG_COMPARE_LIGHTING && isVanilla; - break; - - case HYBRID: - default: - if (isVanilla) { - shouldCompare = Indigo.DEBUG_COMPARE_LIGHTING; + case VANILLA -> calcVanilla(quad); + case EMULATE -> calcFastVanilla(quad); + case HYBRID -> { + if (vanillaShade) { calcFastVanilla(quad); } else { - shouldCompare = false; calcEnhanced(quad); } - - break; - - case ENHANCED: - shouldCompare = false; - calcEnhanced(quad); + } + case ENHANCED -> calcEnhanced(quad); } - if (shouldCompare) { + if (Indigo.DEBUG_COMPARE_LIGHTING && vanillaShade && (config == AoConfig.EMULATE || config == AoConfig.HYBRID)) { float[] vanillaAo = new float[4]; int[] vanillaLight = new int[4]; calcVanilla(quad, vanillaAo, vanillaLight); @@ -158,7 +139,7 @@ public abstract class AoCalculator { } } - private void calcVanilla(MutableQuadViewImpl quad) { + private void calcVanilla(QuadViewImpl quad) { calcVanilla(quad, ao, light); } @@ -169,7 +150,7 @@ public abstract class AoCalculator { 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, float[] aoDest, int[] lightDest) { vanillaAoControlBits.clear(); final Direction lightFace = quad.lightFace(); quad.toVanilla(vertexData, 0); @@ -181,7 +162,7 @@ public abstract class AoCalculator { System.arraycopy(vanillaCalc.light, 0, lightDest, 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 @@ -196,7 +177,7 @@ public abstract class AoCalculator { } } - 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: @@ -271,7 +252,7 @@ public abstract class AoCalculator { /** 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/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/material/MaterialFinderImpl.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/material/MaterialFinderImpl.java index cfae150f4..53cdbdbd3 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/material/MaterialFinderImpl.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/material/MaterialFinderImpl.java @@ -22,6 +22,7 @@ import net.fabricmc.fabric.api.renderer.v1.material.BlendMode; 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 class MaterialFinderImpl extends MaterialViewImpl implements MaterialFind 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/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/material/MaterialViewImpl.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/material/MaterialViewImpl.java index bb4f269ca..ca8ff4558 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/material/MaterialViewImpl.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/material/MaterialViewImpl.java @@ -16,10 +16,13 @@ package net.fabricmc.fabric.impl.client.indigo.renderer.material; +import static net.fabricmc.fabric.impl.client.indigo.renderer.mesh.EncodingFormat.bitMask; + import net.minecraft.util.math.MathHelper; 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; /** @@ -33,6 +36,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; @@ -40,6 +45,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; @@ -47,7 +53,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); @@ -55,19 +62,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; @@ -105,4 +111,9 @@ public class MaterialViewImpl implements MaterialView { 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/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/EncodingFormat.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/EncodingFormat.java index 99e190a23..f5714b529 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/EncodingFormat.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/mesh/EncodingFormat.java @@ -17,6 +17,7 @@ package net.fabricmc.fabric.impl.client.indigo.renderer.mesh; import com.google.common.base.Preconditions; +import org.jetbrains.annotations.Nullable; import net.minecraft.client.render.VertexFormat; import net.minecraft.client.render.VertexFormats; @@ -26,6 +27,7 @@ import net.minecraft.util.math.MathHelper; import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView; import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper; import net.fabricmc.fabric.impl.client.indigo.renderer.helper.GeometryHelper; +import net.fabricmc.fabric.impl.client.indigo.renderer.material.MaterialViewImpl; import net.fabricmc.fabric.impl.client.indigo.renderer.material.RenderMaterialImpl; /** @@ -78,66 +80,75 @@ public abstract class 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; - private static final int DIRECTION_BIT_COUNT = Integer.bitCount(DIRECTION_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 NORMALS_SHIFT = LIGHT_SHIFT + DIRECTION_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 CULL_BIT_LENGTH = MathHelper.ceilLog2(NULLABLE_DIRECTION_COUNT); + private static final int LIGHT_BIT_LENGTH = MathHelper.ceilLog2(DIRECTION_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 NORMALS_BIT_OFFSET = LIGHT_BIT_OFFSET + LIGHT_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 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, "Indigo header encoding bit count (%s) exceeds integer bit length)", TOTAL_STRIDE); + Preconditions.checkArgument(TOTAL_BIT_LENGTH <= 32, "Indigo 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); } /** 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/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/AbstractBlockRenderContext.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/AbstractBlockRenderContext.java index 38659bb2f..3d9ef25fb 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/AbstractBlockRenderContext.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/AbstractBlockRenderContext.java @@ -33,6 +33,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; 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.client.indigo.Indigo; @@ -55,18 +56,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); } }; @@ -88,11 +78,6 @@ public abstract class AbstractBlockRenderContext extends AbstractRenderContext { 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); @@ -108,7 +93,7 @@ public abstract class AbstractBlockRenderContext extends AbstractRenderContext { return vanillaModelConsumer; } - private void renderQuad(MutableQuadViewImpl quad, boolean isVanilla) { + private void renderQuad(MutableQuadViewImpl quad) { if (!transform(quad)) { return; } @@ -122,10 +107,11 @@ public abstract class AbstractBlockRenderContext extends AbstractRenderContext { 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 VertexConsumer vertexConsumer = getVertexConsumer(blockInfo.effectiveRenderLayer(mat.blendMode())); colorizeQuad(quad, colorIndex); - shadeQuad(quad, isVanilla, ao, emissive); + shadeQuad(quad, ao, emissive, vanillaShade); bufferQuad(quad, vertexConsumer); } @@ -140,10 +126,10 @@ public abstract class AbstractBlockRenderContext extends AbstractRenderContext { } } - private void shadeQuad(MutableQuadViewImpl quad, boolean isVanilla, boolean ao, boolean emissive) { + private 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 @@ public abstract class AbstractBlockRenderContext extends AbstractRenderContext { } } } else { - shadeFlatQuad(quad, isVanilla); + shadeFlatQuad(quad, vanillaShade); if (emissive) { for (int i = 0; i < 4; i++) { @@ -177,11 +163,11 @@ public abstract class AbstractBlockRenderContext extends AbstractRenderContext { * 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 ((Indigo.AMBIENT_OCCLUSION_MODE == AoConfig.HYBRID && !isVanilla) || Indigo.AMBIENT_OCCLUSION_MODE == AoConfig.ENHANCED) { + if ((Indigo.AMBIENT_OCCLUSION_MODE == AoConfig.HYBRID && !vanillaShade) || Indigo.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); @@ -305,7 +291,7 @@ public abstract class AbstractBlockRenderContext extends AbstractRenderContext { @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/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/ChunkRenderInfo.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/ChunkRenderInfo.java index 69a83f398..b16ff91a3 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/ChunkRenderInfo.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/ChunkRenderInfo.java @@ -16,7 +16,7 @@ package net.fabricmc.fabric.impl.client.indigo.renderer.render; -import java.util.Map; +import java.util.function.Function; import it.unimi.dsi.fastutil.longs.Long2FloatOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; @@ -24,12 +24,8 @@ import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; import net.minecraft.block.BlockState; import net.minecraft.client.render.BufferBuilder; import net.minecraft.client.render.RenderLayer; -import net.minecraft.client.render.VertexFormat; -import net.minecraft.client.render.VertexFormats; import net.minecraft.client.render.WorldRenderer; -import net.minecraft.client.render.chunk.BlockBufferAllocatorStorage; import net.minecraft.client.render.chunk.ChunkRendererRegion; -import net.minecraft.client.util.BufferAllocator; import net.minecraft.util.math.BlockPos; import net.minecraft.world.BlockRenderView; @@ -69,9 +65,7 @@ public class ChunkRenderInfo { private final Long2IntOpenHashMap brightnessCache; private final Long2FloatOpenHashMap aoLevelCache; - private final BlockPos.Mutable chunkOrigin = new BlockPos.Mutable(); - BlockBufferAllocatorStorage builders; - Map buffers; + private Function bufferFunc; BlockRenderView blockView; ChunkRenderInfo() { @@ -81,31 +75,21 @@ public class ChunkRenderInfo { aoLevelCache.defaultReturnValue(Float.MAX_VALUE); } - void prepare(ChunkRendererRegion blockView, BlockPos chunkOrigin, BlockBufferAllocatorStorage builders, Map buffers) { + void prepare(ChunkRendererRegion blockView, Function bufferFunc) { this.blockView = blockView; - this.chunkOrigin.set(chunkOrigin); - this.builders = builders; - this.buffers = buffers; + this.bufferFunc = bufferFunc; + brightnessCache.clear(); aoLevelCache.clear(); } void release() { + blockView = null; + bufferFunc = null; } - /** Lazily retrieves output buffer for given layer, initializing as needed. */ - public BufferBuilder getInitializedBuffer(RenderLayer renderLayer) { - // TODO 24w21b - possibly AW class_9810#method_60903 which does the same thing? - BufferBuilder builder = buffers.get(renderLayer); - - if (builder == null) { - BufferAllocator byteBuilder = builders.get(renderLayer); - builder = new BufferBuilder(byteBuilder, VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR_TEXTURE_LIGHT_NORMAL); - - buffers.put(renderLayer, builder); - } - - return builder; + BufferBuilder getBuffer(RenderLayer layer) { + return bufferFunc.apply(layer); } /** diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/TerrainRenderContext.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/TerrainRenderContext.java index b35bf8396..5dab19342 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/TerrainRenderContext.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/render/TerrainRenderContext.java @@ -16,14 +16,13 @@ package net.fabricmc.fabric.impl.client.indigo.renderer.render; -import java.util.Map; +import java.util.function.Function; import net.minecraft.block.BlockState; import net.minecraft.client.render.BufferBuilder; import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.chunk.BlockBufferAllocatorStorage; import net.minecraft.client.render.chunk.ChunkRendererRegion; import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.util.math.MatrixStack; @@ -69,12 +68,12 @@ public class TerrainRenderContext extends AbstractBlockRenderContext { @Override protected VertexConsumer getVertexConsumer(RenderLayer layer) { - return chunkInfo.getInitializedBuffer(layer); + return chunkInfo.getBuffer(layer); } - public void prepare(ChunkRendererRegion blockView, BlockPos chunkOrigin, BlockBufferAllocatorStorage builders, Map builderMap) { + public void prepare(ChunkRendererRegion blockView, Function bufferFunc) { + chunkInfo.prepare(blockView, bufferFunc); blockInfo.prepareForWorld(blockView, true); - chunkInfo.prepare(blockView, chunkOrigin, builders, builderMap); } public void release() { diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/BakedModelMixin.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/BakedModelMixin.java deleted file mode 100644 index 10218850f..000000000 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/BakedModelMixin.java +++ /dev/null @@ -1,43 +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 net.fabricmc.fabric.mixin.client.indigo.renderer; - -import java.util.function.Supplier; - -import org.spongepowered.asm.mixin.Mixin; - -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 net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel; -import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; -import net.fabricmc.fabric.impl.client.indigo.renderer.render.AbstractBlockRenderContext; -import net.fabricmc.fabric.impl.renderer.VanillaModelEncoder; - -@Mixin(BakedModel.class) -public interface BakedModelMixin 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()); - } -} diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/SectionBuilderMixin.java b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/SectionBuilderMixin.java index 72b488fc6..fd4ff9eb9 100644 --- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/SectionBuilderMixin.java +++ b/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/mixin/client/indigo/renderer/SectionBuilderMixin.java @@ -17,11 +17,11 @@ package net.fabricmc.fabric.mixin.client.indigo.renderer; import java.util.Map; -import java.util.Set; import com.llamalad7.mixinextras.sugar.Local; import com.mojang.blaze3d.systems.VertexSorter; 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.Redirect; @@ -30,7 +30,6 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import net.minecraft.block.BlockRenderType; import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.render.BufferBuilder; import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.VertexConsumer; @@ -67,17 +66,19 @@ import net.fabricmc.fabric.impl.client.indigo.renderer.render.TerrainRenderConte */ @Mixin(SectionBuilder.class) public abstract class SectionBuilderMixin { + @Shadow + abstract BufferBuilder beginBufferBuilding(Map builders, BlockBufferAllocatorStorage allocatorStorage, RenderLayer layer); + @Inject(method = "build", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/BlockPos;iterate(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/math/BlockPos;)Ljava/lang/Iterable;"), locals = LocalCapture.CAPTURE_FAILHARD) - private void hookChunkBuild(ChunkSectionPos sectionPos, ChunkRendererRegion region, VertexSorter sorter, - BlockBufferAllocatorStorage builder, - CallbackInfoReturnable ci, - @Local(ordinal = 0) Map builderMap) { - // hook just before iterating over the render chunk's chunks blocks, captures the buffer builder map - + private void hookBuild(ChunkSectionPos sectionPos, ChunkRendererRegion region, VertexSorter sorter, + BlockBufferAllocatorStorage allocators, + CallbackInfoReturnable cir, + @Local(ordinal = 0) Map builderMap) { + // hook just before iterating over the render chunk's blocks to capture the buffer builder map TerrainRenderContext renderer = TerrainRenderContext.POOL.get(); - renderer.prepare(region, sectionPos.getMinPos(), builder, builderMap); + renderer.prepare(region, layer -> beginBufferBuilding(builderMap, allocators, layer)); ((AccessChunkRendererRegion) region).fabric_setRenderer(renderer); } @@ -99,7 +100,7 @@ public abstract class SectionBuilderMixin { */ @Redirect(method = "build", require = 1, at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/block/BlockRenderManager;renderBlock(Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/world/BlockRenderView;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumer;ZLnet/minecraft/util/math/random/Random;)V")) - private void hookChunkBuildTessellate(BlockRenderManager renderManager, BlockState blockState, BlockPos blockPos, BlockRenderView blockView, MatrixStack matrix, VertexConsumer bufferBuilder, boolean checkSides, Random random) { + private void hookBuildRenderBlock(BlockRenderManager renderManager, BlockState blockState, BlockPos blockPos, BlockRenderView blockView, MatrixStack matrix, VertexConsumer bufferBuilder, boolean checkSides, Random random) { if (blockState.getRenderType() == BlockRenderType.MODEL) { final BakedModel model = renderManager.getModel(blockState); @@ -115,11 +116,9 @@ public abstract class SectionBuilderMixin { /** * Release all references. Probably not necessary but would be $#%! to debug if it is. */ - @Inject(method = "build", - at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/block/BlockModelRenderer;disableBrightnessCache()V")) - private void hookRebuildChunkReturn(CallbackInfoReturnable> ci) { - // hook after iterating over the render chunk's chunks blocks, must be called if and only if hookChunkBuild happened - - TerrainRenderContext.POOL.get().release(); + @Inject(method = "build", at = @At(value = "RETURN")) + private void hookBuildReturn(ChunkSectionPos sectionPos, ChunkRendererRegion renderRegion, VertexSorter vertexSorter, BlockBufferAllocatorStorage allocatorStorage, CallbackInfoReturnable cir) { + ((AccessChunkRendererRegion) renderRegion).fabric_getRenderer().release(); + ((AccessChunkRendererRegion) renderRegion).fabric_setRenderer(null); } } diff --git a/fabric-renderer-indigo/src/client/resources/fabric-renderer-indigo.accesswidener b/fabric-renderer-indigo/src/client/resources/fabric-renderer-indigo.accesswidener index 85c5f524a..fce49d4a4 100644 --- a/fabric-renderer-indigo/src/client/resources/fabric-renderer-indigo.accesswidener +++ b/fabric-renderer-indigo/src/client/resources/fabric-renderer-indigo.accesswidener @@ -1,11 +1,7 @@ accessWidener v2 named -accessible class net/minecraft/client/render/chunk/ChunkBuilder$BuiltChunk$RebuildTask - accessible class net/minecraft/client/render/block/BlockModelRenderer$AmbientOcclusionCalculator accessible field net/minecraft/client/render/block/BlockModelRenderer$AmbientOcclusionCalculator brightness [F accessible field net/minecraft/client/render/block/BlockModelRenderer$AmbientOcclusionCalculator light [I accessible method net/minecraft/client/render/block/BlockModelRenderer getQuadDimensions (Lnet/minecraft/world/BlockRenderView;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;[ILnet/minecraft/util/math/Direction;[FLjava/util/BitSet;)V - -accessible method net/minecraft/client/render/item/ItemRenderer renderBakedItemModel (Lnet/minecraft/client/render/model/BakedModel;Lnet/minecraft/item/ItemStack;IILnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumer;)V diff --git a/fabric-renderer-indigo/src/client/resources/fabric-renderer-indigo.mixins.json b/fabric-renderer-indigo/src/client/resources/fabric-renderer-indigo.mixins.json index f7adfac5a..0c59e3c42 100644 --- a/fabric-renderer-indigo/src/client/resources/fabric-renderer-indigo.mixins.json +++ b/fabric-renderer-indigo/src/client/resources/fabric-renderer-indigo.mixins.json @@ -1,12 +1,11 @@ { "required": true, "package": "net.fabricmc.fabric.mixin.client.indigo.renderer", - "compatibilityLevel": "JAVA_17", + "compatibilityLevel": "JAVA_21", "plugin": "net.fabricmc.fabric.impl.client.indigo.IndigoMixinConfigPlugin", "mixins": [ ], "client": [ - "BakedModelMixin", "BlockModelRendererMixin", "ChunkRendererRegionMixin", "ItemRendererAccessor",