Skip to content

Commit

Permalink
Improve Indigo and FRAPI Test Mod (#3208)
Browse files Browse the repository at this point in the history
* Improve flat shade

- Use AO mode to make flat shade calculation consistent with shade applied by smooth lighting
- Use face normal to calculate shade if necessary
- Use normal shade even if no custom normals are set

* Improve FRAPI test mod

- Add octagonal column to test irregular face lighting
- Use obsidian sprite instead of missing sprite for frame mesh
- Simplify and organize registration
- Inline `simple` package

* Fix crumbling on 45 degree faces

- Fix checkstyle
- Give octagonal column a non-zero hardness

* Fix checkstyle

* Improve PillarBakedModel to fully support custom block appearance

* Explain OverlayVertexConsumer fix
  • Loading branch information
PepperCode1 authored Aug 13, 2023
1 parent 8536527 commit 6bdb2ed
Show file tree
Hide file tree
Showing 22 changed files with 862 additions and 362 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* 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.renderer.client;

import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

import net.minecraft.client.render.OverlayVertexConsumer;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.MathConstants;

@Mixin(OverlayVertexConsumer.class)
public class OverlayVertexConsumerMixin {
@Unique
private static final Direction[] DIRECTIONS = Direction.values();

/*
The original method call is used to get the closest axis-aligned direction of the world-space
normal vector for a certain face. The world-space normal vector is computed using matrices
that change when the camera values change. Due to precision errors during matrix
multiplication, the computed world-space normal of a face will not remain constant, so the
closest axis-aligned direction may flicker. This issue only affects faces that are directly
between two axis-aligned directions (45 degree faces) or three axis-aligned directions.
The fix involves requiring the dot product of each axis-aligned direction to be a small
amount greater than the previous maximum dot product to be set as the new maximum.
*/
@Redirect(method = "next()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/Direction;getFacing(FFF)Lnet/minecraft/util/math/Direction;"))
private Direction redirectGetFacing(float x, float y, float z) {
Direction closestDir = Direction.NORTH;
float maxDot = 1.4E-45F;

for (Direction direction : DIRECTIONS) {
float dot = x * direction.getOffsetX() + y * direction.getOffsetY() + z * direction.getOffsetZ();

if (dot > maxDot + MathConstants.EPSILON) {
maxDot = dot;
closestDir = direction;
}
}

return closestDir;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"client.BakedModelMixin",
"client.MultipartBakedModelMixin",
"client.WeightedBakedModelMixin",
"client.SpriteAtlasTextureMixin"
"client.SpriteAtlasTextureMixin",
"client.OverlayVertexConsumerMixin"
],
"injectors": {
"defaultRequire": 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package net.fabricmc.fabric.test.renderer.simple;
package net.fabricmc.fabric.test.renderer;

import org.jetbrains.annotations.Nullable;

Expand All @@ -27,24 +27,19 @@
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.Identifier;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockRenderView;
import net.minecraft.world.World;

import net.fabricmc.fabric.api.block.v1.FabricBlock;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachedBlockView;

// Need to implement FabricBlock manually because this is a testmod for another Fabric module, otherwise it would be injected.
public final class FrameBlock extends Block implements BlockEntityProvider, FabricBlock {
public final Identifier id;

public FrameBlock(Identifier id) {
super(FabricBlockSettings.copyOf(Blocks.IRON_BLOCK).nonOpaque());
this.id = id;
public class FrameBlock extends Block implements BlockEntityProvider, FabricBlock {
public FrameBlock(Settings settings) {
super(settings);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package net.fabricmc.fabric.test.renderer.simple;
package net.fabricmc.fabric.test.renderer;

import org.jetbrains.annotations.Nullable;

Expand All @@ -31,12 +31,12 @@

import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachmentBlockEntity;

public final class FrameBlockEntity extends BlockEntity implements RenderAttachmentBlockEntity {
public class FrameBlockEntity extends BlockEntity implements RenderAttachmentBlockEntity {
@Nullable
private Block block = null;

public FrameBlockEntity(BlockPos blockPos, BlockState blockState) {
super(RendererTest.FRAME_BLOCK_ENTITY, blockPos, blockState);
super(Registration.FRAME_BLOCK_ENTITY_TYPE, blockPos, blockState);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.fabric.test.renderer;

import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;

import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;

public final class Registration {
public static final FrameBlock FRAME_BLOCK = register("frame", new FrameBlock(FabricBlockSettings.copyOf(Blocks.IRON_BLOCK).nonOpaque()));
public static final FrameBlock FRAME_MULTIPART_BLOCK = register("frame_multipart", new FrameBlock(FabricBlockSettings.copyOf(Blocks.IRON_BLOCK).nonOpaque()));
public static final FrameBlock FRAME_VARIANT_BLOCK = register("frame_variant", new FrameBlock(FabricBlockSettings.copyOf(Blocks.IRON_BLOCK).nonOpaque()));
public static final Block PILLAR_BLOCK = register("pillar", new Block(FabricBlockSettings.create()));
public static final Block OCTAGONAL_COLUMN_BLOCK = register("octagonal_column", new Block(FabricBlockSettings.create().nonOpaque().strength(1.8F)));

public static final FrameBlock[] FRAME_BLOCKS = new FrameBlock[] {
FRAME_BLOCK,
FRAME_MULTIPART_BLOCK,
FRAME_VARIANT_BLOCK,
};

public static final Item FRAME_ITEM = register("frame", new BlockItem(FRAME_BLOCK, new Item.Settings()));
public static final Item FRAME_MULTIPART_ITEM = register("frame_multipart", new BlockItem(FRAME_MULTIPART_BLOCK, new Item.Settings()));
public static final Item FRAME_VARIANT_ITEM = register("frame_variant", new BlockItem(FRAME_VARIANT_BLOCK, new Item.Settings()));
public static final Item PILLAR_ITEM = register("pillar", new BlockItem(PILLAR_BLOCK, new Item.Settings()));
public static final Item OCTAGONAL_COLUMN_ITEM = register("octagonal_column", new BlockItem(OCTAGONAL_COLUMN_BLOCK, new Item.Settings()));

public static final BlockEntityType<FrameBlockEntity> FRAME_BLOCK_ENTITY_TYPE = register("frame", FabricBlockEntityTypeBuilder.create(FrameBlockEntity::new, FRAME_BLOCKS).build(null));

private static <T extends Block> T register(String path, T block) {
return Registry.register(Registries.BLOCK, RendererTest.id(path), block);
}

private static <T extends Item> T register(String path, T item) {
return Registry.register(Registries.ITEM, RendererTest.id(path), item);
}

private static <T extends BlockEntityType<?>> T register(String path, T blockEntityType) {
return Registry.register(Registries.BLOCK_ENTITY_TYPE, RendererTest.id(path), blockEntityType);
}

public static void init() {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.fabric.test.renderer;

import net.minecraft.util.Identifier;

import net.fabricmc.api.ModInitializer;

/**
* The testmod for the Fabric Renderer API. These tests are used to validate that
* Indigo's implementation is correct, but they may also be useful for other
* implementations of the Fabric Renderer API.
*
* <h3>Tests</h3>
*
* <ul>
* <li>Frame blocks display another block inside, scaled down and made translucent.
* Blocks that provide a block entity cannot be placed inside frames.
*
* <li>Pillars connect vertically with each other by changing textures. They also
* connect vertically to frame blocks containing a pillar, and vice versa.
*
* <li>Octagonal columns have irregular faces to test enhanced AO and normal shade. The
* octagonal item column has glint force enabled on all faces except the top and bottom
* faces.
* </ul>
*/
public final class RendererTest implements ModInitializer {
@Override
public void onInitialize() {
Registration.init();
}

public static Identifier id(String path) {
return new Identifier("fabric-renderer-api-v1-testmod", path);
}
}

This file was deleted.

This file was deleted.

5 changes: 3 additions & 2 deletions fabric-renderer-api-v1/src/testmod/resources/fabric.mod.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
"license": "Apache-2.0",
"depends": {
"fabric-renderer-api-v1":"*",
"fabric-model-loading-api-v1":"*",
"fabric-resource-loader-v0": "*"
},
"entrypoints": {
"main": [
"net.fabricmc.fabric.test.renderer.simple.RendererTest"
"net.fabricmc.fabric.test.renderer.RendererTest"
],
"client": [
"net.fabricmc.fabric.test.renderer.simple.client.RendererClientTest"
"net.fabricmc.fabric.test.renderer.client.RendererClientTest"
]
}
}
Loading

0 comments on commit 6bdb2ed

Please sign in to comment.