模型 (Models)
模型是决定方块或物品视觉形状和纹理的 JSON 文件。模型由立方体元素组成,每个元素都有自己的尺寸,然后每个面被分配一个纹理。
物品使用由其客户端物品定义的关联模型,而方块使用方块状态文件中的关联模型。这些位置是相对于 models 目录的,因此一个引用名称为 examplemod:item/example_model 的模型将由位于 assets/examplemod/models/item/example_model.json 的 JSON 文件定义。
规范 (Specification)
另请参阅: Minecraft Wiki 上的模型
模型是一个根标签中包含以下可选属性的 JSON 文件:
loader:NeoForge 添加。设置自定义模型加载器。更多信息请参见模型加载器。parent:设置父模型,以相对于models文件夹的资源位置形式。所有父级属性将被应用,然后由声明模型中设置的属性覆盖。常见的父级包括:minecraft:block/block:所有方块模型的通用父级。minecraft:block/cube:所有使用 1x1x1 立方体模 型的模型的父级。minecraft:block/cube_all:立方体模型的变体,在所有六个面上使用相同的纹理,例如圆石或木板。minecraft:block/cube_bottom_top:立方体模型的变体,在所有四个水平面上使用相同的纹理,顶部和底部使用单独的纹理。常见的例子包括砂岩或錾制石英。minecraft:block/cube_column:立方体模型的变体,具有侧面纹理以及底部和顶部纹理。例子包括原木,以及石英和紫珀柱。minecraft:block/cross:使用两个具有相同纹理的平面的模型,一个顺时针旋转 45°,另一个逆时针旋转 45°,从上方看形成 X 形(因此得名)。例子包括大多数植物,例如草、树苗和花。minecraft:item/generated:经典 2D 平面物品模型的父级。游戏中大多数物品使用。忽略elements块,因为其四边形是从纹理生成的。minecraft:item/handheld:看起来像是被玩家实际持有的 2D 平面物品模型的父级。主要由工具使用。是item/generated的子模型,这导致它也忽略elements块。- 方块物品通常(但不总是)使用其对应的方块模型作为其[物品模型][itemmodels]。例如,圆石的客户端物品使用
minecraft:block/cobblestone模型。
ambientocclusion:是否启用环境光遮蔽。仅对方块模型有效。默认为true。如果你的自定义方块模型有奇怪的阴影,尝试将其设置为false。render_type:NeoForge 添加。设置要使用的渲染类型组。更多信息请参见渲染类型组。gui_light:可以是"front"或"side"。如果是"front",光线将来自前方,适用于平面 2D 模型。如果是"side",光线将来自侧面,适用于 3D 模型(尤其是方块模型)。默认为"side"。仅对物品模型有效。textures:一个子对象,将名称(称为纹理变量)映射到纹理位置。纹理变量然后可以在元素中使用。它们也可以在元素中指定,但留空以便子模型指定它们。- 方块模型还应指定一个
particle纹理。当方块掉落、在上面跑过或被破坏时使用此纹理。 - 物品模型也可以使用图层纹理,命名为
layer0、layer1等,其中索引较高的图层渲染在索引较低的图层之上(例如,layer1将渲染在layer0之上)。仅当父级是item/generated时有效,并且最多适用于 5 个图层(layer0到layer4)。
- 方块模型还应指定一个
elements:立方体元素的列表。display:一个子对象,保存不同视角的不同显示选项,有关可能的键,请参阅链接文章。仅对物品模型有效,但通常在方块模型中指定,以便物品模型可以继承显示选项。每个视角都是一个可选的子对象,可能包含以下选项,按此顺序应用:translation:模型的平移,指定为[x, y, z]。rotation:模型的旋转,指定为[x, y, z]。scale:模型的缩放,指定为[x, y, z]。right_rotation:NeoForge 添加。缩放后应用的第二个旋转,指定为[x, y, z]。
transform:参见根变换。
如果你难以确定如何准确指定某些内容,可以查看执行类似操作的原版模型。
渲染类型组 (Render Type Groups)
使用可选的 NeoForge 添加的 render_type 字段,你可以为模型设置渲染类型组。渲染类型组由两部分组成:一个用于指定模型作为方块渲染方式的 ChunkSectionLayer,以及一个用于指定模型作为物品渲染方式的 RenderType。如果未设置(所有原版模型都是这种情况),游戏将回退到 ItemBlockRenderTypes 中硬编码的图层和渲染类型。如果 ItemBlockRenderTypes 不包含该图层或渲染类型,它将回退到方块的 ChunkSectionLayer#SOLID 和物品的 Sheets#TRANSLUCENT_ITEM_CULL_BLOCK_SHEET。原版和 NeoForge 公开了以下渲染类型组:
minecraft:solid:用于完全实心的模型,例如石头。minecraft:cutout:用于任何像素要么完全实心要么完全透明的模型,即具有完全透明度或没有透明度,例如玻璃。minecraft:cutout_mipped:minecraft:cutout的变体,将在远距离缩放纹理以避免视觉伪影(Mipmapping)。不将 Mipmapping 应用于物品渲染,因为通常不需要并且可能导致伪影。例如,树叶使用。minecraft:cutout_mipped_all:minecraft:cutout_mipped的变体,也将 Mipmapping 应用于物品模型。minecraft:translucent:用于任何像素可能部分透明的模型,例如染色玻璃。minecraft:tripwire:用于具有渲染到天气目标特殊要求的模型,即绊线。neoforge:item_unlit:NeoForge 添加。应由那些作为物品渲染时不考虑光照方向的模型使用。
选择合适的渲染类型组在一定程度上是性能问题。实体渲染比切除渲染快,切除渲染比半透明渲染快。因此,你应该为你的用例指定“最严格”的适用渲染类型,因为这也将是最快的。
如果你愿意,你也可以添加自己的渲染类型组。为此,请订阅模组总线上的事件 RegisterNamedRenderTypesEvent 并使用 #register 注册你的渲染类型组。#register 有三个参数:
- 渲染类型组的名称。应是一个前缀为你的模组 ID 的
ResourceLocation。 - 区块图层。可以使用任何
ChunkSectionLayer。 - 实体渲染类型。必须是具有
DefaultVertexFormat.NEW_ENTITY顶点格式的渲染类型。
元素 (Elements)
元素是立方体对象的 JSON 表示。它具有以下属性:
from:立方体起始角的坐标,指定为[x, y, z]。以 1/16 方块单位指定。例如,[0, 0, 0]将是“左下”角,[8, 8, 8]将是中心,[16, 16, 16]将是方块的“右上”角。to:立方体结束角的坐标,指定为[x, y, z]。与from一样,以 1/16 方块单位指定。
Minecraft 将 from 和 to 中的值限制在范围 [-16, 32] 内。但是,强烈建议不要超过 [0, 16],因为这会导致光照和/或剔除问题。
neoforge_data:参见额外面数据。faces:一个包含最多 6 个面数据的对象,分别命名为north、south、east、west、up和down。每个面都有以下数据:uv:面的 uv,指定为[u1, v1, u2, v2],其中u1, v1是左上角 uv 坐标,u2, v2是右下角 uv 坐标。texture:用于面的纹理。必须是前缀为#的纹理变量。例如,如果你的模型有一个名为wood的纹理,你将使用#wood来引用该纹理。技术上可选,如果不存在将使用缺失纹理。rotation:可选。将纹理顺时针旋转 90、180 或 270 度。cullface:可选。告诉渲染引擎当指定方向有完整方块接触时跳过渲染该面。方向可以是north、south、east、west、up或down。tintindex:可选。指定一个可能被颜色处理器使用的色调索引,更多信息请参见着色。默认为 -1,表示无着色。neoforge_data:参见额外面数据。
此外,它可以指定以下可选属性:
shade:仅用于方块模型。可选。此元素的表面是否应具有方向相关的阴影。默认为 true。rotation:对象的旋转,指定为包含以下数据的子对象:angle:旋转角度,以度为单位。可以是 -45 到 45,步长为 22.5 度。axis:要围绕旋转的轴。目前无法围绕多个轴旋转对象。origin:可选。要围绕旋转的原始点,指定为[x, y, z]。注意这些是绝对值,即它们不相对于立方体的位置。如果未指定,将使用[0, 0, 0]。
额外面数据 (Extra Face Data)
额外面数据(neoforge_data)可以应用于元素和元素的单个面。在所有可用的上下文中它都是可选的。如果同时指定了元素级和面级额外面数据,则面级数据将覆盖元素级数据。额外数据可以指定以下数据:
color:用给定颜色为面着色。必须是 ARGB 值。可以指定为字符串或十进制整数(JSON 不支持十六进制字面量)。默认为0xFFFFFFFF。如果颜色值是常量,这可以替代着色使用。block_light:覆盖此面使用的方块光照值。默认为 0。sky_light:覆盖此面使用的天空光照值。默认为 0。ambient_occlusion:为此面禁用或启用环境光遮蔽。默认为模型中设置的值。
根变换 (Root Transforms)
在模型顶层添加 transform 属性告诉加载器应在应用方块状态文件(对于方块模型)中的旋转或 display 块(对于物品模型)中的变换之前,对所有几何体应用变换。这是由 NeoForge 添加的。
根变换可以通过两种方式指定。第一种方式是作为名为 matrix 的单个属性,包含一个变换 3x4 矩阵(行主序,省略最后一行),形式为嵌套的 JSON 数组。该矩阵是按顺序应用的平移、左旋转、缩放、右旋转和变换原点的组合。示例看起来像这样:
{
// ...
"transform": {
"matrix": [
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]
]
}
}
第二种方式是指定一个 JSON 对象,包含以下任何组合的条目,按此顺序应用:
translation:相对平移。指定为三维向量([x, y, z]),如果不存在则默认为[0, 0, 0]。rotation或left_rotation:在缩放之前应用于平移原点的旋转。默认为无旋转。通过以下方式之一指定:- 一个具有单轴到旋转映射的 JSON 对象,例如
{"x": 90} - 一个 JSON 对象数组,每个对象具有单轴到旋转映射,按指定顺序应用,例如
[{"x": 90}, {"y": 45}, {"x": -22.5}] - 一个包含三个值的数组,每个值指定围绕每个轴的旋转,例如
[90, 45, -22.5] - 一个直接指定四元数的四个值的数组,例如
[0.38268346, 0, 0, 0.9238795](= 绕 X 轴旋转 45 度)
- 一个具有单轴到旋转映射的 JSON 对象,例如
scale:相对于平移原点的缩放。指定为三维向量([x, y, z]),如果不存在则默认为[1, 1, 1]。post_rotation或right_rotation:在缩放之后应用于平移原点的旋转。默认为无旋转。指定方式与rotation相同。origin:用于旋转和缩放的原始点。变换也作为最后一步移动到这里。指定为三维向量([x, y, z])或使用三个内置值之一"corner"(=[0, 0, 0])、"center"(=[0.5, 0.5, 0.5])或"opposing-corner"(=[1, 1, 1],默认)。
方块状态文件 (Blockstate Files)
另请参阅: Minecraft Wiki 上的方块状态文件
方块状态文件被游戏用于将不同的模型分配给不同的[方块状态][blockstate]。每个注册到游戏的方块必须恰好有一个方块状态文件。为方块状态指定方块模型的工作方式有三种,互斥:通过变体、多部分或 NeoForge 添加的定义类型。
在 variants 块内部,每个方 块状态都有一个元素。这是将方块状态与模型关联的主要方式,绝大多数方块使用。
- 键是方块状态的字符串表示,不包含方块名称,因此例如,对于非含水顶部台阶是
"type=top,waterlogged=false",或对于没有属性的方块是""。值得注意的是,未使用的属性可以省略。例如,如果waterlogged属性对选择的模型没有影响,则两个对象type=top,waterlogged=false和type=top,waterlogged=true可以合并为一个type=top对象。这也意味着空字符串对每个方块都有效。 - 值可以是单个模型对象或模型对象的数组。如果使用模型对象数组,将从其中随机选择一个模型。模型对象由以下数据组成:
type:NeoForge 添加。设置自定义方块状态模型加载器。更多信息请参见方块状态模型加载器。model:模型文件位置的路径,相对于命名空间的models文件夹,例如minecraft:block/cobblestone。x和y:模型在 x 轴/y 轴上的旋转。限制为 90 度的倍数。每个可选,默认为 0。uvlock:旋转时是否锁定模型的 UV。可选,默认为 false。weight:仅在模型对象数组中有用。赋予对象一个权重,用于选择随机模型对象时。可选,默认为 1。
相比之下,在 multipart 块内部,元素根据方块状态的属性进行组合。此方法主要由栅栏和墙使用,它们基于布尔属性启用四个方向部分。多部分元素由两部分组成:一个 when 块和一个 apply 块。
when块指定一个方块状态的字 符串表示或必须满足才能使元素应用的条件列表。列表可以命名为"OR"或"AND",对其内容执行相应的逻辑运算。单个方块状态和列表值都可以通过用|分隔多个实际值来额外指定(例如facing=east|facing=west)。apply块指定要使用的模型对象或模型对象数组。这与variants块完全相同。
最后,neoforge:definition_type 可以指定一个自定义模型加载器来注册方块状态文件。更多信息请参见方块状态定义加载器。
客户端物品 (Client Items)
客户端物品被游戏用于将一个模型或多个模型分配给 ItemStack 的状态。虽然模型 JSON 中有一些物品特定的字段,但客户端物品基于上下文消费模型来渲染,因此它们的大部分信息已移到它们自己单独的章节。
着色 (Tinting)
一些方块,例如草或树叶,会根据其位置和/或属性改变其纹理颜色。模型元素可以在其面上指定一个色调索引,这将允许颜色处理器处理相应的面。代码方面的工作通过三个事件进行,一个用于方块颜色处理器,一个用于基于生物群系的方法方块着色(与方块颜色处理器结合使用),一个用于物品着色源。它们的工作方式非常相似,所以让我们先看一下方块处理器:
@SubscribeEvent // 仅在物理客户端的模组事件总线上
public static void registerBlockColorHandlers(RegisterColorHandlersEvent.Block event) {
// 参数是方块的状态、方块所在的等级、方块的位置以及色调索引。
// 等级和位置可能为 null。
event.register((state, level, pos, tintIndex) -> {
// 替换为你自己的计算。有关原版参考,请参阅 BlockColors 类。
// 颜色为 ARGB 格式。 通常,如果色调索引为 -1,则表示不应进行着色,应使用默认值。
return 0xFFFFFFFF;
},
// 要应用着色的方块的变长参数
EXAMPLE_BLOCK.get(), ...);
}
以下是一个颜色解析器的示例:
@SubscribeEvent // 仅在物理客户端的模组事件总线上
public static void registerColorResolvers(RegisterColorHandlersEvent.ColorResolvers event) {
// 参数是当前的生物群系、方块的 X 位置和方块的 Z 位置。
event.register((biome, x, z) -> {
// 替换为你 自己的计算。有关原版参考,请参阅 BiomeColors 类。
// 颜色为 ARGB 格式。
return 0xFFFFFFFF;
});
}
关于物品着色,请参阅客户端物品文章中的相关部分。
注册独立模型 (Registering Standalone Models)
不直接以某种方式与方块或物品关联,但在其他上下文中(例如方块实体渲染器)仍然需要的模型,可以通过 ModelEvent.RegisterStandalone 注册:
// 这可以是任何类型,只要可以从 ResolvedModel 和 ModelBaker 获取
// 泛型类型应该是 UnbakedStandaloneModel<T> 的泛型类型,无论是什么
public static final StandaloneModelKey<QuadCollection> EXAMPLE_KEY = new StandaloneModelKey<>(
new ModelDebugName() {
@Override
public String debugName() {
// 独立模型的名称
// 可以是任何字符串,但应包含模组 ID
return "examplemod: Example Model";
}
}
);
@SubscribeEvent // 仅在物理客户端的模组事件总线上
public static void registerAdditional(ModelEvent.RegisterStandalone event) {
event.register(
// 要获取的模型
EXAMPLE_KEY,
// 我们关心的 UnbakedStandaloneModel<T>,本例中返回一个 QuadCollection
// 为简单起见,可以使用 SimpleUnbakedStandaloneModel<T> 的静态方法
SimpleUnbakedStandaloneModel.quadCollection(
// 模型 ID,相对于 `assets/<namespace>/models/<path>.json`
ResourceLocation.fromNamespaceAndPath("examplemod", "block/example_unused_model")
)
);
}