Skip to content

Commit

Permalink
Modernize Indium (ported from Indigo) (#115)
Browse files Browse the repository at this point in the history
* Modernize Indium

* Make requested changes

* More changes

* Remove javadoc note about emissive support

Co-authored-by: PepperCode1 <[email protected]>
  • Loading branch information
IMS and PepperCode1 authored Apr 24, 2022
1 parent 5f9388a commit f2f123c
Show file tree
Hide file tree
Showing 14 changed files with 249 additions and 192 deletions.
6 changes: 3 additions & 3 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ org.gradle.jvmargs=-Xmx1G
# Fabric Properties
# check these on https://modmuss50.me/fabric.html
minecraft_version=1.18.2
yarn_mappings=1.18.2+build.1
yarn_mappings=1.18.2+build.3
loader_version=0.13.3
# Mod Properties
mod_version=1.0.2
mod_version=1.0.3
maven_group=link.infra
archives_base_name=indium
# Dependencies
# check this on https://modmuss50.me/fabric.html
fabric_version=0.47.8+1.18.2
fabric_version=0.51.1+1.18.2
4 changes: 2 additions & 2 deletions src/main/java/link/infra/indium/Indium.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
import java.util.Properties;

public class Indium implements ClientModInitializer {
public static final boolean ALWAYS_TESSELATE_INDIUM;
public static final boolean ALWAYS_TESSELLATE_INDIUM;
public static final AoConfig AMBIENT_OCCLUSION_MODE;
/** Set true in dev env to confirm results match vanilla when they should. */
public static final boolean DEBUG_COMPARE_LIGHTING;
Expand Down Expand Up @@ -104,7 +104,7 @@ private static TriState asTriState(String property) {
}
}

ALWAYS_TESSELATE_INDIUM = asBoolean((String) properties.computeIfAbsent("always-tesselate-blocks", (a) -> "auto"), false);
ALWAYS_TESSELLATE_INDIUM = asBoolean((String) properties.computeIfAbsent("always-tesselate-blocks", (a) -> "auto"), false);
AMBIENT_OCCLUSION_MODE = asEnum((String) properties.computeIfAbsent("ambient-occlusion-mode", (a) -> "auto"), AoConfig.ENHANCED);
DEBUG_COMPARE_LIGHTING = asBoolean((String) properties.computeIfAbsent("debug-compare-lighting", (a) -> "auto"), false);
FIX_SMOOTH_LIGHTING_OFFSET = asBoolean((String) properties.computeIfAbsent("fix-smooth-lighting-offset", (a) -> "auto"), true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@

@Mixin(targets = "net.minecraft.client.render.block.BlockModelRenderer$AmbientOcclusionCalculator")
public abstract class MixinAmbientOcclusionCalculator implements AccessAmbientOcclusionCalculator {
@Shadow private float[] brightness;
@Shadow private int[] light;
@Shadow
private float[] brightness;
@Shadow
private int[] light;

@Shadow
public abstract void apply(BlockRenderView blockRenderView, BlockState blockState, BlockPos pos, Direction face, float[] aoData, BitSet controlBits, boolean shade);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
Expand All @@ -42,15 +43,16 @@

@Mixin(BlockModelRenderer.class)
public abstract class MixinBlockModelRenderer implements AccessBlockModelRenderer {
@Unique
private final ThreadLocal<BlockRenderContext> indium_contexts = ThreadLocal.withInitial(BlockRenderContext::new);

@Shadow
protected abstract void getQuadDimensions(BlockRenderView blockView, BlockState blockState, BlockPos blockPos, int[] vertexData, Direction face, float[] aoData, BitSet controlBits);

private final ThreadLocal<BlockRenderContext> CONTEXTS = ThreadLocal.withInitial(BlockRenderContext::new);

@Inject(at = @At("HEAD"), method = "render(Lnet/minecraft/world/BlockRenderView;Lnet/minecraft/client/render/model/BakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumer;ZLjava/util/Random;JI)Z", cancellable = true)
private void hookRender(BlockRenderView blockView, BakedModel model, BlockState state, BlockPos pos, MatrixStack matrix, VertexConsumer buffer, boolean checkSides, Random rand, long seed, int overlay, CallbackInfoReturnable<Boolean> ci) {
if (!((FabricBakedModel) model).isVanillaAdapter()) {
BlockRenderContext context = CONTEXTS.get();
BlockRenderContext context = indium_contexts.get();
// Note that we do not support face-culling here (so checkSides is ignored)
ci.setReturnValue(context.render(blockView, model, state, pos, matrix, buffer, rand, seed, overlay));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@

package link.infra.indium.mixin.renderer;

import link.infra.indium.renderer.accessor.AccessItemRenderer;
import link.infra.indium.renderer.render.IndiumQuadHandler;
import link.infra.indium.renderer.render.ItemRenderContext;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
Expand All @@ -32,29 +36,25 @@
import net.minecraft.item.ItemStack;

import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
import link.infra.indium.renderer.render.ItemRenderContext;
import link.infra.indium.renderer.render.ItemRenderContext.VanillaQuadHandler;
import link.infra.indium.renderer.accessor.AccessItemRenderer;
import link.infra.indium.renderer.render.IndiumQuadHandler;

@Mixin(ItemRenderer.class)
public abstract class MixinItemRenderer implements AccessItemRenderer {
@Shadow
protected abstract void renderBakedItemModel(BakedModel model, ItemStack stack, int light, int overlay, MatrixStack matrixStack, VertexConsumer buffer);

@Shadow
protected ItemColors colors;

private final VanillaQuadHandler vanillaHandler = new IndiumQuadHandler(this);
@Unique
private final ThreadLocal<ItemRenderContext> fabric_contexts = ThreadLocal.withInitial(() -> new ItemRenderContext(colors));

private final ThreadLocal<ItemRenderContext> CONTEXTS = ThreadLocal.withInitial(() -> new ItemRenderContext(colors));
@Unique
private final ItemRenderContext.VanillaQuadHandler indium_vanillaHandler = new IndiumQuadHandler(this);

@Inject(at = @At("HEAD"), method = "renderItem(Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/render/model/json/ModelTransformation$Mode;ZLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;IILnet/minecraft/client/render/model/BakedModel;)V", cancellable = true)
public void hook_method_23179(ItemStack stack, ModelTransformation.Mode transformMode, boolean invert, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int light, int overlay, BakedModel model, CallbackInfo ci) {
final FabricBakedModel fabricModel = (FabricBakedModel) model;
@Shadow
protected abstract void renderBakedItemModel(BakedModel model, ItemStack stack, int light, int overlay, MatrixStack matrixStack, VertexConsumer buffer);

if (!(stack.isEmpty() || fabricModel.isVanillaAdapter())) {
CONTEXTS.get().renderModel(stack, transformMode, invert, matrixStack, vertexConsumerProvider, light, overlay, fabricModel, vanillaHandler);
@Inject(at = @At("HEAD"), method = "renderItem(Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/render/model/json/ModelTransformation$Mode;ZLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;IILnet/minecraft/client/render/model/BakedModel;)V", cancellable = true)
public void hook_renderItem(ItemStack stack, ModelTransformation.Mode transformMode, boolean invert, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int light, int overlay, BakedModel model, CallbackInfo ci) {
if (!stack.isEmpty() && !((FabricBakedModel) model).isVanillaAdapter()) {
fabric_contexts.get().renderModel(stack, transformMode, invert, matrixStack, vertexConsumerProvider, light, overlay, model, indium_vanillaHandler);
ci.cancel();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ public void afterPerformBuild(ChunkBuildContext buildContext, CancellationSource
public boolean onRenderBlock(BlockRenderer blockRenderer, BlockRenderView world, BlockState state, BlockPos pos, BlockPos origin, BakedModel model, ChunkModelBuilder buffers, boolean cull, long seed, ChunkBuildContext buildContext, CancellationSource cancellationSource) {
// We need to get the model with a bit more context than BlockRenderer has, so we do it here

if (!Indium.ALWAYS_TESSELATE_INDIUM && ((FabricBakedModel) model).isVanillaAdapter()) {
if (!Indium.ALWAYS_TESSELLATE_INDIUM && ((FabricBakedModel) model).isVanillaAdapter()) {
return blockRenderer.renderModel(world, state, pos, origin, model, buffers, cull, seed);
} else {
TerrainRenderContext context = ((AccessChunkRenderCacheLocal) buildContext.cache).indium$getTerrainRenderContext();
Vec3d modelOffset = state.getModelOffset(world, pos);
return context.tesselateBlock(state, pos, origin, model, modelOffset);
return context.tessellateBlock(state, pos, origin, model, modelOffset);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import link.infra.indium.renderer.RenderMaterialImpl;
import link.infra.indium.renderer.helper.GeometryHelper;
import link.infra.indium.renderer.helper.NormalHelper;
import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial;
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView;
import net.minecraft.util.math.Direction;
Expand Down Expand Up @@ -148,7 +149,9 @@ public void copyTo(MutableQuadView target) {

final MutableQuadViewImpl quad = (MutableQuadViewImpl) target;
// copy everything except the material
System.arraycopy(data, baseIndex + 1, quad.data, quad.baseIndex + 1, EncodingFormat.TOTAL_STRIDE - 1);
RenderMaterial material = quad.material();
System.arraycopy(data, baseIndex, quad.data, quad.baseIndex, EncodingFormat.TOTAL_STRIDE);
quad.material(material);
quad.faceNormal.set(faceNormal.getX(), faceNormal.getY(), faceNormal.getZ());
quad.nominalFace = this.nominalFace;
quad.isGeometryInvalid = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;

abstract class AbstractRenderContext implements RenderContext {
private final ObjectArrayList<QuadTransform> transformStack = new ObjectArrayList<>();
private static final QuadTransform NO_TRANSFORM = (q) -> true;

private QuadTransform activeTransform = NO_TRANSFORM;
private final ObjectArrayList<QuadTransform> transformStack = new ObjectArrayList<>();
private final QuadTransform stackTransform = (q) -> {
int i = transformStack.size() - 1;

Expand All @@ -37,8 +38,6 @@ abstract class AbstractRenderContext implements RenderContext {
return true;
};

private QuadTransform activeTransform = NO_TRANSFORM;

protected final boolean transform(MutableQuadView q) {
return activeTransform.transform(q);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,16 @@
* manipulating the data via NIO.
*/
public class BaseFallbackConsumer extends BaseQuadRenderer implements Consumer<BakedModel> {
private static Value MATERIAL_FLAT = (Value) IndiumRenderer.INSTANCE.materialFinder().disableAo(0, true).find();
private static Value MATERIAL_SHADED = (Value) IndiumRenderer.INSTANCE.materialFinder().find();

private final int[] editorBuffer = new int[EncodingFormat.TOTAL_STRIDE];
private static final Value MATERIAL_FLAT = (Value) IndiumRenderer.INSTANCE.materialFinder().disableAo(0, true).find();
private static final Value MATERIAL_SHADED = (Value) IndiumRenderer.INSTANCE.materialFinder().find();

BaseFallbackConsumer(QuadBufferer bufferer, BlockRenderInfo blockInfo, AoCalculator aoCalc, QuadTransform transform) {
super(bufferer, blockInfo, aoCalc, transform);
}

private final MutableQuadViewImpl editorQuad = new MutableQuadViewImpl() {
{
data = editorBuffer;
data = new int[EncodingFormat.TOTAL_STRIDE];
material(MATERIAL_SHADED);
}

Expand All @@ -82,28 +80,18 @@ public void accept(BakedModel model) {
final Value defaultMaterial = blockInfo.defaultAo && model.useAmbientOcclusion() ? MATERIAL_SHADED : MATERIAL_FLAT;
final BlockState blockState = blockInfo.blockState;

for (int i = 0; i < 6; i++) {
final Direction face = ModelHelper.faceFromIndex(i);
final List<BakedQuad> quads = model.getQuads(blockState, face, random.get());
for (int i = 0; i <= ModelHelper.NULL_FACE_ID; i++) {
final Direction cullFace = ModelHelper.faceFromIndex(i);
final List<BakedQuad> quads = model.getQuads(blockState, cullFace, random.get());
final int count = quads.size();

if (count != 0) {
for (int j = 0; j < count; j++) {
final BakedQuad q = quads.get(j);
renderQuad(q, face, defaultMaterial);
renderQuad(q, cullFace, defaultMaterial);
}
}
}

final List<BakedQuad> quads = model.getQuads(blockState, null, random.get());
final int count = quads.size();

if (count != 0) {
for (int j = 0; j < count; j++) {
final BakedQuad q = quads.get(j);
renderQuad(q, null, defaultMaterial);
}
}
}

private void renderQuad(BakedQuad quad, Direction cullFace, Value defaultMaterial) {
Expand All @@ -123,16 +111,16 @@ private void renderQuad(BakedQuad quad, Direction cullFace, Value defaultMateria
if (!editorQuad.material().disableAo(0)) {
// needs to happen before offsets are applied
aoCalc.compute(editorQuad, true);
tesselateSmooth(editorQuad, blockInfo.defaultLayer, editorQuad.colorIndex());
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 tesselateFlat() because needs to happen before offsets are applied
// Can't rely on lazy computation in tessellateFlat() because needs to happen before offsets are applied
editorQuad.geometryFlags();
}

tesselateFlat(editorQuad, blockInfo.defaultLayer, editorQuad.colorIndex());
tessellateFlat(editorQuad, blockInfo.defaultLayer, editorQuad.colorIndex());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import link.infra.indium.renderer.RenderMaterialImpl;

/**
* Consumer for pre-baked meshes. Works by copying the mesh data to a
* Consumer for pre-baked meshes. Works by copying the mesh data to an
* "editor" quad held in the instance, where all transformations are applied before buffering.
*/
public class BaseMeshConsumer extends BaseQuadRenderer implements Consumer<Mesh> {
Expand All @@ -44,7 +44,7 @@ protected BaseMeshConsumer(QuadBufferer bufferer, BlockRenderInfo blockInfo, AoC
* Where we handle all pre-buffer coloring, lighting, transformation, etc.
* Reused for all mesh quads. Fixed baking array sized to hold largest possible mesh quad.
*/
private class Maker extends MutableQuadViewImpl implements QuadEmitter {
private class Maker extends MutableQuadViewImpl {
{
data = new int[EncodingFormat.TOTAL_STRIDE];
material(IndiumRenderer.MATERIAL_STANDARD);
Expand Down Expand Up @@ -82,44 +82,44 @@ public QuadEmitter getEmitter() {
return editorQuad;
}

private void renderQuad(MutableQuadViewImpl q) {
if (!transform.transform(editorQuad)) {
private void renderQuad(MutableQuadViewImpl quad) {
if (!transform.transform(quad)) {
return;
}

if (!blockInfo.shouldDrawFace(q.cullFace())) {
if (!blockInfo.shouldDrawFace(quad.cullFace())) {
return;
}

final RenderMaterialImpl.Value mat = q.material();
final RenderMaterialImpl.Value mat = quad.material();

if (!mat.disableAo(0) && MinecraftClient.isAmbientOcclusionEnabled()) {
// needs to happen before offsets are applied
aoCalc.compute(q, false);
aoCalc.compute(quad, false);
}

tesselateQuad(q, mat, 0);
tessellateQuad(quad, mat, 0);
}

/**
* Determines color index and render layer, then routes to appropriate
* tesselate routine based on material properties.
* tessellate routine based on material properties.
*/
private void tesselateQuad(MutableQuadViewImpl quad, RenderMaterialImpl.Value mat, int textureIndex) {
private void tessellateQuad(MutableQuadViewImpl quad, RenderMaterialImpl.Value mat, int textureIndex) {
final int colorIndex = mat.disableColorIndex(textureIndex) ? -1 : quad.colorIndex();
final RenderLayer renderLayer = blockInfo.effectiveRenderLayer(mat.blendMode(textureIndex));

if (blockInfo.defaultAo && !mat.disableAo(textureIndex)) {
if (mat.emissive(textureIndex)) {
tesselateSmoothEmissive(quad, renderLayer, colorIndex);
tessellateSmoothEmissive(quad, renderLayer, colorIndex);
} else {
tesselateSmooth(quad, renderLayer, colorIndex);
tessellateSmooth(quad, renderLayer, colorIndex);
}
} else {
if (mat.emissive(textureIndex)) {
tesselateFlatEmissive(quad, renderLayer, colorIndex);
tessellateFlatEmissive(quad, renderLayer, colorIndex);
} else {
tesselateFlat(quad, renderLayer, colorIndex);
tessellateFlat(quad, renderLayer, colorIndex);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext.QuadTransform;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.LightmapTextureManager;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.util.math.*;
Expand All @@ -32,8 +33,6 @@
* Has most of the actual buffer-time lighting and coloring logic.
*/
public class BaseQuadRenderer {
static final int FULL_BRIGHTNESS = 0xF000F0;

protected final QuadBufferer bufferer;
protected final BlockRenderInfo blockInfo;
protected final AoCalculator aoCalc;
Expand Down Expand Up @@ -69,7 +68,7 @@ private void bufferQuad(MutableQuadViewImpl quad, RenderLayer renderLayer) {
// 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, RenderLayer renderLayer, int blockColorIndex) {
protected void tessellateSmooth(MutableQuadViewImpl q, RenderLayer renderLayer, int blockColorIndex) {
colorizeQuad(q, blockColorIndex);

for (int i = 0; i < 4; i++) {
Expand All @@ -81,19 +80,19 @@ protected void tesselateSmooth(MutableQuadViewImpl q, RenderLayer renderLayer, i
}

/** for emissive mesh quads with smooth lighting. */
protected void tesselateSmoothEmissive(MutableQuadViewImpl q, RenderLayer renderLayer, int blockColorIndex) {
protected void tessellateSmoothEmissive(MutableQuadViewImpl q, RenderLayer 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]));
q.lightmap(i, FULL_BRIGHTNESS);
q.lightmap(i, LightmapTextureManager.MAX_LIGHT_COORDINATE);
}

bufferQuad(q, renderLayer);
}

/** for non-emissive mesh quads and all fallback quads with flat lighting. */
protected void tesselateFlat(MutableQuadViewImpl quad, RenderLayer renderLayer, int blockColorIndex) {
protected void tessellateFlat(MutableQuadViewImpl quad, RenderLayer renderLayer, int blockColorIndex) {
colorizeQuad(quad, blockColorIndex);
shadeFlatQuad(quad);

Expand All @@ -107,12 +106,12 @@ protected void tesselateFlat(MutableQuadViewImpl quad, RenderLayer renderLayer,
}

/** for emissive mesh quads with flat lighting. */
protected void tesselateFlatEmissive(MutableQuadViewImpl quad, RenderLayer renderLayer, int blockColorIndex) {
protected void tessellateFlatEmissive(MutableQuadViewImpl quad, RenderLayer renderLayer, int blockColorIndex) {
colorizeQuad(quad, blockColorIndex);
shadeFlatQuad(quad);

for (int i = 0; i < 4; i++) {
quad.lightmap(i, FULL_BRIGHTNESS);
quad.lightmap(i, LightmapTextureManager.MAX_LIGHT_COORDINATE);
}

bufferQuad(quad, renderLayer);
Expand Down
Loading

0 comments on commit f2f123c

Please sign in to comment.