mirror of
https://github.com/FabricMC/fabric.git
synced 2024-11-23 16:18:29 -05:00
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
This commit is contained in:
parent
6c1df360ce
commit
c705a49cc5
26 changed files with 288 additions and 217 deletions
|
@ -17,13 +17,15 @@
|
||||||
package net.fabricmc.fabric.api.renderer.v1.material;
|
package net.fabricmc.fabric.api.renderer.v1.material;
|
||||||
|
|
||||||
import net.minecraft.client.render.RenderLayer;
|
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 {
|
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),
|
DEFAULT(null),
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package net.fabricmc.fabric.api.renderer.v1.material;
|
package net.fabricmc.fabric.api.renderer.v1.material;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.render.RenderLayer;
|
import net.minecraft.client.render.RenderLayer;
|
||||||
import net.minecraft.client.render.model.BakedModel;
|
import net.minecraft.client.render.model.BakedModel;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
@ -34,33 +35,42 @@ import net.fabricmc.fabric.api.util.TriState;
|
||||||
*/
|
*/
|
||||||
public interface MaterialFinder extends MaterialView {
|
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.
|
||||||
*
|
*
|
||||||
* <p>See {@link BlendMode} for more information.
|
* <p>The default value is {@link BlendMode#DEFAULT}.
|
||||||
|
*
|
||||||
|
* @see BlendMode
|
||||||
*/
|
*/
|
||||||
MaterialFinder blendMode(BlendMode 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.
|
||||||
|
*
|
||||||
|
* <p>The default value is {@code false}.
|
||||||
*/
|
*/
|
||||||
MaterialFinder disableColorIndex(boolean disable);
|
MaterialFinder disableColorIndex(boolean disable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When true, sprite texture and color will be rendered at full brightness.
|
* When true, sprite texture and color will be rendered at full brightness.
|
||||||
* Lightmap values provided via {@link QuadEmitter#lightmap(int)} will be ignored.
|
* Lightmap values provided via {@link QuadEmitter#lightmap(int)} will be ignored.
|
||||||
* False by default
|
|
||||||
*
|
*
|
||||||
* <p>This is the preferred method for emissive lighting effects. Some renderers
|
* <p>This is the preferred method for emissive lighting effects. Some renderers
|
||||||
* with advanced lighting models may not use block lightmaps and this method will
|
* 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.
|
* allow per-sprite emissive lighting in future extensions that support overlay sprites.
|
||||||
*
|
*
|
||||||
* <p>Note that color will still be modified by diffuse shading and ambient occlusion,
|
* <p>Note that color will still be modified by diffuse shading and ambient occlusion,
|
||||||
* unless disabled via {@link #disableDiffuse(boolean)} and {@link #ambientOcclusion(TriState)}.
|
* unless disabled via {@link #disableDiffuse(boolean)} and {@link #ambientOcclusion(TriState)}.
|
||||||
|
*
|
||||||
|
* <p>The default value is {@code false}.
|
||||||
*/
|
*/
|
||||||
MaterialFinder emissive(boolean isEmissive);
|
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.
|
||||||
|
*
|
||||||
|
* <p>The default value is {@code false}.
|
||||||
*
|
*
|
||||||
* <p>This property is guaranteed to be respected in block contexts. Some renderers may also respect it in item
|
* <p>This property is guaranteed to be respected in block contexts. Some renderers may also respect it in item
|
||||||
* contexts, but this is not guaranteed.
|
* contexts, but this is not guaranteed.
|
||||||
|
@ -68,11 +78,15 @@ public interface MaterialFinder extends MaterialView {
|
||||||
MaterialFinder disableDiffuse(boolean disable);
|
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.
|
||||||
*
|
*
|
||||||
* <p>By default, ambient occlusion will be used if {@link BakedModel#useAmbientOcclusion() the model uses ambient occlusion}
|
* <p>If set to {@link TriState#DEFAULT}, ambient occlusion will be used if
|
||||||
* and the block state has {@link BlockState#getLuminance() a luminance} of 0.
|
* {@linkplain BakedModel#useAmbientOcclusion() the model uses ambient occlusion} and the block state has
|
||||||
* Set to {@link TriState#TRUE} or {@link TriState#FALSE} to override this behavior.
|
* {@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}.
|
||||||
|
*
|
||||||
|
* <p>The default value is {@link TriState#DEFAULT}.
|
||||||
*
|
*
|
||||||
* <p>This property is respected only in block contexts. It will not have an effect in other contexts.
|
* <p>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.
|
* Controls whether glint should be applied.
|
||||||
*
|
*
|
||||||
* <p>By default, glint will be applied in item contexts if {@link ItemStack#hasGlint() the item stack has glint}.
|
* <p>If set to {@link TriState#DEFAULT}, glint will be applied in item contexts if
|
||||||
* Set to {@link TriState#TRUE} or {@link TriState#FALSE} to override this behavior.
|
* {@linkplain ItemStack#hasGlint() the item stack has glint}. Set to {@link TriState#TRUE} or
|
||||||
|
* {@link TriState#FALSE} to override this behavior.
|
||||||
|
*
|
||||||
|
* <p>The default value is {@link TriState#DEFAULT}.
|
||||||
*
|
*
|
||||||
* <p>This property is guaranteed to be respected in item contexts. Some renderers may also respect it in block
|
* <p>This property is guaranteed to be respected in item contexts. Some renderers may also respect it in block
|
||||||
* contexts, but this is not guaranteed.
|
* contexts, but this is not guaranteed.
|
||||||
*/
|
*/
|
||||||
MaterialFinder glint(TriState mode);
|
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.
|
||||||
|
*
|
||||||
|
* <p>The default value is {@link ShadeMode#ENHANCED}.
|
||||||
|
*
|
||||||
|
* <p>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.
|
* Copies all properties from the given {@link MaterialView} to this material finder.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -54,4 +54,13 @@ public interface MaterialView {
|
||||||
* @see MaterialFinder#glint(TriState)
|
* @see MaterialFinder#glint(TriState)
|
||||||
*/
|
*/
|
||||||
TriState glint();
|
TriState glint();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see MaterialFinder#shadeMode(ShadeMode)
|
||||||
|
*
|
||||||
|
* @apiNote The default implementation will be removed in the next breaking release.
|
||||||
|
*/
|
||||||
|
default ShadeMode shadeMode() {
|
||||||
|
return ShadeMode.ENHANCED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -94,7 +94,7 @@ public interface FabricBakedModel {
|
||||||
* @param context Accepts model output.
|
* @param context Accepts model output.
|
||||||
*/
|
*/
|
||||||
default void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
|
default void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
|
||||||
VanillaModelEncoder.emitBlockQuads((BakedModel) this, state, randomSupplier, context, context.getEmitter());
|
VanillaModelEncoder.emitBlockQuads((BakedModel) this, state, randomSupplier, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -20,6 +20,7 @@ import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
@ -46,7 +47,7 @@ public final class ModelHelper {
|
||||||
* Null is returned as {@link #NULL_FACE_ID}.
|
* Null is returned as {@link #NULL_FACE_ID}.
|
||||||
* Use {@link #faceFromIndex(int)} to retrieve encoded face.
|
* 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();
|
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}
|
* optionally including the null face. (Use < or <= {@link #NULL_FACE_ID}
|
||||||
* to exclude or include the null value, respectively.)
|
* to exclude or include the null value, respectively.)
|
||||||
*/
|
*/
|
||||||
|
@Nullable
|
||||||
public static Direction faceFromIndex(int faceIndex) {
|
public static Direction faceFromIndex(int faceIndex) {
|
||||||
return FACES[faceIndex];
|
return FACES[faceIndex];
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.Renderer;
|
||||||
import net.fabricmc.fabric.api.renderer.v1.RendererAccess;
|
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.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.mesh.QuadEmitter;
|
||||||
import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper;
|
import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper;
|
||||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||||
|
@ -41,12 +42,12 @@ import net.fabricmc.fabric.api.util.TriState;
|
||||||
*/
|
*/
|
||||||
public class VanillaModelEncoder {
|
public class VanillaModelEncoder {
|
||||||
private static final Renderer RENDERER = RendererAccess.INSTANCE.getRenderer();
|
private static final Renderer RENDERER = RendererAccess.INSTANCE.getRenderer();
|
||||||
private static final RenderMaterial MATERIAL_STANDARD = RENDERER.materialFinder().find();
|
private static final RenderMaterial STANDARD_MATERIAL = RENDERER.materialFinder().shadeMode(ShadeMode.VANILLA).find();
|
||||||
private static final RenderMaterial MATERIAL_NO_AO = RENDERER.materialFinder().ambientOcclusion(TriState.FALSE).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<Random> randomSupplier, RenderContext context) {
|
||||||
public static void emitBlockQuads(BakedModel model, @Nullable BlockState state, Supplier<Random> randomSupplier, RenderContext context, QuadEmitter emitter) {
|
QuadEmitter emitter = context.getEmitter();
|
||||||
final RenderMaterial defaultMaterial = model.useAmbientOcclusion() ? MATERIAL_STANDARD : MATERIAL_NO_AO;
|
final RenderMaterial defaultMaterial = model.useAmbientOcclusion() ? STANDARD_MATERIAL : NO_AO_MATERIAL;
|
||||||
|
|
||||||
for (int i = 0; i <= ModelHelper.NULL_FACE_ID; i++) {
|
for (int i = 0; i <= ModelHelper.NULL_FACE_ID; i++) {
|
||||||
final Direction cullFace = ModelHelper.faceFromIndex(i);
|
final Direction cullFace = ModelHelper.faceFromIndex(i);
|
||||||
|
@ -77,7 +78,7 @@ public class VanillaModelEncoder {
|
||||||
|
|
||||||
for (int j = 0; j < count; j++) {
|
for (int j = 0; j < count; j++) {
|
||||||
final BakedQuad q = quads.get(j);
|
final BakedQuad q = quads.get(j);
|
||||||
emitter.fromVanilla(q, MATERIAL_STANDARD, cullFace);
|
emitter.fromVanilla(q, STANDARD_MATERIAL, cullFace);
|
||||||
emitter.emit();
|
emitter.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"required": true,
|
"required": true,
|
||||||
"package": "net.fabricmc.fabric.mixin.renderer",
|
"package": "net.fabricmc.fabric.mixin.renderer",
|
||||||
"compatibilityLevel": "JAVA_17",
|
"compatibilityLevel": "JAVA_21",
|
||||||
"client": [
|
"client": [
|
||||||
"client.BakedModelMixin",
|
"client.BakedModelMixin",
|
||||||
"client.MultipartBakedModelMixin",
|
"client.MultipartBakedModelMixin",
|
||||||
|
|
|
@ -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<Block, BlockState> builder) {
|
||||||
|
builder.add(VANILLA_SHADE_MODE);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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_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 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 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 Block RIVERSTONE_BLOCK = register("riverstone", new Block(AbstractBlock.Settings.copy(Blocks.STONE)));
|
||||||
|
|
||||||
public static final FrameBlock[] FRAME_BLOCKS = new FrameBlock[] {
|
public static final FrameBlock[] FRAME_BLOCKS = new FrameBlock[] {
|
||||||
|
|
|
@ -24,6 +24,7 @@ import net.minecraft.client.render.model.UnbakedModel;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.client.model.loading.v1.ModelResolver;
|
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;
|
import net.fabricmc.fabric.test.renderer.RendererTest;
|
||||||
|
|
||||||
public class ModelResolverImpl implements ModelResolver {
|
public class ModelResolverImpl implements ModelResolver {
|
||||||
|
@ -44,6 +45,10 @@ public class ModelResolverImpl implements ModelResolver {
|
||||||
RendererTest.id("item/octagonal_column")
|
RendererTest.id("item/octagonal_column")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
private static final Set<Identifier> OCTAGONAL_COLUMN_VANILLA_MODEL_LOCATIONS = Set.of(
|
||||||
|
RendererTest.id("block/octagonal_column_vanilla")
|
||||||
|
);
|
||||||
|
|
||||||
private static final Set<Identifier> RIVERSTONE_MODEL_LOCATIONS = Set.of(
|
private static final Set<Identifier> RIVERSTONE_MODEL_LOCATIONS = Set.of(
|
||||||
RendererTest.id("block/riverstone"),
|
RendererTest.id("block/riverstone"),
|
||||||
RendererTest.id("item/riverstone")
|
RendererTest.id("item/riverstone")
|
||||||
|
@ -63,7 +68,11 @@ public class ModelResolverImpl implements ModelResolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OCTAGONAL_COLUMN_MODEL_LOCATIONS.contains(id)) {
|
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)) {
|
if (RIVERSTONE_MODEL_LOCATIONS.contains(id)) {
|
||||||
|
|
|
@ -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.RendererAccess;
|
||||||
import net.fabricmc.fabric.api.renderer.v1.material.MaterialFinder;
|
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.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.MeshBuilder;
|
||||||
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
|
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
|
||||||
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
|
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 A = (float) (1 - Math.sqrt(2) / 2);
|
||||||
private static final float B = (float) (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
|
@Override
|
||||||
public Collection<Identifier> getModelDependencies() {
|
public Collection<Identifier> getModelDependencies() {
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
|
@ -58,8 +65,8 @@ public class OctagonalColumnUnbakedModel implements UnbakedModel {
|
||||||
public void setParents(Function<Identifier, UnbakedModel> modelLoader) {
|
public void setParents(Function<Identifier, UnbakedModel> modelLoader) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
@Override
|
||||||
|
@Nullable
|
||||||
public BakedModel bake(Baker baker, Function<SpriteIdentifier, Sprite> textureGetter, ModelBakeSettings rotationContainer) {
|
public BakedModel bake(Baker baker, Function<SpriteIdentifier, Sprite> textureGetter, ModelBakeSettings rotationContainer) {
|
||||||
if (!RendererAccess.INSTANCE.hasRenderer()) {
|
if (!RendererAccess.INSTANCE.hasRenderer()) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -69,7 +76,7 @@ public class OctagonalColumnUnbakedModel implements UnbakedModel {
|
||||||
|
|
||||||
Renderer renderer = RendererAccess.INSTANCE.getRenderer();
|
Renderer renderer = RendererAccess.INSTANCE.getRenderer();
|
||||||
MaterialFinder finder = renderer.materialFinder();
|
MaterialFinder finder = renderer.materialFinder();
|
||||||
RenderMaterial glintMaterial = finder.glint(TriState.TRUE).find();
|
RenderMaterial glintMaterial = finder.glint(TriState.TRUE).shadeMode(shadeMode).find();
|
||||||
|
|
||||||
MeshBuilder builder = renderer.meshBuilder();
|
MeshBuilder builder = renderer.meshBuilder();
|
||||||
QuadEmitter emitter = builder.getEmitter();
|
QuadEmitter emitter = builder.getEmitter();
|
||||||
|
|
|
@ -41,6 +41,8 @@ public class RiverstoneUnbakedModel implements UnbakedModel {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setParents(Function<Identifier, UnbakedModel> modelLoader) {
|
public void setParents(Function<Identifier, UnbakedModel> modelLoader) {
|
||||||
|
modelLoader.apply(STONE_MODEL_ID).setParents(modelLoader);
|
||||||
|
modelLoader.apply(GOLD_BLOCK_MODEL_ID).setParents(modelLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"variants": {
|
"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" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.material.RenderMaterial;
|
||||||
import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder;
|
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.MaterialFinderImpl;
|
||||||
|
import net.fabricmc.fabric.impl.client.indigo.renderer.material.RenderMaterialImpl;
|
||||||
import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MeshBuilderImpl;
|
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;
|
if (materialMap.containsKey(id)) return false;
|
||||||
|
|
||||||
// cast to prevent acceptance of impostor implementations
|
// cast to prevent acceptance of impostor implementations
|
||||||
materialMap.put(id, material);
|
materialMap.put(id, (RenderMaterialImpl) material);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,6 @@ import net.minecraft.world.LightType;
|
||||||
import net.fabricmc.fabric.impl.client.indigo.Indigo;
|
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.aocalc.AoFace.WeightFunction;
|
||||||
import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.EncodingFormat;
|
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.mesh.QuadViewImpl;
|
||||||
import net.fabricmc.fabric.impl.client.indigo.renderer.render.BlockRenderInfo;
|
import net.fabricmc.fabric.impl.client.indigo.renderer.render.BlockRenderInfo;
|
||||||
|
|
||||||
|
@ -105,41 +104,23 @@ public abstract class AoCalculator {
|
||||||
completionFlags = 0;
|
completionFlags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void compute(MutableQuadViewImpl quad, boolean isVanilla) {
|
public void compute(QuadViewImpl quad, boolean vanillaShade) {
|
||||||
final AoConfig config = Indigo.AMBIENT_OCCLUSION_MODE;
|
final AoConfig config = Indigo.AMBIENT_OCCLUSION_MODE;
|
||||||
final boolean shouldCompare;
|
|
||||||
|
|
||||||
switch (config) {
|
switch (config) {
|
||||||
case VANILLA:
|
case VANILLA -> calcVanilla(quad);
|
||||||
calcVanilla(quad);
|
case EMULATE -> calcFastVanilla(quad);
|
||||||
|
case HYBRID -> {
|
||||||
// no point in comparing vanilla with itself
|
if (vanillaShade) {
|
||||||
shouldCompare = false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EMULATE:
|
|
||||||
calcFastVanilla(quad);
|
|
||||||
shouldCompare = Indigo.DEBUG_COMPARE_LIGHTING && isVanilla;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case HYBRID:
|
|
||||||
default:
|
|
||||||
if (isVanilla) {
|
|
||||||
shouldCompare = Indigo.DEBUG_COMPARE_LIGHTING;
|
|
||||||
calcFastVanilla(quad);
|
calcFastVanilla(quad);
|
||||||
} else {
|
} else {
|
||||||
shouldCompare = false;
|
|
||||||
calcEnhanced(quad);
|
calcEnhanced(quad);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
case ENHANCED -> calcEnhanced(quad);
|
||||||
|
|
||||||
case ENHANCED:
|
|
||||||
shouldCompare = false;
|
|
||||||
calcEnhanced(quad);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldCompare) {
|
if (Indigo.DEBUG_COMPARE_LIGHTING && vanillaShade && (config == AoConfig.EMULATE || config == AoConfig.HYBRID)) {
|
||||||
float[] vanillaAo = new float[4];
|
float[] vanillaAo = new float[4];
|
||||||
int[] vanillaLight = new int[4];
|
int[] vanillaLight = new int[4];
|
||||||
calcVanilla(quad, vanillaAo, vanillaLight);
|
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);
|
calcVanilla(quad, ao, light);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +150,7 @@ public abstract class AoCalculator {
|
||||||
private final BitSet vanillaAoControlBits = new BitSet(3);
|
private final BitSet vanillaAoControlBits = new BitSet(3);
|
||||||
private final int[] vertexData = new int[EncodingFormat.QUAD_STRIDE];
|
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();
|
vanillaAoControlBits.clear();
|
||||||
final Direction lightFace = quad.lightFace();
|
final Direction lightFace = quad.lightFace();
|
||||||
quad.toVanilla(vertexData, 0);
|
quad.toVanilla(vertexData, 0);
|
||||||
|
@ -181,7 +162,7 @@ public abstract class AoCalculator {
|
||||||
System.arraycopy(vanillaCalc.light, 0, lightDest, 0, 4);
|
System.arraycopy(vanillaCalc.light, 0, lightDest, 0, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void calcFastVanilla(MutableQuadViewImpl quad) {
|
private void calcFastVanilla(QuadViewImpl quad) {
|
||||||
int flags = quad.geometryFlags();
|
int flags = quad.geometryFlags();
|
||||||
|
|
||||||
// force to block face if shape is full cube - matches vanilla logic
|
// 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()) {
|
switch (quad.geometryFlags()) {
|
||||||
case AXIS_ALIGNED_FLAG | CUBIC_FLAG | LIGHT_FACE_FLAG:
|
case AXIS_ALIGNED_FLAG | CUBIC_FLAG | LIGHT_FACE_FLAG:
|
||||||
case AXIS_ALIGNED_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. */
|
/** used exclusively in irregular face to avoid new heap allocations each call. */
|
||||||
private final Vector3f vertexNormal = new Vector3f();
|
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();
|
final Vector3f faceNorm = quad.faceNormal();
|
||||||
Vector3f normal;
|
Vector3f normal;
|
||||||
final float[] w = this.w;
|
final float[] w = this.w;
|
||||||
|
|
|
@ -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.MaterialFinder;
|
||||||
import net.fabricmc.fabric.api.renderer.v1.material.MaterialView;
|
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.RenderMaterial;
|
||||||
|
import net.fabricmc.fabric.api.renderer.v1.material.ShadeMode;
|
||||||
import net.fabricmc.fabric.api.util.TriState;
|
import net.fabricmc.fabric.api.util.TriState;
|
||||||
|
|
||||||
public class MaterialFinderImpl extends MaterialViewImpl implements MaterialFinder {
|
public class MaterialFinderImpl extends MaterialViewImpl implements MaterialFinder {
|
||||||
|
@ -84,6 +85,14 @@ public class MaterialFinderImpl extends MaterialViewImpl implements MaterialFind
|
||||||
return this;
|
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
|
@Override
|
||||||
public MaterialFinder copyFrom(MaterialView material) {
|
public MaterialFinder copyFrom(MaterialView material) {
|
||||||
bits = ((MaterialViewImpl) material).bits;
|
bits = ((MaterialViewImpl) material).bits;
|
||||||
|
|
|
@ -16,10 +16,13 @@
|
||||||
|
|
||||||
package net.fabricmc.fabric.impl.client.indigo.renderer.material;
|
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.minecraft.util.math.MathHelper;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.renderer.v1.material.BlendMode;
|
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.MaterialView;
|
||||||
|
import net.fabricmc.fabric.api.renderer.v1.material.ShadeMode;
|
||||||
import net.fabricmc.fabric.api.util.TriState;
|
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 int BLEND_MODE_COUNT = BLEND_MODES.length;
|
||||||
private static final TriState[] TRI_STATES = TriState.values();
|
private static final TriState[] TRI_STATES = TriState.values();
|
||||||
private static final int TRI_STATE_COUNT = TRI_STATES.length;
|
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 BLEND_MODE_BIT_LENGTH = MathHelper.ceilLog2(BLEND_MODE_COUNT);
|
||||||
protected static final int COLOR_DISABLE_BIT_LENGTH = 1;
|
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 DIFFUSE_BIT_LENGTH = 1;
|
||||||
protected static final int AO_BIT_LENGTH = MathHelper.ceilLog2(TRI_STATE_COUNT);
|
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 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 BLEND_MODE_BIT_OFFSET = 0;
|
||||||
protected static final int COLOR_DISABLE_BIT_OFFSET = BLEND_MODE_BIT_OFFSET + BLEND_MODE_BIT_LENGTH;
|
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 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 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 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 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);
|
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 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 AO_MASK = bitMask(AO_BIT_LENGTH, AO_BIT_OFFSET);
|
||||||
protected static final int GLINT_MASK = bitMask(GLINT_BIT_LENGTH, GLINT_BIT_OFFSET);
|
protected static final int GLINT_MASK = bitMask(GLINT_BIT_LENGTH, GLINT_BIT_OFFSET);
|
||||||
|
protected static final int SHADE_MODE_MASK = bitMask(SHADE_MODE_BIT_LENGTH, SHADE_MODE_BIT_OFFSET);
|
||||||
protected static int bitMask(int bitLength, int bitOffset) {
|
|
||||||
return ((1 << bitLength) - 1) << bitOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static boolean areBitsValid(int bits) {
|
protected static boolean areBitsValid(int bits) {
|
||||||
int blendMode = (bits & BLEND_MODE_MASK) >>> BLEND_MODE_BIT_OFFSET;
|
int blendMode = (bits & BLEND_MODE_MASK) >>> BLEND_MODE_BIT_OFFSET;
|
||||||
int ao = (bits & AO_MASK) >>> AO_BIT_OFFSET;
|
int ao = (bits & AO_MASK) >>> AO_BIT_OFFSET;
|
||||||
int glint = (bits & GLINT_MASK) >>> GLINT_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
|
return blendMode < BLEND_MODE_COUNT
|
||||||
&& ao < TRI_STATE_COUNT
|
&& ao < TRI_STATE_COUNT
|
||||||
&& glint < TRI_STATE_COUNT;
|
&& glint < TRI_STATE_COUNT
|
||||||
|
&& shadeMode < SHADE_MODE_COUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int bits;
|
protected int bits;
|
||||||
|
@ -105,4 +111,9 @@ public class MaterialViewImpl implements MaterialView {
|
||||||
public TriState glint() {
|
public TriState glint() {
|
||||||
return TRI_STATES[(bits & GLINT_MASK) >>> GLINT_BIT_OFFSET];
|
return TRI_STATES[(bits & GLINT_MASK) >>> GLINT_BIT_OFFSET];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ShadeMode shadeMode() {
|
||||||
|
return SHADE_MODES[(bits & SHADE_MODE_MASK) >>> SHADE_MODE_BIT_OFFSET];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package net.fabricmc.fabric.impl.client.indigo.renderer.mesh;
|
package net.fabricmc.fabric.impl.client.indigo.renderer.mesh;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import net.minecraft.client.render.VertexFormat;
|
import net.minecraft.client.render.VertexFormat;
|
||||||
import net.minecraft.client.render.VertexFormats;
|
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.mesh.QuadView;
|
||||||
import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper;
|
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.helper.GeometryHelper;
|
||||||
|
import net.fabricmc.fabric.impl.client.indigo.renderer.material.MaterialViewImpl;
|
||||||
import net.fabricmc.fabric.impl.client.indigo.renderer.material.RenderMaterialImpl;
|
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. */
|
/** used for quick clearing of quad buffers. */
|
||||||
static final int[] EMPTY = new int[TOTAL_STRIDE];
|
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_COUNT = Direction.values().length;
|
||||||
private static final int DIRECTION_BIT_COUNT = Integer.bitCount(DIRECTION_MASK);
|
private static final int NULLABLE_DIRECTION_COUNT = DIRECTION_COUNT + 1;
|
||||||
private static final int CULL_SHIFT = 0;
|
|
||||||
private static final int CULL_INVERSE_MASK = ~(DIRECTION_MASK << CULL_SHIFT);
|
private static final int CULL_BIT_LENGTH = MathHelper.ceilLog2(NULLABLE_DIRECTION_COUNT);
|
||||||
private static final int LIGHT_SHIFT = CULL_SHIFT + DIRECTION_BIT_COUNT;
|
private static final int LIGHT_BIT_LENGTH = MathHelper.ceilLog2(DIRECTION_COUNT);
|
||||||
private static final int LIGHT_INVERSE_MASK = ~(DIRECTION_MASK << LIGHT_SHIFT);
|
private static final int NORMALS_BIT_LENGTH = 4;
|
||||||
private static final int NORMALS_SHIFT = LIGHT_SHIFT + DIRECTION_BIT_COUNT;
|
private static final int GEOMETRY_BIT_LENGTH = GeometryHelper.FLAG_BIT_COUNT;
|
||||||
private static final int NORMALS_COUNT = 4;
|
private static final int MATERIAL_BIT_LENGTH = MaterialViewImpl.TOTAL_BIT_LENGTH;
|
||||||
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 CULL_BIT_OFFSET = 0;
|
||||||
private static final int GEOMETRY_SHIFT = NORMALS_SHIFT + NORMALS_COUNT;
|
private static final int LIGHT_BIT_OFFSET = CULL_BIT_OFFSET + CULL_BIT_LENGTH;
|
||||||
private static final int GEOMETRY_MASK = (1 << GeometryHelper.FLAG_BIT_COUNT) - 1;
|
private static final int NORMALS_BIT_OFFSET = LIGHT_BIT_OFFSET + LIGHT_BIT_LENGTH;
|
||||||
private static final int GEOMETRY_INVERSE_MASK = ~(GEOMETRY_MASK << GEOMETRY_SHIFT);
|
private static final int GEOMETRY_BIT_OFFSET = NORMALS_BIT_OFFSET + NORMALS_BIT_LENGTH;
|
||||||
private static final int MATERIAL_SHIFT = GEOMETRY_SHIFT + GeometryHelper.FLAG_BIT_COUNT;
|
private static final int MATERIAL_BIT_OFFSET = GEOMETRY_BIT_OFFSET + GEOMETRY_BIT_LENGTH;
|
||||||
private static final int MATERIAL_MASK = MathHelper.smallestEncompassingPowerOfTwo(RenderMaterialImpl.VALUE_COUNT) - 1;
|
private static final int TOTAL_BIT_LENGTH = MATERIAL_BIT_OFFSET + MATERIAL_BIT_LENGTH;
|
||||||
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 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 {
|
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) {
|
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) {
|
static int cullFace(int bits, @Nullable Direction face) {
|
||||||
return (bits & CULL_INVERSE_MASK) | (ModelHelper.toFaceIndex(face) << CULL_SHIFT);
|
return (bits & ~CULL_MASK) | (ModelHelper.toFaceIndex(face) << CULL_BIT_OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Direction lightFace(int bits) {
|
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) {
|
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. */
|
/** indicate if vertex normal has been set - bits correspond to vertex ordinals. */
|
||||||
static int normalFlags(int bits) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Direction;
|
import net.minecraft.util.math.Direction;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial;
|
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.mesh.QuadEmitter;
|
||||||
import net.fabricmc.fabric.api.util.TriState;
|
import net.fabricmc.fabric.api.util.TriState;
|
||||||
import net.fabricmc.fabric.impl.client.indigo.Indigo;
|
import net.fabricmc.fabric.impl.client.indigo.Indigo;
|
||||||
|
@ -55,18 +56,7 @@ public abstract class AbstractBlockRenderContext extends AbstractRenderContext {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void emitDirectly() {
|
public void emitDirectly() {
|
||||||
renderQuad(this, false);
|
renderQuad(this);
|
||||||
}
|
|
||||||
};
|
|
||||||
private final MutableQuadViewImpl vanillaModelEditorQuad = new MutableQuadViewImpl() {
|
|
||||||
{
|
|
||||||
data = new int[EncodingFormat.TOTAL_STRIDE];
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void emitDirectly() {
|
|
||||||
renderQuad(this, true);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -88,11 +78,6 @@ public abstract class AbstractBlockRenderContext extends AbstractRenderContext {
|
||||||
return editorQuad;
|
return editorQuad;
|
||||||
}
|
}
|
||||||
|
|
||||||
public QuadEmitter getVanillaModelEmitter() {
|
|
||||||
// Do not clear the editorQuad since it is not accessible to API users.
|
|
||||||
return vanillaModelEditorQuad;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isFaceCulled(@Nullable Direction face) {
|
public boolean isFaceCulled(@Nullable Direction face) {
|
||||||
return !blockInfo.shouldDrawFace(face);
|
return !blockInfo.shouldDrawFace(face);
|
||||||
|
@ -108,7 +93,7 @@ public abstract class AbstractBlockRenderContext extends AbstractRenderContext {
|
||||||
return vanillaModelConsumer;
|
return vanillaModelConsumer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderQuad(MutableQuadViewImpl quad, boolean isVanilla) {
|
private void renderQuad(MutableQuadViewImpl quad) {
|
||||||
if (!transform(quad)) {
|
if (!transform(quad)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -122,10 +107,11 @@ public abstract class AbstractBlockRenderContext extends AbstractRenderContext {
|
||||||
final TriState aoMode = mat.ambientOcclusion();
|
final TriState aoMode = mat.ambientOcclusion();
|
||||||
final boolean ao = blockInfo.useAo && (aoMode == TriState.TRUE || (aoMode == TriState.DEFAULT && blockInfo.defaultAo));
|
final boolean ao = blockInfo.useAo && (aoMode == TriState.TRUE || (aoMode == TriState.DEFAULT && blockInfo.defaultAo));
|
||||||
final boolean emissive = mat.emissive();
|
final boolean emissive = mat.emissive();
|
||||||
|
final boolean vanillaShade = mat.shadeMode() == ShadeMode.VANILLA;
|
||||||
final VertexConsumer vertexConsumer = getVertexConsumer(blockInfo.effectiveRenderLayer(mat.blendMode()));
|
final VertexConsumer vertexConsumer = getVertexConsumer(blockInfo.effectiveRenderLayer(mat.blendMode()));
|
||||||
|
|
||||||
colorizeQuad(quad, colorIndex);
|
colorizeQuad(quad, colorIndex);
|
||||||
shadeQuad(quad, isVanilla, ao, emissive);
|
shadeQuad(quad, ao, emissive, vanillaShade);
|
||||||
bufferQuad(quad, vertexConsumer);
|
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
|
// routines below have a bit of copy-paste code reuse to avoid conditional execution inside a hot loop
|
||||||
if (ao) {
|
if (ao) {
|
||||||
aoCalc.compute(quad, isVanilla);
|
aoCalc.compute(quad, vanillaShade);
|
||||||
|
|
||||||
if (emissive) {
|
if (emissive) {
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
|
@ -157,7 +143,7 @@ public abstract class AbstractBlockRenderContext extends AbstractRenderContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
shadeFlatQuad(quad, isVanilla);
|
shadeFlatQuad(quad, vanillaShade);
|
||||||
|
|
||||||
if (emissive) {
|
if (emissive) {
|
||||||
for (int i = 0; i < 4; i++) {
|
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
|
* 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.
|
* 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();
|
final boolean hasShade = quad.hasShade();
|
||||||
|
|
||||||
// Check the AO mode to match how shade is applied during smooth lighting
|
// 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()) {
|
if (quad.hasAllVertexNormals()) {
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
float shade = normalShade(quad.normalX(i), quad.normalY(i), quad.normalZ(i), hasShade);
|
float shade = normalShade(quad.normalX(i), quad.normalY(i), quad.normalZ(i), hasShade);
|
||||||
|
@ -305,7 +291,7 @@ public abstract class AbstractBlockRenderContext extends AbstractRenderContext {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(BakedModel model, @Nullable BlockState state) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
package net.fabricmc.fabric.impl.client.indigo.renderer.render;
|
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.Long2FloatOpenHashMap;
|
||||||
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
|
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.block.BlockState;
|
||||||
import net.minecraft.client.render.BufferBuilder;
|
import net.minecraft.client.render.BufferBuilder;
|
||||||
import net.minecraft.client.render.RenderLayer;
|
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.WorldRenderer;
|
||||||
import net.minecraft.client.render.chunk.BlockBufferAllocatorStorage;
|
|
||||||
import net.minecraft.client.render.chunk.ChunkRendererRegion;
|
import net.minecraft.client.render.chunk.ChunkRendererRegion;
|
||||||
import net.minecraft.client.util.BufferAllocator;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.BlockRenderView;
|
import net.minecraft.world.BlockRenderView;
|
||||||
|
|
||||||
|
@ -69,9 +65,7 @@ public class ChunkRenderInfo {
|
||||||
private final Long2IntOpenHashMap brightnessCache;
|
private final Long2IntOpenHashMap brightnessCache;
|
||||||
private final Long2FloatOpenHashMap aoLevelCache;
|
private final Long2FloatOpenHashMap aoLevelCache;
|
||||||
|
|
||||||
private final BlockPos.Mutable chunkOrigin = new BlockPos.Mutable();
|
private Function<RenderLayer, BufferBuilder> bufferFunc;
|
||||||
BlockBufferAllocatorStorage builders;
|
|
||||||
Map<RenderLayer, BufferBuilder> buffers;
|
|
||||||
BlockRenderView blockView;
|
BlockRenderView blockView;
|
||||||
|
|
||||||
ChunkRenderInfo() {
|
ChunkRenderInfo() {
|
||||||
|
@ -81,31 +75,21 @@ public class ChunkRenderInfo {
|
||||||
aoLevelCache.defaultReturnValue(Float.MAX_VALUE);
|
aoLevelCache.defaultReturnValue(Float.MAX_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepare(ChunkRendererRegion blockView, BlockPos chunkOrigin, BlockBufferAllocatorStorage builders, Map<RenderLayer, BufferBuilder> buffers) {
|
void prepare(ChunkRendererRegion blockView, Function<RenderLayer, BufferBuilder> bufferFunc) {
|
||||||
this.blockView = blockView;
|
this.blockView = blockView;
|
||||||
this.chunkOrigin.set(chunkOrigin);
|
this.bufferFunc = bufferFunc;
|
||||||
this.builders = builders;
|
|
||||||
this.buffers = buffers;
|
|
||||||
brightnessCache.clear();
|
brightnessCache.clear();
|
||||||
aoLevelCache.clear();
|
aoLevelCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void release() {
|
void release() {
|
||||||
|
blockView = null;
|
||||||
|
bufferFunc = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Lazily retrieves output buffer for given layer, initializing as needed. */
|
BufferBuilder getBuffer(RenderLayer layer) {
|
||||||
public BufferBuilder getInitializedBuffer(RenderLayer renderLayer) {
|
return bufferFunc.apply(layer);
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -16,14 +16,13 @@
|
||||||
|
|
||||||
package net.fabricmc.fabric.impl.client.indigo.renderer.render;
|
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.block.BlockState;
|
||||||
import net.minecraft.client.render.BufferBuilder;
|
import net.minecraft.client.render.BufferBuilder;
|
||||||
import net.minecraft.client.render.OverlayTexture;
|
import net.minecraft.client.render.OverlayTexture;
|
||||||
import net.minecraft.client.render.RenderLayer;
|
import net.minecraft.client.render.RenderLayer;
|
||||||
import net.minecraft.client.render.VertexConsumer;
|
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.chunk.ChunkRendererRegion;
|
||||||
import net.minecraft.client.render.model.BakedModel;
|
import net.minecraft.client.render.model.BakedModel;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
@ -69,12 +68,12 @@ public class TerrainRenderContext extends AbstractBlockRenderContext {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected VertexConsumer getVertexConsumer(RenderLayer layer) {
|
protected VertexConsumer getVertexConsumer(RenderLayer layer) {
|
||||||
return chunkInfo.getInitializedBuffer(layer);
|
return chunkInfo.getBuffer(layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void prepare(ChunkRendererRegion blockView, BlockPos chunkOrigin, BlockBufferAllocatorStorage builders, Map<RenderLayer, BufferBuilder> builderMap) {
|
public void prepare(ChunkRendererRegion blockView, Function<RenderLayer, BufferBuilder> bufferFunc) {
|
||||||
|
chunkInfo.prepare(blockView, bufferFunc);
|
||||||
blockInfo.prepareForWorld(blockView, true);
|
blockInfo.prepareForWorld(blockView, true);
|
||||||
chunkInfo.prepare(blockView, chunkOrigin, builders, builderMap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void release() {
|
public void release() {
|
||||||
|
|
|
@ -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<Random> randomSupplier, RenderContext context) {
|
|
||||||
VanillaModelEncoder.emitBlockQuads((BakedModel) this, state, randomSupplier, context, ((AbstractBlockRenderContext) context).getVanillaModelEmitter());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -17,11 +17,11 @@
|
||||||
package net.fabricmc.fabric.mixin.client.indigo.renderer;
|
package net.fabricmc.fabric.mixin.client.indigo.renderer;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import com.llamalad7.mixinextras.sugar.Local;
|
import com.llamalad7.mixinextras.sugar.Local;
|
||||||
import com.mojang.blaze3d.systems.VertexSorter;
|
import com.mojang.blaze3d.systems.VertexSorter;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
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.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
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.BlockRenderType;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.entity.BlockEntity;
|
|
||||||
import net.minecraft.client.render.BufferBuilder;
|
import net.minecraft.client.render.BufferBuilder;
|
||||||
import net.minecraft.client.render.RenderLayer;
|
import net.minecraft.client.render.RenderLayer;
|
||||||
import net.minecraft.client.render.VertexConsumer;
|
import net.minecraft.client.render.VertexConsumer;
|
||||||
|
@ -67,17 +66,19 @@ import net.fabricmc.fabric.impl.client.indigo.renderer.render.TerrainRenderConte
|
||||||
*/
|
*/
|
||||||
@Mixin(SectionBuilder.class)
|
@Mixin(SectionBuilder.class)
|
||||||
public abstract class SectionBuilderMixin {
|
public abstract class SectionBuilderMixin {
|
||||||
|
@Shadow
|
||||||
|
abstract BufferBuilder beginBufferBuilding(Map<RenderLayer, BufferBuilder> builders, BlockBufferAllocatorStorage allocatorStorage, RenderLayer layer);
|
||||||
|
|
||||||
@Inject(method = "build",
|
@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;"),
|
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)
|
locals = LocalCapture.CAPTURE_FAILHARD)
|
||||||
private void hookChunkBuild(ChunkSectionPos sectionPos, ChunkRendererRegion region, VertexSorter sorter,
|
private void hookBuild(ChunkSectionPos sectionPos, ChunkRendererRegion region, VertexSorter sorter,
|
||||||
BlockBufferAllocatorStorage builder,
|
BlockBufferAllocatorStorage allocators,
|
||||||
CallbackInfoReturnable<SectionBuilder.RenderData> ci,
|
CallbackInfoReturnable<SectionBuilder.RenderData> cir,
|
||||||
@Local(ordinal = 0) Map<RenderLayer, BufferBuilder> builderMap) {
|
@Local(ordinal = 0) Map<RenderLayer, BufferBuilder> builderMap) {
|
||||||
// hook just before iterating over the render chunk's chunks blocks, captures the buffer builder map
|
// hook just before iterating over the render chunk's blocks to capture the buffer builder map
|
||||||
|
|
||||||
TerrainRenderContext renderer = TerrainRenderContext.POOL.get();
|
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);
|
((AccessChunkRendererRegion) region).fabric_setRenderer(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +100,7 @@ public abstract class SectionBuilderMixin {
|
||||||
*/
|
*/
|
||||||
@Redirect(method = "build", require = 1, at = @At(value = "INVOKE",
|
@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"))
|
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) {
|
if (blockState.getRenderType() == BlockRenderType.MODEL) {
|
||||||
final BakedModel model = renderManager.getModel(blockState);
|
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.
|
* Release all references. Probably not necessary but would be $#%! to debug if it is.
|
||||||
*/
|
*/
|
||||||
@Inject(method = "build",
|
@Inject(method = "build", at = @At(value = "RETURN"))
|
||||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/block/BlockModelRenderer;disableBrightnessCache()V"))
|
private void hookBuildReturn(ChunkSectionPos sectionPos, ChunkRendererRegion renderRegion, VertexSorter vertexSorter, BlockBufferAllocatorStorage allocatorStorage, CallbackInfoReturnable<SectionBuilder.RenderData> cir) {
|
||||||
private void hookRebuildChunkReturn(CallbackInfoReturnable<Set<BlockEntity>> ci) {
|
((AccessChunkRendererRegion) renderRegion).fabric_getRenderer().release();
|
||||||
// hook after iterating over the render chunk's chunks blocks, must be called if and only if hookChunkBuild happened
|
((AccessChunkRendererRegion) renderRegion).fabric_setRenderer(null);
|
||||||
|
|
||||||
TerrainRenderContext.POOL.get().release();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
accessWidener v2 named
|
accessWidener v2 named
|
||||||
|
|
||||||
accessible class net/minecraft/client/render/chunk/ChunkBuilder$BuiltChunk$RebuildTask
|
|
||||||
|
|
||||||
accessible class net/minecraft/client/render/block/BlockModelRenderer$AmbientOcclusionCalculator
|
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 brightness [F
|
||||||
accessible field net/minecraft/client/render/block/BlockModelRenderer$AmbientOcclusionCalculator light [I
|
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/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
|
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
{
|
{
|
||||||
"required": true,
|
"required": true,
|
||||||
"package": "net.fabricmc.fabric.mixin.client.indigo.renderer",
|
"package": "net.fabricmc.fabric.mixin.client.indigo.renderer",
|
||||||
"compatibilityLevel": "JAVA_17",
|
"compatibilityLevel": "JAVA_21",
|
||||||
"plugin": "net.fabricmc.fabric.impl.client.indigo.IndigoMixinConfigPlugin",
|
"plugin": "net.fabricmc.fabric.impl.client.indigo.IndigoMixinConfigPlugin",
|
||||||
"mixins": [
|
"mixins": [
|
||||||
],
|
],
|
||||||
"client": [
|
"client": [
|
||||||
"BakedModelMixin",
|
|
||||||
"BlockModelRendererMixin",
|
"BlockModelRendererMixin",
|
||||||
"ChunkRendererRegionMixin",
|
"ChunkRendererRegionMixin",
|
||||||
"ItemRendererAccessor",
|
"ItemRendererAccessor",
|
||||||
|
|
Loading…
Reference in a new issue