19w38b API Fixes ()

* Fix compilation errors (untested)

* Random fixes

* Various modded rendering fixes

* Restore contract of RenderAttachedBlockView

* Bump versions as needed

* Add API for BlockRenderLayer

* Minor format / name cleanup

Will do a more comprehensive pass as part of separate refactor PR

* Bump versions not handled earlier

* Bump loader/mc bounds for dependent modules

* Update fabric-blockrenderlayer-v1/src/main/java/net/fabricmc/fabric/impl/blockrenderlayer/v1/BlockRenderLayerMapImpl.java

Co-Authored-By: liach <7806504+liach@users.noreply.github.com>

* Update fabric-blockrenderlayer-v1/src/main/java/net/fabricmc/fabric/impl/blockrenderlayer/v1/BlockRenderLayerMapImpl.java

Co-Authored-By: liach <7806504+liach@users.noreply.github.com>

* Minor clean ups

* Improve docs, minor format corrections.

* Update MC dependency
This commit is contained in:
grondag 2019-09-20 16:50:49 -07:00 committed by GitHub
parent d32291da65
commit d2ac651a7a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
46 changed files with 677 additions and 366 deletions
fabric-blockrenderlayer-v1
build.gradle
src/main
java/net/fabricmc/fabric
api/blockrenderlayer/v1
impl/blockrenderlayer/v1
mixin/blockrenderlayer
resources
fabric-events-interaction-v0
build.gradle
src/main/java/net/fabricmc/fabric/mixin/eventsinteraction
fabric-item-groups-v0
fabric-loot-tables-v1
fabric-registry-sync-v0
fabric-renderer-api-v1
build.gradle
src/main
java/net/fabricmc/fabric
resources
fabric-renderer-indigo
fabric-rendering-data-attachment-v1
build.gradle
src/main/java/net/fabricmc/fabric
api/rendering/data/v1
mixin/rendering/data
fabric-rendering-fluids-v1
fabric-resource-loader-v0
settings.gradle
src/main/resources

View file

@ -0,0 +1,6 @@
archivesBaseName = "fabric-blockrenderlayer-v1"
version = getSubprojectVersion(project, "1.0.0")
dependencies {
compile project(path: ':fabric-api-base', configuration: 'dev')
}

View file

@ -0,0 +1,56 @@
/*
* 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.blockrenderlayer.v1;
import net.fabricmc.fabric.impl.blockrenderlayer.v1.BlockRenderLayerMapImpl;
import net.minecraft.block.Block;
import net.minecraft.block.BlockRenderLayer;
import net.minecraft.fluid.Fluid;
/**
* Use to associate blocks or fluids with block render layer other than default.
* Replaces the {@code renderLayer} property previously on {@code Block}.<p>
*
* {@code BlockRenderLayer} controls how sprite pixels for fluids and blocks are blended
* with the scene. Consult the vanilla {@code BlockRenderLayer} implementation for examples.<p>
*
* The Fabric Renderer API can be used to control this at a per-quad level at the code
* via {@code BlendMode}.<p>
*
* Client-side only.
*/
public interface BlockRenderLayerMap {
BlockRenderLayerMap INSTANCE = BlockRenderLayerMapImpl.INSTANCE;
/**
* Map (or re-map) a block state with a render layer. Re-mapping is not recommended but if done, last one in wins.
* Must be called from client thread prior to world load/rendering. Best practice will be to call from mod's client initializer.
*
* @param block Identifies block to be mapped.
* @param renderLayer Render layer. Should be one of the layers used for terrain rendering.
*/
void putBlock(Block block, BlockRenderLayer renderLayer);
/**
* Map (or re-map) a fluid state with a render layer. Re-mapping is not recommended but if done, last one in wins.
* Must be called from client thread prior to world load/rendering. Best practice will be to call from mod's client initializer.
*
* @param fluid Identifies fluid to be mapped.
* @param renderLayer Render layer. Should be one of the layers used for terrain rendering.
*/
void putFluid(Fluid fluid, BlockRenderLayer renderLayer);
}

View file

@ -0,0 +1,74 @@
/*
* 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.impl.blockrenderlayer.v1;
import java.util.function.BiConsumer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
import net.minecraft.block.Block;
import net.minecraft.block.BlockRenderLayer;
import net.minecraft.fluid.Fluid;
public class BlockRenderLayerMapImpl implements BlockRenderLayerMap {
private BlockRenderLayerMapImpl() {}
@Override
public void putBlock(Block block, BlockRenderLayer renderLayer) {
if (block == null) {
LOG.warn("Ignoring request to map null block to BlockRenderLayer");
} else if (renderLayer == null) {
LOG.warn("Ignoring request to map block " + block.toString() + " to null BlockRenderLayer");
} else {
blockHandler.accept(block, renderLayer);
}
}
@Override
public void putFluid(Fluid fluid, BlockRenderLayer renderLayer) {
if (fluid == null) {
LOG.warn("Ignoring request to map null fluid to BlockRenderLayer");
} else if (renderLayer == null) {
LOG.warn("Ignoring request to map fluid " + fluid.toString() + " to null BlockRenderLayer");
} else {
fluidHandler.accept(fluid, renderLayer);
}
}
public static final BlockRenderLayerMap INSTANCE = new BlockRenderLayerMapImpl();
private static final Logger LOG = LogManager.getLogger();
// These should never be used before our Mixin populates them because a non-null BRL instance is
// a required parameter of our methods. They are given dummy consumers that log
// warnings in case something goes wrong.
private static BiConsumer<Block, BlockRenderLayer> blockHandler = (b, l) -> {
LOG.warn("Unable to map Block {} to BlockRenderLayer. Mapping handler not ready.", b);
};
private static BiConsumer<Fluid, BlockRenderLayer> fluidHandler = (f, b) -> {
LOG.warn("Unable to map Fluid {} to BlockRenderLayer. Mapping handler not ready.", f);
};
public static void initialize(BiConsumer<Block, BlockRenderLayer> blockHandlerIn, BiConsumer<Fluid, BlockRenderLayer> fluidHandlerIn) {
blockHandler = blockHandlerIn;
fluidHandler = fluidHandlerIn;
}
}

View file

@ -0,0 +1,41 @@
/*
* 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.blockrenderlayer;
import java.util.Map;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.fabricmc.fabric.impl.blockrenderlayer.v1.BlockRenderLayerMapImpl;
import net.minecraft.block.Block;
import net.minecraft.block.BlockRenderLayer;
import net.minecraft.fluid.Fluid;
@Mixin(BlockRenderLayer.class)
public class MixinBlockRenderLayer {
@Shadow private static Map<Block, BlockRenderLayer> field_20803;
@Shadow private static Map<Fluid, BlockRenderLayer> field_20804;
@Inject(method = "<clinit>*", at = @At("RETURN"))
private static void onInitialize(CallbackInfo info) {
BlockRenderLayerMapImpl.initialize(field_20803::put, field_20804::put);
}
}

Binary file not shown.

After

(image error) Size: 1.5 KiB

View file

@ -0,0 +1,11 @@
{
"required": true,
"package": "net.fabricmc.fabric.mixin.blockrenderlayer",
"compatibilityLevel": "JAVA_8",
"client": [
"MixinBlockRenderLayer"
],
"injectors": {
"defaultRequire": 1
}
}

View file

@ -0,0 +1,27 @@
{
"schemaVersion": 1,
"id": "fabric-blockrenderlayer-v1",
"name": "Fabric BlockRenderLayer Registration (v1)",
"version": "${version}",
"environment": "client",
"license": "Apache-2.0",
"icon": "assets/fabric-blockrenderlayer-v1/icon.png",
"contact": {
"homepage": "https://fabricmc.net",
"irc": "irc://irc.esper.net:6667/fabric",
"issues": "https://github.com/FabricMC/fabric/issues",
"sources": "https://github.com/FabricMC/fabric"
},
"authors": [
"FabricMC"
],
"depends": {
"fabricloader": ">=0.6.2",
"minecraft": ">=1.15-alpha.19.38.b",
"fabric-api-base": "*"
},
"description": "Registration utility for block and fluid render layers.",
"mixins": [
"fabric-blockrenderlayer-v1.mixins.json"
]
}

View file

@ -1,5 +1,5 @@
archivesBaseName = "fabric-events-interaction-v0"
version = getSubprojectVersion(project, "0.1.2")
version = getSubprojectVersion(project, "0.1.3")
dependencies {
compile project(path: ':fabric-api-base', configuration: 'dev')

View file

@ -46,7 +46,7 @@ public class MixinServerPlayerInteractionManager {
@Shadow
public ServerPlayerEntity player;
@Inject(at = @At("HEAD"), method = "method_14263", cancellable = true)
@Inject(at = @At("HEAD"), method = "processBlockBreakingAction", cancellable = true)
public void startBlockBreak(BlockPos pos, PlayerActionC2SPacket.Action playerAction, Direction direction, int i, CallbackInfo info) {
ActionResult result = AttackBlockCallback.EVENT.invoker().interact(player, world, Hand.MAIN_HAND, pos, direction);
if (result != ActionResult.PASS) {

View file

@ -1,5 +1,5 @@
archivesBaseName = "fabric-item-groups-v0"
version = getSubprojectVersion(project, "0.1.1")
version = getSubprojectVersion(project, "0.1.2")
dependencies {
compile project(path: ':fabric-api-base', configuration: 'dev')

View file

@ -1,5 +1,5 @@
archivesBaseName = "fabric-loot-tables-v1"
version = getSubprojectVersion(project, "0.1.0")
version = getSubprojectVersion(project, "0.1.1")
dependencies {
compile project(path: ':fabric-api-base', configuration: 'dev')

View file

@ -1,5 +1,5 @@
archivesBaseName = "fabric-registry-sync-v0"
version = getSubprojectVersion(project, "0.2.2")
version = getSubprojectVersion(project, "0.2.3")
dependencies {
compile project(path: ':fabric-api-base', configuration: 'dev')

View file

@ -1,5 +1,5 @@
archivesBaseName = "fabric-renderer-api-v1"
version = getSubprojectVersion(project, "0.1.1")
version = getSubprojectVersion(project, "0.2.0")
dependencies {
compile project(path: ':fabric-api-base', configuration: 'dev')

View file

@ -0,0 +1,72 @@
/*
* 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;
import net.minecraft.block.BlockRenderLayer;
/**
* Defines how sprite pixels will be blended with the scene.
*/
public enum BlendMode {
/**
* Emulate blending behavior of {@code BlockRenderLayer} associated with the block.
*/
DEFAULT(null),
/**
* Fully opaque with depth test, no blending. Used for most normal blocks.
*/
SOLID(BlockRenderLayer.field_9178),
/**
* Pixels with alpha > 0.5 are rendered as if {@code SOLID}. Other pixels are not rendered.
* Texture mip-map enabled. Used for leaves.
*/
CUTOUT_MIPPED(BlockRenderLayer.CUTOUT_MIPPED),
/**
* Pixels with alpha > 0.5 are rendered as if {@code SOLID}. Other pixels are not rendered.
* Texture mip-map disabled. Used for iron bars, glass and other cutout sprites with hard edges.
*/
CUTOUT(BlockRenderLayer.field_9174),
/**
* Pixels are blended with the background according to alpha color values. Some performance cost,
* use in moderation. Texture mip-map enabled. Used for stained glass.
*/
TRANSLUCENT(BlockRenderLayer.field_9179);
public final BlockRenderLayer blockRenderLayer;
private BlendMode(BlockRenderLayer blockRenderLayer) {
this.blockRenderLayer = blockRenderLayer;
}
public static BlendMode fromRenderLayer(BlockRenderLayer renderLayer) {
if (renderLayer == BlockRenderLayer.field_9178) {
return SOLID;
} else if (renderLayer == BlockRenderLayer.CUTOUT_MIPPED) {
return CUTOUT_MIPPED;
} else if (renderLayer == BlockRenderLayer.field_9174) {
return CUTOUT;
} else if (renderLayer == BlockRenderLayer.field_9179) {
return TRANSLUCENT;
} else {
return DEFAULT;
}
}
}

View file

@ -16,10 +16,9 @@
package net.fabricmc.fabric.api.renderer.v1.material;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.fabricmc.fabric.api.renderer.v1.Renderer;
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
import net.minecraft.block.Block;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.block.BlockRenderLayer;
/**
@ -55,16 +54,28 @@ public interface MaterialFinder {
/**
* Defines how sprite pixels will be blended with the scene.
* Accepts {link @BlockRenderLayer} values and blending behavior
* will emulate the way that Minecraft renders each pass. But this does
* will emulate the way that Minecraft renders those instances. This does
* NOT mean the sprite will be rendered in a specific render pass - some
* implementations may not use the standard Minecraft render passes.<p>
* implementations may not use the standard vanilla render passes.<p>
*
* CAN be null and is null by default. A null value means the renderer
* will use {@link Block#getRenderLayer()} for the associate block, or
* {@link BlockRenderLayer#TRANSLUCENT} for item renders. (Normal Minecraft rendering)
* will use the value normally associated with the block being rendered, or
* {@code TRANSLUCENT} for item renders. (Normal Minecraft rendering)
*
* @deprecated Use {@code BlendMode} version instead.
*/
MaterialFinder blendMode(int spriteIndex, BlockRenderLayer blendMode);
@Deprecated
default MaterialFinder blendMode(int spriteIndex, BlockRenderLayer renderLayer) {
return blendMode(spriteIndex, BlendMode.fromRenderLayer(renderLayer));
}
/**
* Defines how sprite pixels will be blended with the scene.<p>
*
* See {@link BlendMode} for more information.
*/
MaterialFinder blendMode(int spriteIndex, BlendMode blendMode);
/**
* Vertex color(s) will be modified for quad color index unless disabled.<p>
*/

View file

@ -21,7 +21,6 @@ import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.util.math.Vector3f;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.MathHelper;
/**
* Specialized {@link MutableQuadView} obtained via {@link MeshBuilder#getEmitter()}

View file

@ -18,7 +18,6 @@ package net.fabricmc.fabric.mixin.renderer.client;
import java.util.Random;
import net.fabricmc.fabric.impl.renderer.DamageModel;
import org.apache.commons.lang3.tuple.MutablePair;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@ -28,8 +27,9 @@ import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
import net.fabricmc.fabric.impl.renderer.DamageModel;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.block.BlockModelRenderer;
import net.minecraft.client.render.block.BlockRenderManager;
import net.minecraft.client.render.model.BakedModel;
@ -63,11 +63,11 @@ public abstract class MixinBlockRenderManager {
*/
@Inject(method = "tesselateDamage", cancellable = true,
at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/client/render/block/BlockModels;getModel(Lnet/minecraft/block/BlockState;)Lnet/minecraft/client/render/model/BakedModel;"))
private void hookTesselateDamage(BlockState blockState, BlockPos blockPos, Sprite sprite, BlockRenderView blockView, CallbackInfo ci) {
private void hookTesselateDamage(BufferBuilder bufferBuilder, BlockState blockState, BlockPos blockPos, Sprite sprite, BlockRenderView blockView, CallbackInfo ci) {
MutablePair<DamageModel, BakedModel> damageState = DAMAGE_STATE.get();
if(damageState.right != null && !((FabricBakedModel)damageState.right).isVanillaAdapter()) {
damageState.left.prepare(damageState.right, sprite, blockState, blockPos);
this.renderer.tesselate(blockView, damageState.left, blockState, blockPos, Tessellator.getInstance().getBufferBuilder(), true, this.random, blockState.getRenderingSeed(blockPos));
this.renderer.tesselate(blockView, damageState.left, blockState, blockPos, bufferBuilder, true, this.random, blockState.getRenderingSeed(blockPos));
ci.cancel();
}
}

View file

@ -16,7 +16,8 @@
"FabricMC"
],
"depends": {
"fabricloader": ">=0.4.0",
"fabricloader": ">=0.6.2",
"minecraft": ">=1.15-alpha.19.38.b",
"fabric-api-base": "*"
},
"description": "Defines rendering extensions for dynamic/fancy block and item models.",

View file

@ -1,5 +1,5 @@
archivesBaseName = "fabric-renderer-indigo"
version = getSubprojectVersion(project, "0.1.13")
version = getSubprojectVersion(project, "0.2.0")
dependencies {
compile project(path: ':fabric-api-base', configuration: 'dev')

View file

@ -18,9 +18,9 @@ package net.fabricmc.indigo.renderer;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
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.RenderMaterial;
import net.minecraft.block.BlockRenderLayer;
/**
* Default implementation of the standard render materials.
@ -29,9 +29,7 @@ import net.minecraft.block.BlockRenderLayer;
* easy/fast interning via int/object hashmap.
*/
public abstract class RenderMaterialImpl {
/** zero position (default value) will be NULL */
private static final BlockRenderLayer[] BLEND_MODES = new BlockRenderLayer[5];
private static final BlendMode[] BLEND_MODES = BlendMode.values();
/**
* Indigo currently support up to 3 sprite layers but is configured to recognize only one.
@ -49,8 +47,6 @@ public abstract class RenderMaterialImpl {
private static final int[] AO_FLAGS = new int[3];
static {
System.arraycopy(BlockRenderLayer.values(), 0, BLEND_MODES, 1, 4);
int shift = Integer.bitCount(TEXTURE_DEPTH_MASK);
for(int i = 0; i < 3; i++) {
BLEND_MODE_SHIFT[i] = shift;
@ -71,7 +67,7 @@ public abstract class RenderMaterialImpl {
protected int bits;
public BlockRenderLayer blendMode(int textureIndex) {
public BlendMode blendMode(int textureIndex) {
return BLEND_MODES[(bits >> BLEND_MODE_SHIFT[textureIndex]) & BLEND_MODE_MASK];
}
@ -137,11 +133,11 @@ public abstract class RenderMaterialImpl {
}
@Override
public MaterialFinder blendMode(int textureIndex, BlockRenderLayer blendMode) {
public MaterialFinder blendMode(int textureIndex, BlendMode blendMode) {
if (blendMode == null) blendMode = BlendMode.DEFAULT;
final int shift = BLEND_MODE_SHIFT[textureIndex];
// zero position is null (default) value
final int ordinal = blendMode == null ? 0 : blendMode.ordinal() + 1;
bits = (bits & ~(BLEND_MODE_MASK << shift)) | (ordinal << shift);
bits = (bits & ~(BLEND_MODE_MASK << shift)) | (blendMode.ordinal() << shift);
return this;
}

View file

@ -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.indigo.renderer.accessor;
import net.minecraft.block.BlockRenderLayer;
public interface AccessChunkRendererData {
/**
* Mark internal tracking set that buffer has been initialized.
*
* @param renderLayer Layer to be initialized.
* @return {@code true} if layer was not already initialized.
*/
boolean fabric_markInitialized(BlockRenderLayer renderLayer);
/**
* Mark internal tracking set that buffer has content.
*
* @param renderLayer Layer with content.
*/
void fabric_markPopulated(BlockRenderLayer renderLayer);
}

View file

@ -36,17 +36,14 @@ public abstract class EncodingFormat {
// our internal format always include packed normals
public static final int VERTEX_START_OFFSET = HEADER_STRIDE;
static final int VANILLA_STRIDE = 28;
public static final int NORMALS_OFFSET = VERTEX_START_OFFSET + VANILLA_STRIDE;
static final int NORMALS_STRIDE = 4;
public static final int NORMALS_OFFSET_VANILLA = VANILLA_STRIDE;
static final int VANILLA_STRIDE = 32;
// normals are followed by 0-2 sets of color/uv coordinates
static final int TEXTURE_STRIDE = 12;
/** is one tex stride less than the actual base, because when used tex index is &gt;= 1 */
static final int TEXTURE_OFFSET_MINUS = NORMALS_OFFSET + NORMALS_STRIDE - TEXTURE_STRIDE;
static final int SECOND_TEXTURE_OFFSET = NORMALS_OFFSET + NORMALS_STRIDE;
static final int TEXTURE_OFFSET_MINUS = HEADER_STRIDE + VANILLA_STRIDE - TEXTURE_STRIDE;
static final int SECOND_TEXTURE_OFFSET = TEXTURE_OFFSET_MINUS + TEXTURE_STRIDE;
static final int THIRD_TEXTURE_OFFSET = SECOND_TEXTURE_OFFSET + TEXTURE_STRIDE;
public static final int MAX_STRIDE = HEADER_STRIDE + VANILLA_STRIDE + NORMALS_STRIDE
public static final int MAX_STRIDE = HEADER_STRIDE + VANILLA_STRIDE
+ TEXTURE_STRIDE * (RenderMaterialImpl.MAX_SPRITE_DEPTH - 1);
/** used for quick clearing of quad buffers */

View file

@ -17,14 +17,12 @@
package net.fabricmc.indigo.renderer.mesh;
import static net.fabricmc.indigo.renderer.mesh.EncodingFormat.EMPTY;
import static net.fabricmc.indigo.renderer.mesh.EncodingFormat.NORMALS_OFFSET;
import static net.fabricmc.indigo.renderer.mesh.EncodingFormat.VANILLA_STRIDE;
import static net.fabricmc.indigo.renderer.mesh.EncodingFormat.VERTEX_START_OFFSET;
import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial;
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
import net.fabricmc.indigo.renderer.RenderMaterialImpl.Value;
import net.fabricmc.indigo.renderer.IndigoRenderer;
import net.fabricmc.indigo.renderer.RenderMaterialImpl.Value;
import net.fabricmc.indigo.renderer.helper.ColorHelper.ShadeableQuad;
import net.fabricmc.indigo.renderer.helper.GeometryHelper;
import net.fabricmc.indigo.renderer.helper.NormalHelper;
@ -98,19 +96,7 @@ public abstract class MutableQuadViewImpl extends QuadViewImpl implements QuadEm
@Override
public final MutableQuadViewImpl fromVanilla(int[] quadData, int startIndex, boolean isItem) {
final int vertexStart = vertexStart();
if(isItem) {
System.arraycopy(quadData, startIndex, data, vertexStart, 6);
System.arraycopy(quadData, startIndex + 7, data, vertexStart + 7, 6);
System.arraycopy(quadData, startIndex + 14, data, vertexStart + 14, 6);
System.arraycopy(quadData, startIndex + 21, data, vertexStart + 21, 6);
final int normalsIndex = baseIndex + NORMALS_OFFSET;
data[normalsIndex] = quadData[startIndex + 6];
data[normalsIndex + 1] = quadData[startIndex + 13];
data[normalsIndex + 2] = quadData[startIndex + 20];
data[normalsIndex + 3] = quadData[startIndex + 27];
} else {
System.arraycopy(quadData, startIndex, data, vertexStart, 28);
}
System.arraycopy(quadData, startIndex, data, vertexStart, 32);
this.invalidateShape();
return this;
}
@ -127,7 +113,7 @@ public abstract class MutableQuadViewImpl extends QuadViewImpl implements QuadEm
@Override
public MutableQuadViewImpl pos(int vertexIndex, float x, float y, float z) {
final int index = vertexStart() + vertexIndex * 7;
final int index = vertexStart() + vertexIndex * 8;
data[index] = Float.floatToRawIntBits(x);
data[index + 1] = Float.floatToRawIntBits(y);
data[index + 2] = Float.floatToRawIntBits(z);
@ -138,13 +124,27 @@ public abstract class MutableQuadViewImpl extends QuadViewImpl implements QuadEm
@Override
public MutableQuadViewImpl normal(int vertexIndex, float x, float y, float z) {
normalFlags |= (1 << vertexIndex);
data[baseIndex + VERTEX_START_OFFSET + VANILLA_STRIDE + vertexIndex] = NormalHelper.packNormal(x, y, z, 0);
data[baseIndex + vertexIndex * 8 + 7 + VERTEX_START_OFFSET] = NormalHelper.packNormal(x, y, z, 0);
return this;
}
/**
* Internal helper method. Copies face normals to vertex normals lacking one.
*/
public final void populateMissingNormals() {
final int normalFlags = this.normalFlags;
if (normalFlags == 0b1111) return;
final int packedFaceNormal = NormalHelper.packNormal(faceNormal(), 0);
for (int v = 0; v < 4; v++) {
if ((normalFlags & (1 << v)) == 0) {
data[baseIndex + v * 8 + 7 + VERTEX_START_OFFSET] = packedFaceNormal;
}
}
}
@Override
public MutableQuadViewImpl lightmap(int vertexIndex, int lightmap) {
data[baseIndex + vertexIndex * 7 + 6 + VERTEX_START_OFFSET] = lightmap;
data[baseIndex + vertexIndex * 8 + 6 + VERTEX_START_OFFSET] = lightmap;
return this;
}

View file

@ -20,12 +20,10 @@ import static net.fabricmc.indigo.renderer.mesh.EncodingFormat.HEADER_BITS;
import static net.fabricmc.indigo.renderer.mesh.EncodingFormat.HEADER_COLOR_INDEX;
import static net.fabricmc.indigo.renderer.mesh.EncodingFormat.HEADER_MATERIAL;
import static net.fabricmc.indigo.renderer.mesh.EncodingFormat.HEADER_TAG;
import static net.fabricmc.indigo.renderer.mesh.EncodingFormat.NORMALS_OFFSET;
import static net.fabricmc.indigo.renderer.mesh.EncodingFormat.SECOND_TEXTURE_OFFSET;
import static net.fabricmc.indigo.renderer.mesh.EncodingFormat.TEXTURE_OFFSET_MINUS;
import static net.fabricmc.indigo.renderer.mesh.EncodingFormat.TEXTURE_STRIDE;
import static net.fabricmc.indigo.renderer.mesh.EncodingFormat.THIRD_TEXTURE_OFFSET;
import static net.fabricmc.indigo.renderer.mesh.EncodingFormat.VANILLA_STRIDE;
import static net.fabricmc.indigo.renderer.mesh.EncodingFormat.VERTEX_START_OFFSET;
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
@ -154,15 +152,7 @@ public class QuadViewImpl implements QuadView {
@Override
public final void toVanilla(int textureIndex, int[] target, int targetIndex, boolean isItem) {
System.arraycopy(data, vertexStart(), target, targetIndex, 28);
if(textureIndex > 0) {
copyColorUV(textureIndex, target, targetIndex);
}
if(isItem) {
copyNormals(target, targetIndex);
}
System.arraycopy(data, vertexStart(), target, targetIndex, 32);
}
/**
@ -174,31 +164,18 @@ public class QuadViewImpl implements QuadView {
int strideFrom;
if(textureIndex == 0) {
indexFrom = baseIndex + VERTEX_START_OFFSET + 3;
strideFrom = 7;
strideFrom = 8;
} else {
indexFrom = baseIndex + (textureIndex == 1 ? SECOND_TEXTURE_OFFSET : THIRD_TEXTURE_OFFSET);
strideFrom = 3;
}
for(int i = 0; i < 4; i++) {
System.arraycopy(data, indexFrom, target, indexTo, 3);
indexTo += 7;
indexTo += 8;
indexFrom += strideFrom;
}
}
/**
* Internal helper method. Copies packed normals to target, assuming vanilla format.
*/
public final void copyNormals(int[] target, int targetIndex) {
final int normalFlags = this.normalFlags;
final int packedFaceNormal = normalFlags == 0b1111 ? 0 : NormalHelper.packNormal(faceNormal(), 0);
final int normalsIndex = baseIndex + NORMALS_OFFSET;
for(int v = 0; v < 4; v++) {
final int packed = (normalFlags & (1 << v)) == 0 ? packedFaceNormal : data[normalsIndex + v];
target[targetIndex + v * 7 + 6] = packed;
}
}
@Override
public final RenderMaterialImpl.Value material() {
return material;
@ -263,7 +240,7 @@ public class QuadViewImpl implements QuadView {
if(target == null) {
target = new Vector3f();
}
final int index = vertexStart() + vertexIndex * 7;
final int index = vertexStart() + vertexIndex * 8;
target.set(
Float.intBitsToFloat(data[index]),
Float.intBitsToFloat(data[index + 1]),
@ -273,22 +250,22 @@ public class QuadViewImpl implements QuadView {
@Override
public float posByIndex(int vertexIndex, int coordinateIndex) {
return Float.intBitsToFloat(data[vertexStart() + vertexIndex * 7 + coordinateIndex]);
return Float.intBitsToFloat(data[vertexStart() + vertexIndex * 8 + coordinateIndex]);
}
@Override
public float x(int vertexIndex) {
return Float.intBitsToFloat(data[vertexStart() + vertexIndex * 7]);
return Float.intBitsToFloat(data[vertexStart() + vertexIndex * 8]);
}
@Override
public float y(int vertexIndex) {
return Float.intBitsToFloat(data[vertexStart() + vertexIndex * 7 + 1]);
return Float.intBitsToFloat(data[vertexStart() + vertexIndex * 8 + 1]);
}
@Override
public float z(int vertexIndex) {
return Float.intBitsToFloat(data[vertexStart() + vertexIndex * 7 + 2]);
return Float.intBitsToFloat(data[vertexStart() + vertexIndex * 8 + 2]);
}
@Override
@ -302,7 +279,7 @@ public class QuadViewImpl implements QuadView {
if(target == null) {
target = new Vector3f();
}
final int normal = data[vertexStart() + VANILLA_STRIDE + vertexIndex];
final int normal = data[vertexStart() + vertexIndex * 8 + 7];
target.set(
NormalHelper.getPackedNormalComponent(normal, 0),
NormalHelper.getPackedNormalComponent(normal, 1),
@ -316,31 +293,31 @@ public class QuadViewImpl implements QuadView {
@Override
public float normalX(int vertexIndex) {
return hasNormal(vertexIndex)
? NormalHelper.getPackedNormalComponent(data[baseIndex + VERTEX_START_OFFSET + VANILLA_STRIDE + vertexIndex], 0)
? NormalHelper.getPackedNormalComponent(data[vertexStart() + vertexIndex * 8 + 7], 0)
: Float.NaN;
}
@Override
public float normalY(int vertexIndex) {
return hasNormal(vertexIndex)
? NormalHelper.getPackedNormalComponent(data[baseIndex + VERTEX_START_OFFSET + VANILLA_STRIDE + vertexIndex], 1)
? NormalHelper.getPackedNormalComponent(data[vertexStart() + vertexIndex * 8 + 7], 1)
: Float.NaN;
}
@Override
public float normalZ(int vertexIndex) {
return hasNormal(vertexIndex)
? NormalHelper.getPackedNormalComponent(data[baseIndex + VERTEX_START_OFFSET + VANILLA_STRIDE + vertexIndex], 2)
? NormalHelper.getPackedNormalComponent(data[vertexStart() + vertexIndex * 8 + 7], 2)
: Float.NaN;
}
@Override
public int lightmap(int vertexIndex) {
return data[baseIndex + vertexIndex * 7 + 6 + VERTEX_START_OFFSET];
return data[baseIndex + vertexIndex * 8 + 6 + VERTEX_START_OFFSET];
}
protected int colorIndex(int vertexIndex, int textureIndex) {
return textureIndex == 0 ? vertexIndex * 7 + 3 + VERTEX_START_OFFSET : TEXTURE_OFFSET_MINUS + textureIndex * TEXTURE_STRIDE + vertexIndex * 3;
return textureIndex == 0 ? vertexIndex * 8 + 3 + VERTEX_START_OFFSET : TEXTURE_OFFSET_MINUS + textureIndex * TEXTURE_STRIDE + vertexIndex * 3;
}
@Override

View file

@ -36,13 +36,13 @@ public abstract class MixinBufferBuilder implements AccessBufferBuilder {
@Shadow abstract int getCurrentSize();
@Shadow public abstract VertexFormat getVertexFormat();
private static final int VERTEX_STRIDE_INTS = 7;
private static final int VERTEX_STRIDE_INTS = 8;
private static final int QUAD_STRIDE_INTS = VERTEX_STRIDE_INTS * 4;
private static final int QUAD_STRIDE_BYTES = QUAD_STRIDE_INTS * 4;
@Override
public void fabric_putQuad(QuadViewImpl quad) {
if(Indigo.ENSURE_VERTEX_FORMAT_COMPATIBILITY) {
if (Indigo.ENSURE_VERTEX_FORMAT_COMPATIBILITY) {
bufferCompatibly(quad);
} else {
bufferFast(quad);
@ -50,7 +50,8 @@ public abstract class MixinBufferBuilder implements AccessBufferBuilder {
}
private void bufferFast(QuadViewImpl quad) {
grow(QUAD_STRIDE_BYTES);
grow(QUAD_STRIDE_BYTES + getVertexFormat().getVertexSize());
bufInt.limit(bufInt.capacity());
bufInt.position(getCurrentSize());
bufInt.put(quad.data(), quad.vertexStart(), QUAD_STRIDE_INTS);
vertexCount += 4;
@ -93,9 +94,8 @@ public abstract class MixinBufferBuilder implements AccessBufferBuilder {
break;
// these types should never occur and/or require no action
case MATRIX:
case BLEND_WEIGHT:
case PADDING:
case GENERIC:
default:
break;

View file

@ -0,0 +1,119 @@
/*
* 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.indigo.renderer.mixin;
import java.util.Random;
import java.util.Set;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
import net.fabricmc.indigo.Indigo;
import net.fabricmc.indigo.renderer.accessor.AccessChunkRendererRegion;
import net.fabricmc.indigo.renderer.render.TerrainRenderContext;
import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.block.BlockRenderManager;
import net.minecraft.client.render.chunk.BlockLayeredBufferBuilder;
import net.minecraft.client.render.chunk.ChunkBatcher;
import net.minecraft.client.render.chunk.ChunkBatcher.ChunkRenderer;
import net.minecraft.client.render.chunk.ChunkRendererRegion;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.BlockRenderView;
/**
* Implements the main hooks for terrain rendering. Attempts to tread
* lightly. This means we are deliberately stepping over some minor
* optimization opportunities.<p>
*
* Non-Fabric renderer implementations that are looking to maximize
* performance will likely take a much more aggressive approach.
* For that reason, mod authors who want compatibility with advanced
* renderers will do well to steer clear of chunk rebuild hooks unless
* they are creating a renderer.<p>
*
* These hooks are intended only for the Fabric default renderer and
* aren't expected to be present when a different renderer is being used.
* Renderer authors are responsible for creating the hooks they need.
* (Though they can use these as an example if they wish.)
*/
@Mixin(targets = "net.minecraft.client.render.chunk.ChunkBatcher$ChunkRenderer$class_4578")
public class MixinChunkRebuildTask {
@Shadow protected ChunkRendererRegion field_20838;
@Shadow protected ChunkRenderer field_20839;
@Inject(at = @At("HEAD"), method = "method_22785")
private void hookChunkBuild(
float float_1,
float float_2,
float float_3,
ChunkBatcher.ChunkRenderData renderData,
BlockLayeredBufferBuilder builder,
CallbackInfoReturnable<Set<BlockEntity>> ci) {
if (field_20838 != null) {
TerrainRenderContext renderer = TerrainRenderContext.POOL.get();
renderer.prepare(field_20838, field_20839, renderData, builder);
((AccessChunkRendererRegion)field_20838).fabric_setRenderer(renderer);
}
}
/**
* This is the hook that actually implements the rendering API for terrain rendering.<p>
*
* It's unusual to have a @Redirect in a Fabric library, but in this case
* it is our explicit intention that {@link BlockRenderManager#tesselateBlock(BlockState, BlockPos, BlockRenderView, BufferBuilder, Random)}
* does not execute for models that will be rendered by our renderer.<p>
*
* Any mod that wants to redirect this specific call is likely also a renderer, in which case this
* renderer should not be present, or the mod should probably instead be relying on the renderer API
* which was specifically created to provide for enhanced terrain rendering.<p>
*
* Note also that {@link BlockRenderManager#tesselateBlock(BlockState, BlockPos, BlockRenderView, BufferBuilder, Random)}
* IS called if the block render type is something other than {@link BlockRenderType#MODEL}.
* Normally this does nothing but will allow mods to create rendering hooks that are
* driven off of render type. (Not recommended or encouraged, but also not prevented.)
*/
@Redirect(method = "method_22785", require = 1,
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/block/BlockRenderManager;tesselateBlock(Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/world/BlockRenderView;Lnet/minecraft/client/render/BufferBuilder;Ljava/util/Random;)Z"))
private boolean hookChunkBuildTesselate(BlockRenderManager renderManager, BlockState blockState, BlockPos blockPos, BlockRenderView blockView, BufferBuilder bufferBuilder, Random random) {
if (blockState.getRenderType() == BlockRenderType.MODEL) {
final BakedModel model = renderManager.getModel(blockState);
if (Indigo.ALWAYS_TESSELATE_INDIGO || !((FabricBakedModel) model).isVanillaAdapter()) {
return ((AccessChunkRendererRegion) blockView).fabric_getRenderer().tesselateBlock(blockState, blockPos, model);
}
}
return renderManager.tesselateBlock(blockState, blockPos, blockView, bufferBuilder, random);
}
/**
* Release all references. Probably not necessary but would be $#%! to debug if it is.
*/
@Inject(at = @At("RETURN"), method = "method_22785")
private void hookRebuildChunkReturn(CallbackInfoReturnable<Set<BlockEntity>> ci) {
TerrainRenderContext.POOL.get().release();
}
}

View file

@ -0,0 +1,44 @@
/*
* 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.indigo.renderer.mixin;
import java.util.Set;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import net.fabricmc.indigo.renderer.accessor.AccessChunkRendererData;
import net.minecraft.block.BlockRenderLayer;
import net.minecraft.client.render.chunk.ChunkBatcher.ChunkRenderData;
@Mixin(ChunkRenderData.class)
public class MixinChunkRenderData implements AccessChunkRendererData {
@Shadow private Set<BlockRenderLayer> initialized;
@Shadow private Set<BlockRenderLayer> nonEmpty;
@Shadow private boolean empty;
@Override
public boolean fabric_markInitialized(BlockRenderLayer renderLayer) {
return initialized.add(renderLayer);
}
@Override
public void fabric_markPopulated(BlockRenderLayer renderLayer) {
empty = false;
nonEmpty.add(renderLayer);
}
}

View file

@ -1,50 +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.indigo.renderer.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.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.fabricmc.indigo.renderer.accessor.AccessChunkRendererRegion;
import net.fabricmc.indigo.renderer.render.TerrainRenderContext;
import net.minecraft.client.render.chunk.ChunkRenderTask;
import net.minecraft.client.render.chunk.ChunkRendererRegion;
@Mixin(ChunkRenderTask.class)
public abstract class MixinChunkRenderTask {
@Shadow private ChunkRendererRegion region;
/**
* The block view reference is voided when {@link ChunkRenderTask#getAndInvalidateWorldView()} is called during
* chunk rebuild, but we need it and it is harder to make reliable, non-invasive changes there.
* So we capture the block view before the reference is voided and send it to the renderer. <p>
*
* We also store a reference to the renderer in the view to avoid doing thread-local lookups for each block.
*/
@Inject(at = @At("HEAD"), method = "takeRegion")
private void chunkDataHook(CallbackInfoReturnable<ChunkRendererRegion> info) {
final ChunkRendererRegion blockView = region;
if(blockView != null) {
final TerrainRenderContext renderer = TerrainRenderContext.POOL.get();
renderer.setBlockView(blockView);
((AccessChunkRendererRegion)blockView).fabric_setRenderer(renderer);
}
}
}

View file

@ -16,121 +16,23 @@
package net.fabricmc.indigo.renderer.mixin;
import java.util.Random;
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
import net.fabricmc.indigo.Indigo;
import net.minecraft.client.render.model.BakedModel;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.fabricmc.indigo.renderer.accessor.AccessChunkRenderer;
import net.fabricmc.indigo.renderer.accessor.AccessChunkRendererRegion;
import net.fabricmc.indigo.renderer.render.TerrainRenderContext;
import net.minecraft.block.BlockRenderLayer;
import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.block.BlockRenderManager;
import net.minecraft.client.render.chunk.ChunkRenderData;
import net.minecraft.client.render.chunk.ChunkRenderTask;
import net.minecraft.client.render.chunk.ChunkRenderer;
import net.minecraft.client.render.chunk.ChunkBatcher.ChunkRenderer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.BlockRenderView;
/**
* Implements the main hooks for terrain rendering. Attempts to tread
* lightly. This means we are deliberately stepping over some minor
* optimization opportunities.<p>
*
* Non-Fabric renderer implementations that are looking to maximize
* performance will likely take a much more aggressive approach.
* For that reason, mod authors who want compatibility with advanced
* renderers will do well to steer clear of chunk rebuild hooks unless
* they are creating a renderer.<p>
*
* These hooks are intended only for the Fabric default renderer and
* aren't expected to be present when a different renderer is being used.
* Renderer authors are responsible for creating the hooks they need.
* (Though they can use these as a example if they wish.)
*/
@Mixin(ChunkRenderer.class)
public abstract class MixinChunkRenderer implements AccessChunkRenderer{
@Shadow private BlockPos.Mutable origin;
@Shadow abstract void beginBufferBuilding(BufferBuilder bufferBuilder_1, BlockPos blockPos_1);
@Shadow abstract void endBufferBuilding(BlockRenderLayer blockRenderLayer_1, float float_1, float float_2, float float_3, BufferBuilder bufferBuilder_1, ChunkRenderData chunkRenderData_1);
@Shadow abstract void beginBufferBuilding(BufferBuilder builder, BlockPos pos);
/**
* Access method for renderer.
*/
@Override
public void fabric_beginBufferBuilding(BufferBuilder bufferBuilder_1, BlockPos blockPos_1) {
beginBufferBuilding(bufferBuilder_1, blockPos_1);
}
/**
* Save task to renderer, this is the easiest place to capture it.
*/
@Inject(at = @At("HEAD"), method = "rebuildChunk")
private void hookRebuildChunkHead(float float_1, float float_2, float float_3, ChunkRenderTask chunkRenderTask_1, CallbackInfo info) {
if(chunkRenderTask_1 != null) {
TerrainRenderContext renderer = TerrainRenderContext.POOL.get();
renderer.setChunkTask(chunkRenderTask_1);
}
}
/**
* Capture the block layer result flags when they are first created so our renderer
* can update then when more than one layer is renderer for a single model.
* This is also where we signal the renderer to prepare for a new chunk using
* the data we've accumulated up to this point.
*/
@ModifyVariable(method = "rebuildChunk", at = @At(value = "STORE", ordinal = 0), allow = 1, require = 1)
private boolean[] hookResultFlagsAndPrepare(boolean[] flagsIn) {
TerrainRenderContext.POOL.get().prepare((ChunkRenderer)(Object)this, origin, flagsIn);
return flagsIn;
}
/**
* This is the hook that actually implements the rendering API for terrain rendering.<p>
*
* It's unusual to have a @Redirect in a Fabric library, but in this case
* it is our explicit intention that {@link BlockRenderManager#tesselateBlock(BlockState, BlockPos, BlockRenderView, BufferBuilder, Random)}
* does not execute for models that will be rendered by our renderer.<p>
*
* Any mod that wants to redirect this specific call is likely also a renderer, in which case this
* renderer should not be present, or the mod should probably instead be relying on the renderer API
* which was specifically created to provide for enhanced terrain rendering.<p>
*
* Note also that {@link BlockRenderManager#tesselateBlock(BlockState, BlockPos, BlockRenderView, BufferBuilder, Random)}
* IS called if the block render type is something other than {@link BlockRenderType#MODEL}.
* Normally this does nothing but will allow mods to create rendering hooks that are
* driven off of render type. (Not recommended or encouraged, but also not prevented.)
*/
@Redirect(method = "rebuildChunk", require = 1,
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/block/BlockRenderManager;tesselateBlock(Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/world/BlockRenderView;Lnet/minecraft/client/render/BufferBuilder;Ljava/util/Random;)Z"))
private boolean hookChunkBuildTesselate(BlockRenderManager renderManager, BlockState blockState, BlockPos blockPos, BlockRenderView blockView, BufferBuilder bufferBuilder, Random random) {
if(blockState.getRenderType() == BlockRenderType.MODEL) {
final BakedModel model = renderManager.getModel(blockState);
if (Indigo.ALWAYS_TESSELATE_INDIGO || !((FabricBakedModel) model).isVanillaAdapter()) {
return ((AccessChunkRendererRegion) blockView).fabric_getRenderer().tesselateBlock(blockState, blockPos, model);
}
}
return renderManager.tesselateBlock(blockState, blockPos, blockView, bufferBuilder, random);
}
/**
* Release all references. Probably not necessary but would be $#%! to debug if it is.
*/
@Inject(at = @At("RETURN"), method = "rebuildChunk")
private void hookRebuildChunkReturn(float float_1, float float_2, float float_3, ChunkRenderTask chunkRenderTask_1, CallbackInfo info) {
TerrainRenderContext.POOL.get().release();
public void fabric_beginBufferBuilding(BufferBuilder builder, BlockPos pos) {
beginBufferBuilding(builder, pos);
}
}

View file

@ -17,8 +17,8 @@
package net.fabricmc.indigo.renderer.render;
import java.util.function.Consumer;
import java.util.function.Function;
import it.unimi.dsi.fastutil.ints.Int2ObjectFunction;
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;
@ -32,6 +32,7 @@ import net.fabricmc.indigo.renderer.helper.GeometryHelper;
import net.fabricmc.indigo.renderer.mesh.EncodingFormat;
import net.fabricmc.indigo.renderer.mesh.MeshImpl;
import net.fabricmc.indigo.renderer.mesh.MutableQuadViewImpl;
import net.minecraft.block.BlockRenderLayer;
import net.minecraft.client.MinecraftClient;
/**
@ -39,7 +40,7 @@ import net.minecraft.client.MinecraftClient;
* "editor" quad held in the instance, where all transformations are applied before buffering.
*/
public abstract class AbstractMeshConsumer extends AbstractQuadRenderer implements Consumer<Mesh> {
protected AbstractMeshConsumer(BlockRenderInfo blockInfo, Int2ObjectFunction<AccessBufferBuilder> bufferFunc, AoCalculator aoCalc, QuadTransform transform) {
protected AbstractMeshConsumer(BlockRenderInfo blockInfo, Function<BlockRenderLayer, AccessBufferBuilder> bufferFunc, AoCalculator aoCalc, QuadTransform transform) {
super(blockInfo, bufferFunc, aoCalc, transform);
}
@ -136,7 +137,7 @@ public abstract class AbstractMeshConsumer extends AbstractQuadRenderer implemen
*/
private void tesselateQuad(MutableQuadViewImpl quad, RenderMaterialImpl.Value mat, int textureIndex) {
final int colorIndex = mat.disableColorIndex(textureIndex) ? -1 : quad.colorIndex();
final int renderLayer = blockInfo.layerIndexOrDefault(mat.blendMode(textureIndex));
final BlockRenderLayer renderLayer = blockInfo.effectiveRenderLayer(mat.blendMode(textureIndex));
if(blockInfo.defaultAo && !mat.disableAo(textureIndex)) {
if(mat.emissive(textureIndex)) {

View file

@ -18,7 +18,8 @@ package net.fabricmc.indigo.renderer.render;
import static net.fabricmc.indigo.renderer.helper.GeometryHelper.LIGHT_FACE_FLAG;
import it.unimi.dsi.fastutil.ints.Int2ObjectFunction;
import java.util.function.Function;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext.QuadTransform;
import net.fabricmc.indigo.renderer.accessor.AccessBufferBuilder;
import net.fabricmc.indigo.renderer.aocalc.AoCalculator;
@ -26,6 +27,7 @@ import net.fabricmc.indigo.renderer.helper.ColorHelper;
import net.fabricmc.indigo.renderer.mesh.EncodingFormat;
import net.fabricmc.indigo.renderer.mesh.MutableQuadViewImpl;
import net.minecraft.block.Block;
import net.minecraft.block.BlockRenderLayer;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
@ -36,12 +38,12 @@ import net.minecraft.util.math.BlockPos;
public abstract class AbstractQuadRenderer {
private static final int FULL_BRIGHTNESS = 15 << 20 | 15 << 4;
protected final Int2ObjectFunction<AccessBufferBuilder> bufferFunc;
protected final Function<BlockRenderLayer, AccessBufferBuilder> bufferFunc;
protected final BlockRenderInfo blockInfo;
protected final AoCalculator aoCalc;
protected final QuadTransform transform;
AbstractQuadRenderer(BlockRenderInfo blockInfo, Int2ObjectFunction<AccessBufferBuilder> bufferFunc, AoCalculator aoCalc, QuadTransform transform) {
AbstractQuadRenderer(BlockRenderInfo blockInfo, Function<BlockRenderLayer, AccessBufferBuilder> bufferFunc, AoCalculator aoCalc, QuadTransform transform) {
this.blockInfo = blockInfo;
this.bufferFunc = bufferFunc;
this.aoCalc = aoCalc;
@ -64,14 +66,14 @@ public abstract class AbstractQuadRenderer {
}
/** final output step, common to all renders */
private void bufferQuad(MutableQuadViewImpl quad, int renderLayer) {
bufferFunc.get(renderLayer).fabric_putQuad(quad);
private void bufferQuad(MutableQuadViewImpl quad, BlockRenderLayer renderLayer) {
bufferFunc.apply(renderLayer).fabric_putQuad(quad);
}
// routines below have a bit of copy-paste code reuse to avoid conditional execution inside a hot loop
/** for non-emissive mesh quads and all fallback quads with smooth lighting*/
protected void tesselateSmooth(MutableQuadViewImpl q, int renderLayer, int blockColorIndex) {
protected void tesselateSmooth(MutableQuadViewImpl q, BlockRenderLayer renderLayer, int blockColorIndex) {
colorizeQuad(q, blockColorIndex);
for(int i = 0; i < 4; i++) {
q.spriteColor(i, 0, ColorHelper.multiplyRGB(q.spriteColor(i, 0), aoCalc.ao[i]));
@ -81,7 +83,7 @@ public abstract class AbstractQuadRenderer {
}
/** for emissive mesh quads with smooth lighting*/
protected void tesselateSmoothEmissive(MutableQuadViewImpl q, int renderLayer, int blockColorIndex) {
protected void tesselateSmoothEmissive(MutableQuadViewImpl q, BlockRenderLayer renderLayer, int blockColorIndex) {
colorizeQuad(q, blockColorIndex);
for(int i = 0; i < 4; i++) {
q.spriteColor(i, 0, ColorHelper.multiplyRGB(q.spriteColor(i, 0), aoCalc.ao[i]));
@ -91,7 +93,7 @@ public abstract class AbstractQuadRenderer {
}
/** for non-emissive mesh quads and all fallback quads with flat lighting*/
protected void tesselateFlat(MutableQuadViewImpl quad, int renderLayer, int blockColorIndex) {
protected void tesselateFlat(MutableQuadViewImpl quad, BlockRenderLayer renderLayer, int blockColorIndex) {
colorizeQuad(quad, blockColorIndex);
final int brightness = flatBrightness(quad, blockInfo.blockState, blockInfo.blockPos);
for(int i = 0; i < 4; i++) {
@ -101,7 +103,7 @@ public abstract class AbstractQuadRenderer {
}
/** for emissive mesh quads with flat lighting*/
protected void tesselateFlatEmissive(MutableQuadViewImpl quad, int renderLayer, int blockColorIndex, int[] lightmaps) {
protected void tesselateFlatEmissive(MutableQuadViewImpl quad, BlockRenderLayer renderLayer, int blockColorIndex, int[] lightmaps) {
colorizeQuad(quad, blockColorIndex);
for(int i = 0; i < 4; i++) {
quad.lightmap(i, FULL_BRIGHTNESS);
@ -115,18 +117,18 @@ public abstract class AbstractQuadRenderer {
final int[] data = q.data();
final int[] lightmaps = this.lightmaps;
lightmaps[0] = data[EncodingFormat.VERTEX_START_OFFSET + 6];
lightmaps[1] = data[EncodingFormat.VERTEX_START_OFFSET + 6 + 7];
lightmaps[2] = data[EncodingFormat.VERTEX_START_OFFSET + 6 + 14];
lightmaps[3] = data[EncodingFormat.VERTEX_START_OFFSET + 6 + 21];
lightmaps[1] = data[EncodingFormat.VERTEX_START_OFFSET + 6 + 8];
lightmaps[2] = data[EncodingFormat.VERTEX_START_OFFSET + 6 + 16];
lightmaps[3] = data[EncodingFormat.VERTEX_START_OFFSET + 6 + 24];
}
protected void restoreLightmaps(MutableQuadViewImpl q) {
final int[] data = q.data();
final int[] lightmaps = this.lightmaps;
data[EncodingFormat.VERTEX_START_OFFSET + 6] = lightmaps[0];
data[EncodingFormat.VERTEX_START_OFFSET + 6 + 7] = lightmaps[1];
data[EncodingFormat.VERTEX_START_OFFSET + 6 + 14] = lightmaps[2];
data[EncodingFormat.VERTEX_START_OFFSET + 6 + 21] = lightmaps[3];
data[EncodingFormat.VERTEX_START_OFFSET + 6 + 8] = lightmaps[1];
data[EncodingFormat.VERTEX_START_OFFSET + 6 + 16] = lightmaps[2];
data[EncodingFormat.VERTEX_START_OFFSET + 6 + 24] = lightmaps[3];
}
private final BlockPos.Mutable mpos = new BlockPos.Mutable();

View file

@ -18,8 +18,8 @@ package net.fabricmc.indigo.renderer.render;
import java.util.Random;
import java.util.function.Consumer;
import java.util.function.Function;
import it.unimi.dsi.fastutil.ints.Int2ObjectFunction;
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.model.FabricBakedModel;
@ -29,6 +29,7 @@ import net.fabricmc.indigo.renderer.aocalc.AoCalculator;
import net.fabricmc.indigo.renderer.aocalc.AoLuminanceFix;
import net.fabricmc.indigo.renderer.mesh.MutableQuadViewImpl;
import net.fabricmc.indigo.renderer.mixin.BufferBuilderOffsetAccessor;
import net.minecraft.block.BlockRenderLayer;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.block.BlockModelRenderer;
@ -70,7 +71,7 @@ public class BlockRenderContext extends AbstractRenderContext implements RenderC
return blockView == null ? 1f : AoLuminanceFix.INSTANCE.apply(blockView, pos);
}
private AccessBufferBuilder outputBuffer(int renderLayer) {
private AccessBufferBuilder outputBuffer(BlockRenderLayer renderLayer) {
didOutput = true;
return fabricBuffer;
}
@ -108,7 +109,7 @@ public class BlockRenderContext extends AbstractRenderContext implements RenderC
}
private class MeshConsumer extends AbstractMeshConsumer {
MeshConsumer(BlockRenderInfo blockInfo, Int2ObjectFunction<AccessBufferBuilder> bufferFunc, AoCalculator aoCalc, QuadTransform transform) {
MeshConsumer(BlockRenderInfo blockInfo, Function<BlockRenderLayer, AccessBufferBuilder> bufferFunc, AoCalculator aoCalc, QuadTransform transform) {
super(blockInfo, bufferFunc, aoCalc, transform);
}

View file

@ -19,6 +19,7 @@ package net.fabricmc.indigo.renderer.render;
import java.util.Random;
import java.util.function.Supplier;
import net.fabricmc.fabric.api.renderer.v1.material.BlendMode;
import net.minecraft.block.BlockRenderLayer;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
@ -42,7 +43,7 @@ public class BlockRenderInfo {
public BlockState blockState;
public long seed;
boolean defaultAo;
int defaultLayerIndex;
BlockRenderLayer defaultLayer;
public final Supplier<Random> randomSupplier = () -> {
final Random result = random;
@ -65,7 +66,8 @@ public class BlockRenderInfo {
// in the unlikely case seed actually matches this, we'll simply retrieve it more than one
seed = -1L;
defaultAo = modelAO && MinecraftClient.isAmbientOcclusionEnabled() && blockState.getLuminance() == 0;
defaultLayerIndex = blockState.getBlock().getRenderLayer().ordinal();
defaultLayer = BlockRenderLayer.method_22715(blockState);
}
public void release() {
@ -81,7 +83,7 @@ public class BlockRenderInfo {
return true;
}
int layerIndexOrDefault(BlockRenderLayer layer) {
return layer == null ? this.defaultLayerIndex : layer.ordinal();
BlockRenderLayer effectiveRenderLayer(BlendMode blendMode) {
return blendMode == BlendMode.DEFAULT ? this.defaultLayer : blendMode.blockRenderLayer;
}
}

View file

@ -18,18 +18,20 @@ package net.fabricmc.indigo.renderer.render;
import it.unimi.dsi.fastutil.longs.Long2FloatOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.fabricmc.indigo.Indigo;
import net.fabricmc.indigo.renderer.accessor.AccessBufferBuilder;
import net.fabricmc.indigo.renderer.accessor.AccessChunkRenderer;
import net.fabricmc.indigo.renderer.accessor.AccessChunkRendererData;
import net.fabricmc.indigo.renderer.aocalc.AoLuminanceFix;
import net.fabricmc.indigo.renderer.mesh.MutableQuadViewImpl;
import net.minecraft.block.Block.OffsetType;
import net.minecraft.block.BlockRenderLayer;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.chunk.ChunkRenderData;
import net.minecraft.client.render.chunk.ChunkRenderTask;
import net.minecraft.client.render.chunk.ChunkRenderer;
import net.minecraft.client.render.chunk.BlockLayeredBufferBuilder;
import net.minecraft.client.render.chunk.ChunkBatcher.ChunkRenderData;
import net.minecraft.client.render.chunk.ChunkBatcher.ChunkRenderer;
import net.minecraft.client.render.chunk.ChunkRendererRegion;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
@ -70,14 +72,12 @@ public class ChunkRenderInfo {
private final BlockRenderInfo blockInfo;
private final BlockPos.Mutable chunkOrigin = new BlockPos.Mutable();
ChunkRenderTask chunkTask;
ChunkRenderData chunkData;
AccessChunkRendererData chunkData;
ChunkRenderer chunkRenderer;
BlockLayeredBufferBuilder builders;
BlockRenderView blockView;
boolean [] resultFlags;
private final AccessBufferBuilder[] buffers = new AccessBufferBuilder[4];
private final BlockRenderLayer[] LAYERS = BlockRenderLayer.values();
private final Object2ObjectOpenHashMap<BlockRenderLayer, AccessBufferBuilder> buffers = new Object2ObjectOpenHashMap<>();
private double chunkOffsetX;
private double chunkOffsetY;
@ -96,23 +96,17 @@ public class ChunkRenderInfo {
aoLevelCache.defaultReturnValue(Float.MAX_VALUE);
}
void setBlockView(ChunkRendererRegion blockView) {
this.blockView = blockView;
}
void setChunkTask(ChunkRenderTask chunkTask) {
this.chunkTask = chunkTask;
}
void prepare(ChunkRenderer chunkRenderer, BlockPos.Mutable chunkOrigin, boolean [] resultFlags) {
this.chunkOrigin.set(chunkOrigin);
this.chunkData = chunkTask.getRenderData();
void prepare(
ChunkRendererRegion blockView,
ChunkRenderer chunkRenderer,
ChunkRenderData chunkData,
BlockLayeredBufferBuilder builders) {
this.blockView = blockView;
this.chunkOrigin.set(chunkRenderer.getOrigin());
this.chunkData = (AccessChunkRendererData) chunkData;
this.chunkRenderer = chunkRenderer;
this.resultFlags = resultFlags;
buffers[0] = null;
buffers[1] = null;
buffers[2] = null;
buffers[3] = null;
this.builders = builders;
buffers.clear();
chunkOffsetX = -chunkOrigin.getX();
chunkOffsetY = -chunkOrigin.getY();
chunkOffsetZ = -chunkOrigin.getZ();
@ -122,12 +116,8 @@ public class ChunkRenderInfo {
void release() {
chunkData = null;
chunkTask = null;
chunkRenderer = null;
buffers[0] = null;
buffers[1] = null;
buffers[2] = null;
buffers[3] = null;
buffers.clear();
}
void beginBlock() {
@ -154,21 +144,18 @@ public class ChunkRenderInfo {
}
}
/** Lazily retrieves output buffer for given layer, initializing as needed. */
public AccessBufferBuilder getInitializedBuffer(int layerIndex) {
// redundant for first layer, but probably not faster to check
resultFlags[layerIndex] = true;
AccessBufferBuilder result = buffers[layerIndex];
public AccessBufferBuilder getInitializedBuffer(BlockRenderLayer renderLayer) {
AccessBufferBuilder result = buffers.get(renderLayer);
if (result == null) {
BufferBuilder builder = chunkTask.getBufferBuilders().get(layerIndex);
buffers[layerIndex] = (AccessBufferBuilder) builder;
BlockRenderLayer layer = LAYERS[layerIndex];
if (!chunkData.isBufferInitialized(layer)) {
chunkData.markBufferInitialized(layer); // start buffer
BufferBuilder builder = builders.get(renderLayer);
result = (AccessBufferBuilder) builder;
chunkData.fabric_markPopulated(renderLayer);
buffers.put(renderLayer, result);
if (chunkData.fabric_markInitialized(renderLayer)) {
((AccessChunkRenderer) chunkRenderer).fabric_beginBufferBuilding(builder, chunkOrigin);
}
result = (AccessBufferBuilder) builder;
}
return result;
}

View file

@ -92,7 +92,7 @@ public class ItemRenderContext extends AbstractRenderContext implements RenderCo
public void renderModel(FabricBakedModel model, int color, ItemStack stack, VanillaQuadHandler vanillaHandler) {
this.color = color;
if(stack.isEmpty() && enchantmentStack != null) {
if (stack.isEmpty() && enchantmentStack != null) {
enchantment = true;
this.itemStack = enchantmentStack;
enchantmentStack = null;
@ -110,7 +110,7 @@ public class ItemRenderContext extends AbstractRenderContext implements RenderCo
model.emitItemQuads(stack, randomSupplier, this);
tessellator.draw();
if(smoothShading) {
if (smoothShading) {
RenderSystem.shadeModel(GL11.GL_FLAT);
smoothShading = false;
}
@ -145,7 +145,7 @@ public class ItemRenderContext extends AbstractRenderContext implements RenderCo
final int[] data = m.data();
final int limit = data.length;
int index = 0;
while(index < limit) {
while (index < limit) {
RenderMaterialImpl.Value mat = RenderMaterialImpl.byIndex(data[index]);
final int stride = EncodingFormat.stride(mat.spriteDepth());
System.arraycopy(data, index, editorQuad.data(), 0, stride);
@ -164,7 +164,7 @@ public class ItemRenderContext extends AbstractRenderContext implements RenderCo
* for every item, every frame.
*/
private void handleShading() {
if(!smoothShading && editorQuad.hasVertexNormals()) {
if (!smoothShading && editorQuad.hasVertexNormals()) {
smoothShading = true;
RenderSystem.shadeModel(GL11.GL_SMOOTH);
}
@ -182,7 +182,7 @@ public class ItemRenderContext extends AbstractRenderContext implements RenderCo
private void colorizeAndOutput(int quadColor) {
final MutableQuadViewImpl q = editorQuad;
for(int i = 0; i < 4; i++) {
for (int i = 0; i < 4; i++) {
int c = q.spriteColor(i, 0);
c = ColorHelper.multiplyColor(quadColor, c);
q.spriteColor(i, 0, ColorHelper.swapRedBlueIfNeeded(c));
@ -192,7 +192,7 @@ public class ItemRenderContext extends AbstractRenderContext implements RenderCo
private void renderQuad() {
final MutableQuadViewImpl quad = editorQuad;
if(!transform(editorQuad)) {
if (!transform(editorQuad)) {
return;
}
@ -202,19 +202,17 @@ public class ItemRenderContext extends AbstractRenderContext implements RenderCo
handleShading();
// A bit of a hack - copy packed normals on top of lightmaps.
// Violates normal encoding format but the editor content will be discarded
// and this avoids the step of copying to a separate array.
quad.copyNormals(quadData, EncodingFormat.VERTEX_START_OFFSET);
quad.populateMissingNormals();
quad.lightmap(0xF000F0, 0xF000F0, 0xF000F0, 0xF000F0);
colorizeAndOutput(!enchantment && mat.disableColorIndex(0) ? -1 : quadColor);
// no need to render additional textures for enchantment overlay
if(!enchantment && textureCount > 1) {
if (!enchantment && textureCount > 1) {
quad.copyColorUV(1, quadData, EncodingFormat.VERTEX_START_OFFSET);
colorizeAndOutput(mat.disableColorIndex(1) ? -1 : quadColor);
if(textureCount == 3) {
if (textureCount == 3) {
quad.copyColorUV(2, quadData, EncodingFormat.VERTEX_START_OFFSET);
colorizeAndOutput(mat.disableColorIndex(2) ? -1 : quadColor);
}
@ -227,15 +225,15 @@ public class ItemRenderContext extends AbstractRenderContext implements RenderCo
}
private void fallbackConsumer(BakedModel model) {
if(hasTransform()) {
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 < 7; i++) {
for (int i = 0; i < 7; i++) {
random.setSeed(42L);
final Direction cullFace = ModelHelper.faceFromIndex(i);
renderFallbackWithTransform(bufferBuilder, model.getQuads((BlockState)null, cullFace, random), color, itemStack, cullFace);
}
} else {
for(int i = 0; i < 7; i++) {
for (int i = 0; i < 7; i++) {
random.setSeed(42L);
vanillaHandler.accept(bufferBuilder, model.getQuads((BlockState)null, ModelHelper.faceFromIndex(i), random), color, itemStack);
}
@ -243,12 +241,12 @@ public class ItemRenderContext extends AbstractRenderContext implements RenderCo
};
private void renderFallbackWithTransform(BufferBuilder bufferBuilder, List<BakedQuad> quads, int color, ItemStack stack, Direction cullFace) {
if(quads.isEmpty()) {
if (quads.isEmpty()) {
return;
}
if(CompatibilityHelper.canRender(quads.get(0).getVertexData())) {
if (CompatibilityHelper.canRender(quads.get(0).getVertexData())) {
Maker editorQuad = this.editorQuad;
for(BakedQuad q : quads) {
for (BakedQuad q : quads) {
editorQuad.clear();
editorQuad.fromVanilla(q.getVertexData(), 0, false);
editorQuad.cullFace(cullFace);

View file

@ -58,7 +58,7 @@ public class TerrainFallbackConsumer extends AbstractQuadRenderer implements Con
private static Value MATERIAL_FLAT = (Value) IndigoRenderer.INSTANCE.materialFinder().disableAo(0, true).find();
private static Value MATERIAL_SHADED = (Value) IndigoRenderer.INSTANCE.materialFinder().find();
private final int[] editorBuffer = new int[28];
private final int[] editorBuffer = new int[32];
private final ChunkRenderInfo chunkInfo;
TerrainFallbackConsumer(BlockRenderInfo blockInfo, ChunkRenderInfo chunkInfo, AoCalculator aoCalc, QuadTransform transform) {
@ -90,7 +90,7 @@ public class TerrainFallbackConsumer extends AbstractQuadRenderer implements Con
Direction face = ModelHelper.faceFromIndex(i);
List<BakedQuad> quads = model.getQuads(blockState, face, random.get());
final int count = quads.size();
if(count != 0 && blockInfo.shouldDrawFace(face)) {
if (count != 0 && blockInfo.shouldDrawFace(face)) {
for(int j = 0; j < count; j++) {
BakedQuad q = quads.get(j);
renderQuad(q, face, defaultMaterial);
@ -100,7 +100,7 @@ public class TerrainFallbackConsumer extends AbstractQuadRenderer implements Con
List<BakedQuad> quads = model.getQuads(blockState, null, random.get());
final int count = quads.size();
if(count != 0) {
if (count != 0) {
for(int j = 0; j < count; j++) {
BakedQuad q = quads.get(j);
renderQuad(q, null, defaultMaterial);
@ -110,12 +110,12 @@ public class TerrainFallbackConsumer extends AbstractQuadRenderer implements Con
private void renderQuad(BakedQuad quad, Direction cullFace, Value defaultMaterial) {
final int[] vertexData = quad.getVertexData();
if(!CompatibilityHelper.canRender(vertexData)) {
if (!CompatibilityHelper.canRender(vertexData)) {
return;
}
final MutableQuadViewImpl editorQuad = this.editorQuad;
System.arraycopy(vertexData, 0, editorBuffer, 0, 28);
System.arraycopy(vertexData, 0, editorBuffer, 0, 32);
editorQuad.cullFace(cullFace);
final Direction lightFace = quad.getFace();
editorQuad.lightFace(lightFace);
@ -123,7 +123,7 @@ public class TerrainFallbackConsumer extends AbstractQuadRenderer implements Con
editorQuad.colorIndex(quad.getColorIndex());
editorQuad.material(defaultMaterial);
if(!transform.transform(editorQuad)) {
if (!transform.transform(editorQuad)) {
return;
}
@ -132,7 +132,7 @@ public class TerrainFallbackConsumer extends AbstractQuadRenderer implements Con
editorQuad.invalidateShape();
aoCalc.compute(editorQuad, true);
chunkInfo.applyOffsets(editorQuad);
tesselateSmooth(editorQuad, blockInfo.defaultLayerIndex, editorQuad.colorIndex());
tesselateSmooth(editorQuad, blockInfo.defaultLayer, editorQuad.colorIndex());
} else {
// vanilla compatibility hack
// For flat lighting, cull face drives everything and light face is ignored.
@ -145,7 +145,7 @@ public class TerrainFallbackConsumer extends AbstractQuadRenderer implements Con
editorQuad.lightFace(cullFace);
}
chunkInfo.applyOffsets(editorQuad);
tesselateFlat(editorQuad, blockInfo.defaultLayerIndex, editorQuad.colorIndex());
tesselateFlat(editorQuad, blockInfo.defaultLayer, editorQuad.colorIndex());
}
}
}

View file

@ -24,8 +24,9 @@ import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.fabricmc.indigo.renderer.aocalc.AoCalculator;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.chunk.ChunkRenderTask;
import net.minecraft.client.render.chunk.ChunkRenderer;
import net.minecraft.client.render.chunk.ChunkBatcher.ChunkRenderData;
import net.minecraft.client.render.chunk.ChunkBatcher.ChunkRenderer;
import net.minecraft.client.render.chunk.BlockLayeredBufferBuilder;
import net.minecraft.client.render.chunk.ChunkRendererRegion;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.util.crash.CrashException;
@ -46,17 +47,13 @@ public class TerrainRenderContext extends AbstractRenderContext implements Rende
private final TerrainMeshConsumer meshConsumer = new TerrainMeshConsumer(blockInfo, chunkInfo, aoCalc, this::transform);
private final TerrainFallbackConsumer fallbackConsumer = new TerrainFallbackConsumer(blockInfo, chunkInfo, aoCalc, this::transform);
public void setBlockView(ChunkRendererRegion blockView) {
blockInfo.setBlockView(blockView);
chunkInfo.setBlockView(blockView);
}
public void setChunkTask(ChunkRenderTask chunkTask) {
chunkInfo.setChunkTask(chunkTask);
}
public TerrainRenderContext prepare(ChunkRenderer chunkRenderer, BlockPos.Mutable chunkOrigin, boolean [] resultFlags) {
chunkInfo.prepare(chunkRenderer, chunkOrigin, resultFlags);
public TerrainRenderContext prepare(
ChunkRendererRegion blockView,
ChunkRenderer chunkRenderer,
ChunkRenderData chunkData,
BlockLayeredBufferBuilder builders) {
blockInfo.setBlockView(blockView);
chunkInfo.prepare(blockView, chunkRenderer, chunkData, builders);
return this;
}
@ -78,7 +75,8 @@ public class TerrainRenderContext extends AbstractRenderContext implements Rende
CrashReportSection.addBlockInfo(crashReportElement_1, blockPos, blockState);
throw new CrashException(crashReport_1);
}
return chunkInfo.resultFlags[blockInfo.defaultLayerIndex];
// false because we've already marked the chunk as populated - caller doesn't need to
return false;
}
@Override

View file

@ -9,9 +9,10 @@
"BufferBuilderOffsetAccessor",
"MixinBlockModelRenderer",
"MixinBufferBuilder",
"MixinChunkRebuildTask",
"MixinChunkRenderData",
"MixinChunkRenderer",
"MixinChunkRendererRegion",
"MixinChunkRenderTask",
"MixinItemRenderer"
],
"injectors": {

View file

@ -16,8 +16,8 @@
"FabricMC"
],
"depends": {
"fabricloader": ">=0.6.1",
"minecraft": ">=1.15-",
"fabricloader": ">=0.6.2",
"minecraft": ">=1.15-alpha.19.38.b",
"fabric-api-base": "*",
"fabric-renderer-api-v1": "*"
},

View file

@ -1,5 +1,5 @@
archivesBaseName = "fabric-rendering-data-attachment-v1"
version = getSubprojectVersion(project, "0.1.0")
version = getSubprojectVersion(project, "0.1.1")
dependencies {
compile project(path: ':fabric-api-base', configuration: 'dev')

View file

@ -40,7 +40,7 @@ import net.minecraft.world.BlockRenderView;
* application from network packets and render chunk rebuilds. Use of {link #getCachedRenderData()}
* will ensure consistency of model state with the rest of the chunk being rendered.<p>
*
* Models should avoid using {@link ExtendedBlockView#getBlockEntity(BlockPos)}
* Models should avoid using {@link BlockRenderView#getBlockEntity(BlockPos)}
* to ensure thread safety because this view may be accessed outside the main client thread.
* Models that require Block Entity data should implement {@link RenderAttachmentBlockEntity}
* and then use {@link #getBlockEntityRenderAttachment(BlockPos)} to retrieve it. When called from the
@ -59,7 +59,7 @@ public interface RenderAttachedBlockView extends BlockRenderView {
* @param pos Position of the block for the block model.
*/
default Object getBlockEntityRenderAttachment(BlockPos pos) {
BlockEntity be = this.getBlockEntity(pos);
BlockEntity be = ((BlockRenderView) this).getBlockEntity(pos);
return be == null ? null : ((RenderAttachmentBlockEntity) be).getRenderAttachmentData();
}
}

View file

@ -17,11 +17,12 @@
package net.fabricmc.fabric.mixin.rendering.data;
import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachedBlockView;
import net.minecraft.class_4538;
import net.minecraft.world.BlockRenderView;
import org.spongepowered.asm.mixin.Mixin;
/** Make {@link BlockRenderView} implement {@link RenderAttachedBlockView}. */
@Mixin(BlockRenderView.class)
@Mixin(class_4538.class)
public interface MixinViewableWorld extends RenderAttachedBlockView {
}

View file

@ -1,5 +1,5 @@
archivesBaseName = "fabric-rendering-fluids-v1"
version = getSubprojectVersion(project, "0.1.1")
version = getSubprojectVersion(project, "0.1.2")
dependencies {
compile project(path: ':fabric-api-base', configuration: 'dev')

View file

@ -1,2 +1,2 @@
archivesBaseName = "fabric-resource-loader-v0"
version = getSubprojectVersion(project, "0.1.3")
version = getSubprojectVersion(project, "0.1.4")

View file

@ -15,6 +15,7 @@ rootProject.name = "fabric-api"
include 'fabric-api-base'
include 'fabric-biomes-v1'
include 'fabric-blockrenderlayer-v1'
include 'fabric-commands-v0'
include 'fabric-containers-v0'
include 'fabric-content-registries-v0'

View file

@ -17,7 +17,7 @@
],
"depends": {
"fabricloader": ">=0.6.2",
"minecraft": ">=1.15-alpha.19.38.a"
"minecraft": "~1.15-alpha.19.38.b"
},
"description": "Core API module providing key hooks and intercompatibility features."
}