mirror of
https://github.com/FabricMC/fabric.git
synced 2025-03-23 21:40:02 -04:00
Indigo and Renderer API fixes related to fallback consumers (#2775)
* Fix #2639: Indigo fallback consumer does not respect BlendMode or emissivity * Change renderer testmod to test material change * Remove presumably unneeded `quad.geometryFlags()` call * Also test emissivity * Call emitBlockQuads in the testmod * Allow passing the block state explicitly to the fallback consumer. Fixes #1871 * Expand testmod to also test item models * Also fix fallback consumer ignoring material for items * Slight changes * Introduce new interface for the expanded fallback consumer * Add javadoc to ModelHelper (cherry picked from commit9f179aa14c
) (cherry picked from commit2e5408b563
)
This commit is contained in:
parent
88087ab966
commit
6bd39c990e
12 changed files with 220 additions and 113 deletions
fabric-renderer-api-v1/src
main/java/net/fabricmc/fabric
api/renderer/v1
mixin/renderer/client
testmod/java/net/fabricmc/fabric/test/renderer/simple/client
fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer/render
|
@ -36,6 +36,8 @@ import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
|||
* Can also be used to generate or customize outputs based on world state instead of
|
||||
* or in addition to block state when render chunks are rebuilt.
|
||||
*
|
||||
* <p>Implementors should have a look at {@link ModelHelper} as it contains many useful functions.
|
||||
*
|
||||
* <p>Note for {@link Renderer} implementors: Fabric causes BakedModel to extend this
|
||||
* interface with {@link #isVanillaAdapter()} == true and to produce standard vertex data.
|
||||
* This means any BakedModel instance can be safely cast to this interface without an instanceof check.
|
||||
|
@ -82,7 +84,7 @@ public interface FabricBakedModel {
|
|||
* parameter is normally initialized with the same seed prior to each face layer.
|
||||
* Model authors should note this method is called only once per block, and call the provided
|
||||
* Random supplier multiple times if re-seeding is necessary. For wrapped vanilla baked models,
|
||||
* it will probably be easier to use {@link RenderContext#fallbackConsumer} which handles
|
||||
* it will probably be easier to use {@link RenderContext#bakedModelConsumer()} which handles
|
||||
* re-seeding per face automatically.
|
||||
*
|
||||
* @param blockView Access to world state. Using {@link net.fabricmc.fabric.api.rendering.data.v1.RenderAttachedBlockView#getBlockEntityRenderAttachment(BlockPos)} to
|
||||
|
|
|
@ -18,6 +18,9 @@ package net.fabricmc.fabric.api.renderer.v1.render;
|
|||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh;
|
||||
|
@ -39,11 +42,64 @@ public interface RenderContext {
|
|||
Consumer<Mesh> meshConsumer();
|
||||
|
||||
/**
|
||||
* Fallback consumer that can process a vanilla {@link BakedModel}.
|
||||
* Fabric causes vanilla baked models to send themselves
|
||||
* via this interface. Can also be used by compound models that contain a mix
|
||||
* of vanilla baked models, packaged quads and/or dynamic elements.
|
||||
*/
|
||||
Consumer<BakedModel> fallbackConsumer();
|
||||
default BakedModelConsumer bakedModelConsumer() {
|
||||
// Default implementation is provided for compat with older renderer implementations,
|
||||
// but they should always override this function.
|
||||
Consumer<BakedModel> fallback = fallbackConsumer();
|
||||
return new BakedModelConsumer() {
|
||||
@Override
|
||||
public void accept(BakedModel model) {
|
||||
fallback.accept(model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(BakedModel model, @Nullable BlockState state) {
|
||||
fallback.accept(model);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
interface BakedModelConsumer extends Consumer<BakedModel> {
|
||||
/**
|
||||
* Render a baked model by processing its {@linkplain BakedModel#getQuads} using the rendered block state.
|
||||
*
|
||||
* <p>For block contexts, this will pass the block state being rendered to {@link BakedModel#getQuads}.
|
||||
* For item contexts, this will pass a {@code null} block state to {@link BakedModel#getQuads}.
|
||||
* {@link #accept(BakedModel, BlockState)} can be used instead to pass the block state explicitly.
|
||||
*/
|
||||
@Override
|
||||
void accept(BakedModel model);
|
||||
|
||||
/**
|
||||
* Render a baked model by processing its {@linkplain BakedModel#getQuads} with an explicit block state.
|
||||
*
|
||||
* <p>This overload allows passing the block state (or {@code null} to query the item quads).
|
||||
* This is useful when a model is being wrapped, and expects a different
|
||||
* block state than the one of the block being rendered.
|
||||
*
|
||||
* <p>For item render contexts, you can use this function if you want to render the model with a specific block state.
|
||||
* Otherwise, use {@linkplain #accept(BakedModel)} the other overload} to render the usual item quads.
|
||||
*/
|
||||
void accept(BakedModel model, @Nullable BlockState state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fabric causes vanilla baked models to send themselves
|
||||
* via this interface. Can also be used by compound models that contain a mix
|
||||
* of vanilla baked models, packaged quads and/or dynamic elements.
|
||||
*
|
||||
* @deprecated Prefer using the more flexible {@link #bakedModelConsumer}.
|
||||
*/
|
||||
@Deprecated
|
||||
default Consumer<BakedModel> fallbackConsumer() {
|
||||
// This default implementation relies on implementors overriding bakedModelConsumer().
|
||||
return bakedModelConsumer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link QuadEmitter} instance that emits directly to the render buffer.
|
||||
|
|
|
@ -42,11 +42,12 @@ public interface MixinBakedModel extends FabricBakedModel {
|
|||
|
||||
@Override
|
||||
default void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
|
||||
context.fallbackConsumer().accept((BakedModel) this);
|
||||
context.bakedModelConsumer().accept((BakedModel) this, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
default void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {
|
||||
context.fallbackConsumer().accept((BakedModel) this);
|
||||
// Pass null state to enforce item quads in block render contexts
|
||||
context.bakedModelConsumer().accept((BakedModel) this, null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.jetbrains.annotations.Nullable;
|
|||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
|
@ -36,20 +37,29 @@ import net.minecraft.util.math.BlockPos;
|
|||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
|
||||
import net.fabricmc.fabric.api.renderer.v1.Renderer;
|
||||
import net.fabricmc.fabric.api.renderer.v1.RendererAccess;
|
||||
import net.fabricmc.fabric.api.renderer.v1.material.BlendMode;
|
||||
import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh;
|
||||
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.model.FabricBakedModel;
|
||||
import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||
import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachedBlockView;
|
||||
|
||||
final class FrameBakedModel implements BakedModel, FabricBakedModel {
|
||||
private final Mesh frameMesh;
|
||||
private final Sprite frameSprite;
|
||||
private final RenderMaterial translucentMaterial;
|
||||
private final RenderMaterial translucentEmissiveMaterial;
|
||||
|
||||
FrameBakedModel(Mesh frameMesh, Sprite frameSprite) {
|
||||
this.frameMesh = frameMesh;
|
||||
this.frameSprite = frameSprite;
|
||||
|
||||
Renderer renderer = RendererAccess.INSTANCE.getRenderer();
|
||||
this.translucentMaterial = renderer.materialFinder().blendMode(0, BlendMode.TRANSLUCENT).find();
|
||||
this.translucentEmissiveMaterial = renderer.materialFinder().blendMode(0, BlendMode.TRANSLUCENT).emissive(0, true).find();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -69,7 +79,7 @@ final class FrameBakedModel implements BakedModel, FabricBakedModel {
|
|||
|
||||
@Override
|
||||
public boolean isSideLit() {
|
||||
return false;
|
||||
return true; // we want the block to be lit from the side when rendered as an item
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -84,7 +94,7 @@ final class FrameBakedModel implements BakedModel, FabricBakedModel {
|
|||
|
||||
@Override
|
||||
public ModelTransformation getTransformation() {
|
||||
return ModelTransformation.NONE;
|
||||
return ModelHelper.MODEL_TRANSFORM_BLOCK;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -112,27 +122,71 @@ final class FrameBakedModel implements BakedModel, FabricBakedModel {
|
|||
return; // No inner block to render
|
||||
}
|
||||
|
||||
Sprite sprite = MinecraftClient.getInstance().getBlockRenderManager().getModels().getModelManager().getBlockModels().getModelParticleSprite(data.getDefaultState());
|
||||
QuadEmitter emitter = context.getEmitter();
|
||||
BlockState innerState = data.getDefaultState();
|
||||
|
||||
// We can emit our quads outside of the mesh as the block being put in the frame is very much dynamic.
|
||||
// Emit the quads for each face of the block inside the frame
|
||||
for (Direction direction : Direction.values()) {
|
||||
// Add a face, with an inset to give the appearance of the block being in a frame.
|
||||
emitter.square(direction, 0.1F, 0.1F, 0.9F, 0.9F, 0.1F)
|
||||
// Set the sprite of the fact, use whole texture via BAKE_LOCK_UV
|
||||
.spriteBake(0, sprite, MutableQuadView.BAKE_LOCK_UV)
|
||||
// Allow textures
|
||||
// TODO: the magic values here are not documented at all and probably should be
|
||||
.spriteColor(0, -1, -1, -1, -1)
|
||||
// Emit the quad
|
||||
.emit();
|
||||
}
|
||||
// Now, we emit a transparent scaled-down version of the inner model
|
||||
// Try both emissive and non-emissive versions of the translucent material
|
||||
RenderMaterial material = pos.getX() % 2 == 0 ? translucentMaterial : translucentEmissiveMaterial;
|
||||
|
||||
emitInnerQuads(context, material, () -> {
|
||||
// Use emitBlockQuads to allow for Renderer API features
|
||||
((FabricBakedModel) MinecraftClient.getInstance().getBlockRenderManager().getModel(innerState)).emitBlockQuads(blockView, innerState, pos, randomSupplier, context);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {
|
||||
// TODO: Implement an item test.
|
||||
// For now we will just leave this as I have not added a block item yet
|
||||
// Emit our frame mesh
|
||||
context.meshConsumer().accept(this.frameMesh);
|
||||
|
||||
// Emit a scaled-down fence for testing, trying both materials again.
|
||||
RenderMaterial material = stack.hasCustomName() ? translucentEmissiveMaterial : translucentMaterial;
|
||||
|
||||
BlockState innerState = Blocks.OAK_FENCE.getDefaultState();
|
||||
|
||||
emitInnerQuads(context, material, () -> {
|
||||
// Need to use the fallback consumer directly:
|
||||
// - we can't use emitBlockQuads because we don't have a blockView
|
||||
// - we can't use emitItemQuads because multipart models don't have item quads
|
||||
context.bakedModelConsumer().accept(MinecraftClient.getInstance().getBlockRenderManager().getModel(innerState), innerState);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit a scaled-down version of the inner model.
|
||||
*/
|
||||
private void emitInnerQuads(RenderContext context, RenderMaterial material, Runnable innerModelEmitter) {
|
||||
// Let's push a transform to scale the model down and make it transparent
|
||||
context.pushTransform(quad -> {
|
||||
// Scale model down
|
||||
for (int vertex = 0; vertex < 4; ++vertex) {
|
||||
float x = quad.x(vertex) * 0.8f + 0.1f;
|
||||
float y = quad.y(vertex) * 0.8f + 0.1f;
|
||||
float z = quad.z(vertex) * 0.8f + 0.1f;
|
||||
quad.pos(vertex, x, y, z);
|
||||
}
|
||||
|
||||
// Make the quad partially transparent
|
||||
// Change material to translucent
|
||||
quad.material(material);
|
||||
|
||||
// Change vertex colors to be partially transparent
|
||||
for (int vertex = 0; vertex < 4; ++vertex) {
|
||||
int color = quad.spriteColor(vertex, 0);
|
||||
int alpha = (color >> 24) & 0xFF;
|
||||
alpha = alpha * 3 / 4;
|
||||
color = (color & 0xFFFFFF) | (alpha << 24);
|
||||
quad.spriteColor(vertex, 0, color);
|
||||
}
|
||||
|
||||
// Return true because we want the quad to be rendered
|
||||
return true;
|
||||
});
|
||||
|
||||
// Emit the inner block model
|
||||
innerModelEmitter.run();
|
||||
|
||||
// Let's not forget to pop the transform!
|
||||
context.popTransform();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
|
||||
package net.fabricmc.fabric.test.renderer.simple.client;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.client.render.model.UnbakedModel;
|
||||
|
@ -28,12 +31,12 @@ import net.fabricmc.fabric.api.client.model.ModelResourceProvider;
|
|||
* Provides the unbaked model for use with the frame block.
|
||||
*/
|
||||
final class FrameModelResourceProvider implements ModelResourceProvider {
|
||||
private static final Identifier FRAME_MODEL_ID = new Identifier("fabric-renderer-api-v1-testmod", "block/frame");
|
||||
static final Set<Identifier> FRAME_MODELS = new HashSet<>();
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public UnbakedModel loadModelResource(Identifier resourceId, ModelProviderContext context) {
|
||||
if (resourceId.equals(FRAME_MODEL_ID)) {
|
||||
if (FRAME_MODELS.contains(resourceId)) {
|
||||
return new FrameUnbakedModel();
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,10 @@
|
|||
|
||||
package net.fabricmc.fabric.test.renderer.simple.client;
|
||||
|
||||
import static net.fabricmc.fabric.test.renderer.simple.RendererTest.id;
|
||||
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
|
||||
import net.fabricmc.api.ClientModInitializer;
|
||||
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
|
||||
|
@ -31,7 +34,14 @@ public final class RendererClientTest implements ClientModInitializer {
|
|||
ModelLoadingRegistry.INSTANCE.registerVariantProvider(manager -> new PillarModelVariantProvider());
|
||||
|
||||
for (FrameBlock frameBlock : RendererTest.FRAMES) {
|
||||
// We don't specify a material for the frame mesh,
|
||||
// so it will use the default material, i.e. the one from BlockRenderLayerMap.
|
||||
BlockRenderLayerMap.INSTANCE.putBlock(frameBlock, RenderLayer.getCutoutMipped());
|
||||
|
||||
String itemPath = Registry.ITEM.getId(frameBlock.asItem()).getPath();
|
||||
FrameModelResourceProvider.FRAME_MODELS.add(id("item/" + itemPath));
|
||||
}
|
||||
|
||||
FrameModelResourceProvider.FRAME_MODELS.add(id("block/frame"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh;
|
|||
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext.QuadTransform;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.IndigoRenderer;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.RenderMaterialImpl;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.aocalc.AoCalculator;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.EncodingFormat;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MeshImpl;
|
||||
|
@ -55,7 +54,7 @@ public abstract class AbstractMeshConsumer extends AbstractQuadRenderer implemen
|
|||
@Override
|
||||
public Maker emit() {
|
||||
computeGeometry();
|
||||
renderQuad(this);
|
||||
renderQuad(this, false);
|
||||
clear();
|
||||
return this;
|
||||
}
|
||||
|
@ -74,7 +73,7 @@ public abstract class AbstractMeshConsumer extends AbstractQuadRenderer implemen
|
|||
System.arraycopy(data, index, editorQuad.data(), 0, EncodingFormat.TOTAL_STRIDE);
|
||||
editorQuad.load();
|
||||
index += EncodingFormat.TOTAL_STRIDE;
|
||||
renderQuad(editorQuad);
|
||||
renderQuad(editorQuad, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,43 +81,4 @@ public abstract class AbstractMeshConsumer extends AbstractQuadRenderer implemen
|
|||
editorQuad.clear();
|
||||
return editorQuad;
|
||||
}
|
||||
|
||||
private void renderQuad(MutableQuadViewImpl quad) {
|
||||
if (!transform.transform(quad)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!blockInfo.shouldDrawFace(quad.cullFace())) {
|
||||
return;
|
||||
}
|
||||
|
||||
tessellateQuad(quad, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines color index and render layer, then routes to appropriate
|
||||
* tessellate routine based on material properties.
|
||||
*/
|
||||
private void tessellateQuad(MutableQuadViewImpl quad, int textureIndex) {
|
||||
final RenderMaterialImpl.Value mat = quad.material();
|
||||
final int colorIndex = mat.disableColorIndex(textureIndex) ? -1 : quad.colorIndex();
|
||||
final RenderLayer renderLayer = blockInfo.effectiveRenderLayer(mat.blendMode(textureIndex));
|
||||
|
||||
if (blockInfo.defaultAo && !mat.disableAo(textureIndex)) {
|
||||
// needs to happen before offsets are applied
|
||||
aoCalc.compute(quad, false);
|
||||
|
||||
if (mat.emissive(textureIndex)) {
|
||||
tessellateSmoothEmissive(quad, renderLayer, colorIndex);
|
||||
} else {
|
||||
tessellateSmooth(quad, renderLayer, colorIndex);
|
||||
}
|
||||
} else {
|
||||
if (mat.emissive(textureIndex)) {
|
||||
tessellateFlatEmissive(quad, renderLayer, colorIndex);
|
||||
} else {
|
||||
tessellateFlat(quad, renderLayer, colorIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import net.minecraft.util.math.Matrix4f;
|
|||
import net.minecraft.util.math.Vec3f;
|
||||
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext.QuadTransform;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.RenderMaterialImpl;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.aocalc.AoCalculator;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.helper.ColorHelper;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.helper.GeometryHelper;
|
||||
|
@ -62,6 +63,45 @@ public abstract class AbstractQuadRenderer {
|
|||
this.transform = transform;
|
||||
}
|
||||
|
||||
protected void renderQuad(MutableQuadViewImpl quad, boolean isVanilla) {
|
||||
if (!transform.transform(quad)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!blockInfo.shouldDrawFace(quad.cullFace())) {
|
||||
return;
|
||||
}
|
||||
|
||||
tessellateQuad(quad, 0, isVanilla);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines color index and render layer, then routes to appropriate
|
||||
* tessellate routine based on material properties.
|
||||
*/
|
||||
private void tessellateQuad(MutableQuadViewImpl quad, int textureIndex, boolean isVanilla) {
|
||||
final RenderMaterialImpl.Value mat = quad.material();
|
||||
final int colorIndex = mat.disableColorIndex(textureIndex) ? -1 : quad.colorIndex();
|
||||
final RenderLayer renderLayer = blockInfo.effectiveRenderLayer(mat.blendMode(textureIndex));
|
||||
|
||||
if (blockInfo.defaultAo && !mat.disableAo(textureIndex)) {
|
||||
// needs to happen before offsets are applied
|
||||
aoCalc.compute(quad, isVanilla);
|
||||
|
||||
if (mat.emissive(textureIndex)) {
|
||||
tessellateSmoothEmissive(quad, renderLayer, colorIndex);
|
||||
} else {
|
||||
tessellateSmooth(quad, renderLayer, colorIndex);
|
||||
}
|
||||
} else {
|
||||
if (mat.emissive(textureIndex)) {
|
||||
tessellateFlatEmissive(quad, renderLayer, colorIndex);
|
||||
} else {
|
||||
tessellateFlat(quad, renderLayer, colorIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** handles block color and red-blue swizzle, common to all renders. */
|
||||
private void colorizeQuad(MutableQuadViewImpl q, int blockColorIndex) {
|
||||
if (blockColorIndex == -1) {
|
||||
|
|
|
@ -141,7 +141,7 @@ public class BlockRenderContext extends AbstractRenderContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Consumer<BakedModel> fallbackConsumer() {
|
||||
public BakedModelConsumer bakedModelConsumer() {
|
||||
return fallbackConsumer;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@ import java.util.Random;
|
|||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.color.item.ItemColors;
|
||||
|
@ -265,21 +267,27 @@ public class ItemRenderContext extends AbstractRenderContext {
|
|||
}
|
||||
}
|
||||
|
||||
private class FallbackConsumer implements Consumer<BakedModel> {
|
||||
private class FallbackConsumer implements BakedModelConsumer {
|
||||
@Override
|
||||
public void accept(BakedModel model) {
|
||||
accept(model, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(BakedModel model, @Nullable BlockState state) {
|
||||
if (hasTransform()) {
|
||||
// if there's a transform in effect, convert to mesh-based quads so that we can apply it
|
||||
for (int i = 0; i <= ModelHelper.NULL_FACE_ID; i++) {
|
||||
final Direction cullFace = ModelHelper.faceFromIndex(i);
|
||||
random.setSeed(ITEM_RANDOM_SEED);
|
||||
final List<BakedQuad> quads = model.getQuads(null, cullFace, random);
|
||||
final List<BakedQuad> quads = model.getQuads(state, cullFace, random);
|
||||
final int count = quads.size();
|
||||
|
||||
if (count != 0) {
|
||||
for (int j = 0; j < count; j++) {
|
||||
final BakedQuad q = quads.get(j);
|
||||
renderQuadWithTransform(q, cullFace);
|
||||
editorQuad.fromVanilla(q, IndigoRenderer.MATERIAL_STANDARD, cullFace);
|
||||
renderMeshQuad(editorQuad);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -287,17 +295,6 @@ public class ItemRenderContext extends AbstractRenderContext {
|
|||
vanillaHandler.accept(model, itemStack, lightmap, overlay, matrixStack, modelVertexConsumer);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderQuadWithTransform(BakedQuad quad, Direction cullFace) {
|
||||
final Maker editorQuad = ItemRenderContext.this.editorQuad;
|
||||
editorQuad.fromVanilla(quad, IndigoRenderer.MATERIAL_STANDARD, cullFace);
|
||||
|
||||
if (!transform(editorQuad)) {
|
||||
return;
|
||||
}
|
||||
|
||||
renderQuad(editorQuad, BlendMode.DEFAULT, editorQuad.colorIndex());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -306,7 +303,7 @@ public class ItemRenderContext extends AbstractRenderContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Consumer<BakedModel> fallbackConsumer() {
|
||||
public BakedModelConsumer bakedModelConsumer() {
|
||||
return fallbackConsumer;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@ import java.util.function.Consumer;
|
|||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
|
@ -31,6 +33,7 @@ import net.minecraft.util.math.Direction;
|
|||
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
|
||||
import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext.QuadTransform;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.IndigoRenderer;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.RenderMaterialImpl.Value;
|
||||
|
@ -57,7 +60,7 @@ import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MutableQuadViewImpl;
|
|||
* vertex data is sent to the byte buffer. Generally POJO array access will be faster than
|
||||
* manipulating the data via NIO.
|
||||
*/
|
||||
public abstract class TerrainFallbackConsumer extends AbstractQuadRenderer implements Consumer<BakedModel> {
|
||||
public abstract class TerrainFallbackConsumer extends AbstractQuadRenderer implements RenderContext.BakedModelConsumer {
|
||||
private static final Value MATERIAL_FLAT = (Value) IndigoRenderer.INSTANCE.materialFinder().disableAo(0, true).find();
|
||||
private static final Value MATERIAL_SHADED = (Value) IndigoRenderer.INSTANCE.materialFinder().find();
|
||||
|
||||
|
@ -79,10 +82,14 @@ public abstract class TerrainFallbackConsumer extends AbstractQuadRenderer imple
|
|||
};
|
||||
|
||||
@Override
|
||||
public void accept(BakedModel model) {
|
||||
public void accept(BakedModel bakedModel) {
|
||||
accept(bakedModel, blockInfo.blockState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(BakedModel model, @Nullable BlockState blockState) {
|
||||
final Supplier<Random> random = blockInfo.randomSupplier;
|
||||
final Value defaultMaterial = blockInfo.defaultAo && model.useAmbientOcclusion() ? MATERIAL_SHADED : MATERIAL_FLAT;
|
||||
final BlockState blockState = blockInfo.blockState;
|
||||
|
||||
for (int i = 0; i <= ModelHelper.NULL_FACE_ID; i++) {
|
||||
final Direction cullFace = ModelHelper.faceFromIndex(i);
|
||||
|
@ -102,29 +109,6 @@ public abstract class TerrainFallbackConsumer extends AbstractQuadRenderer imple
|
|||
final MutableQuadViewImpl editorQuad = this.editorQuad;
|
||||
editorQuad.fromVanilla(quad, defaultMaterial, cullFace);
|
||||
|
||||
if (!transform.transform(editorQuad)) {
|
||||
return;
|
||||
}
|
||||
|
||||
cullFace = editorQuad.cullFace();
|
||||
|
||||
if (cullFace != null && !blockInfo.shouldDrawFace(cullFace)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!editorQuad.material().disableAo(0)) {
|
||||
// needs to happen before offsets are applied
|
||||
aoCalc.compute(editorQuad, true);
|
||||
tessellateSmooth(editorQuad, blockInfo.defaultLayer, editorQuad.colorIndex());
|
||||
} else {
|
||||
// Recomputing whether the quad has a light face is only needed if it doesn't also have a cull face,
|
||||
// as in those cases, the cull face will always be used to offset the light sampling position
|
||||
if (cullFace == null) {
|
||||
// Can't rely on lazy computation in tessellateFlat() because needs to happen before offsets are applied
|
||||
editorQuad.geometryFlags();
|
||||
}
|
||||
|
||||
tessellateFlat(editorQuad, blockInfo.defaultLayer, editorQuad.colorIndex());
|
||||
}
|
||||
renderQuad(editorQuad, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ public class TerrainRenderContext extends AbstractRenderContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Consumer<BakedModel> fallbackConsumer() {
|
||||
public BakedModelConsumer bakedModelConsumer() {
|
||||
return fallbackConsumer;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue