This is an old revision of the document!
渲染动态使用方块实体渲染器方块和物品
这是本教程的1.15版本。 对于1.14版本,请参见使用方块实体渲染器动态渲染块和项目(1.14)。
阅读本教程之前,请确保您已添加方块实体!
===== 介绍 =====
方块本身并不是那么有趣,
它们只是在某个位置和某个大小保持静止直到损坏。
我们可以使用方块实体渲染器来更加动态地渲染与方块实体相关联的项目和方块-渲染多个不同的项目,
在不同的位置和大小,甚至更多。
===== 例子 =====
在本教程中,我们将通过向其添加BlockEntityRenderer
来构建所创建的方块实体。
渲染器将显示一个自动点唱机,该自动点唱机漂浮在方块上方,上下,旋转。
我们需要做的第一件事是创建我们的“ BlockEntityRenderer”类:
<code java>
public class MyBlockEntityRenderer extends BlockEntityRenderer<DemoBlockEntity> {
A jukebox itemstack
private static ItemStack stack = new ItemStack(Items.JUKEBOX, 1); public MyBlockEntityRenderer(BlockEntityRenderDispatcher dispatcher) { super(dispatcher); } @Override public void render(DemoBlockEntity blockEntity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) { }
}
</code>
我们将需要注册我们的BlockEntityRenderer
,但仅针对客户端。
在单人游戏设置中这无关紧要,因为服务器与客户端在同一进程中运行。
但是,在多人游戏设置中,服务器在与客户端不同的进程中运行,服务器代码
没有BlockEntityRenderer
的概念,因此不接受注册。
要仅为客户端运行初始化代码,我们需要设置一个客户端
入口点。
在实现ClientModInitializer
的主类旁边创建一个新类:
public class ExampleModClient implements ClientModInitializer { @Override public void onInitializeClient() { // Here we will put client-only registration code } }
将此类设置为fabric.mod.json
中的“客户端”入口点(根据需要修改路径):
- "fabric.mod.json"
"entrypoints": { [...] "client": [ { "value": "tutorial.path.to.ExampleModClient" } ] }
并在我们的ClientModInitializer中注册BlockEntityRenderer
:
@Override public void onInitializeClient() { BlockEntityRendererRegistry.INSTANCE.register(DEMO_BLOCK_ENTITY, MyBlockEntityRenderer::new); }
我们重写了render
方法,该方法被称为每一帧(!),并在其中进行渲染
- 对于初学者,请调用
matrices.push();
,这在进行GL调用时是必需的(我们将在紧接之后进行):
public void render(DemoBlockEntity blockEntity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) { matrices.push(); }
然后,我们执行自动点唱机的移动(matrices.translate)和旋转(matrices.multiply)。 转换分为两部分:将其转换为高于方块中心的0.5、1.25和0.5。 第二部分是更改的部分:y值的偏移量。 偏移量是任何给定框架的项目高度。 每次我们都要重新计算,因为我们希望它可以动画上下跳跃。 我们通过以下方式计算:
- 获取当前世界时间,该时间会随着时间而变化。
- 添加部分刻度。 (部分刻度线是一个小数值,代表最后一次完整刻度线和现在之间的时间间隔。我们使用此方法是因为否则动画会抖动,因为每秒的刻度数少于每秒的帧数。)
- 用8除以减慢运动速度。
- 以正弦值产生介于-1和1之间的值,例如a正弦波.
- 将其除以4可垂直压缩正弦波,因此该项目不会上下移动太多。
public void render(DemoBlockEntity blockEntity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) { [...] // Calculate the current offset in the y value double offset = Math.sin((blockEntity.getWorld().getTime() + tickDelta) / 8.0) / 4.0; // Move the item matrices.translate(0.5, 1.25 + offset, 0.5); // Rotate the item matrices.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion((blockEntity.getWorld().getTime() + tickDelta) * 4)); }
最后,我们将获得Minecraft的ItemRenderer
,并使用renderItem
渲染自动点唱机项目。
我们还将ModelTransformation.Type.GROUND
传递给renderItem
,因为我们希望有类似的效果
躺在地上的物品。 尝试尝试使用此值,看看会发生什么(这是一个枚举)。
在这些GL调用之后,我们还需要调用matrices.pop();
:
public void render(DemoBlockEntity blockEntity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) { [...] MinecraftClient.getInstance().getItemRenderer().renderItem(stack, ModelTransformation.Type.GROUND, light, overlay, matrices, vertexConsumers); // Mandatory call after GL calls matrices.pop(); }
您可以立即尝试新创建的方块实体渲染器。 但是,如果您没有使方块透明,您会发现有些不对劲-浮动方块,点唱机是黑色的! 这是因为默认情况下,无论您在方块实体中进行渲染的任何内容,都将接收光线,就好像它与方块实体处于同一位置一样。 因此,浮动方块从不透明的方块中接收inside的光,这意味着它没有接收到光! 为了解决这个问题,我们将告诉Minecraft从上方的一个方块方块实体的位置接收光。
要获取灯光,我们在方块实体上方的位置调用WorldRenderer#getLightmapCoordinates();
,
并使用灯光,我们在renderItem();
中使用它:
@Override public void render(DemoBlockEntity blockEntity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) { [...] int lightAbove = WorldRenderer.getLightmapCoordinates(blockEntity.getWorld(), blockEntity.getPos().up()); MinecraftClient.getInstance().getItemRenderer().renderItem(stack, ModelTransformation.Type.GROUND, lightAbove, OverlayTexture.DEFAULT_UV, matrices, vertexConsumers); [...] }
点唱机现在应具有适当的照明。