Skip to main content
Version: 1.21.4

模型(Models)

模型(Model)是用于决定方块或物品外观形状和纹理的 JSON 文件。一个模型由若干立方体元素(cuboid elements)组成,每个元素有各自的尺寸,并且每个面的纹理可以单独指定。

物品(item)会使用它的 客户端物品 中定义的模型,而方块(block)则使用 方块状态文件 中关联的模型。这些路径都是相对于 models 目录的,因此名为 examplemod:item/example_model 的模型,会对应 assets/examplemod/models/item/example_model.json 这个 JSON 文件。

规范(Specification)

另见:模型(Model)在 Minecraft Wiki 上的相关内容

一个模型(model)是一个 JSON 文件,其根标签下包含如下可选属性:

  • loader:NeoForge 新增。设置一个自定义模型加载器(custom model loader)。详细信息请参阅 自定义模型加载器
  • parent:设置父模型,格式为相对于 models 文件夹的 资源位置。所有父模型的属性会被应用,然后被当前模型中设置的属性覆盖。常见的父模型包括:
    • minecraft:block/block:所有方块模型(block model)的通用父模型。
    • 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 块,因为其四边形(quad)是从纹理生成的。
    • minecraft:item/handheld:玩家实际持有时显示为 2D 扁平物品模型的父模型。主要被工具类物品使用。它是 item/generated 的子模型,因此同样会忽略 elements 块。
    • 方块物品(block item)通常(但不总是)使用对应的方块模型作为它们的 [物品模型][itemmodels]。例如,鹅卵石的客户端物品使用 minecraft:block/cobblestone 模型。
  • ambientocclusion:是否启用 环境光遮蔽。仅对方块模型有效。默认为 true。如果你的自定义方块模型出现奇怪的阴影,请尝试将其设为 false
  • render_type:NeoForge 新增。设置要使用的渲染类型。详细信息请参阅 渲染类型
  • gui_light:可以为 "front""side"。如果为 "front",光源来自正面,适用于 2D 扁平模型。如果为 "side",光源来自侧面,适用于 3D 模型(尤其是方块模型)。默认为 "side"。仅对物品模型有效。
  • textures:一个子对象,用于将名称(称为纹理变量,texture variables)映射到 纹理位置。纹理变量随后可以在 元素 中使用。你也可以在元素中指定纹理变量,但可以留空,这样子模型就可以指定它们。
    • 方块模型(block models)通常还应指定一个 particle 纹理。这个纹理会在踩踏、奔跑或破坏方块时被使用。
    • 物品模型(item models)也可以使用图层纹理(layer textures),命名为 layer0layer1 等,其中索引更高的图层会渲染在索引较低的图层之上(例如,layer1 会渲染在 layer0 之上)。这只在父模型为 item/generated 时有效,并且最多只支持 5 个图层(layer0layer4)。
  • elements:一个立方体 元素 的列表。
  • display:一个子对象,包含不同 视角 下的显示选项。具体可用的键请参阅链接文章。该属性仅对物品模型生效,但通常也会在方块模型中指定,以便物品模型可以继承这些显示选项。每个视角都是可选的子对象,可能包含以下选项,按此顺序应用:
    • translation:模型的平移,格式为 [x, y, z]
    • rotation:模型的旋转,格式为 [x, y, z]
    • scale:模型的缩放,格式为 [x, y, z]
    • right_rotation:NeoForge 新增。缩放之后应用的第二次旋转,格式为 [x, y, z]
  • transform:参见 根变换
tip

如果你不知道某个属性具体应该如何指定,可以参考一个实现了类似功能的原版模型(vanilla model)。

渲染类型(Render Types)

你可以使用可选的 NeoForge 新增字段 render_type,为你的模型设置渲染类型。如果没有设置(所有原版模型均未设置),游戏会回退到 ItemBlockRenderTypes 中硬编码的渲染类型。如果 ItemBlockRenderTypes 也没有为该方块指定渲染类型,则会回退到 minecraft:solid。原版提供了以下默认渲染类型:

  • minecraft:solid:用于完全实心的方块,例如石头。
  • minecraft:cutout:用于像玻璃这类方块,其任意像素要么完全不透明,要么完全透明(即没有半透明效果)。
  • minecraft:cutout_mippedminecraft:cutout 的一个变体,在远距离时会缩小纹理以避免视觉伪影(mipmapping)。此类型不会对物品渲染应用 mipmapping,因为通常不希望在物品上使用,且可能导致伪影。例如树叶会用到此类型。
  • minecraft:cutout_mipped_allminecraft:cutout_mipped 的变体,也会对物品模型应用 mipmapping。
  • minecraft:translucent:用于像染色玻璃这类方块,其任意像素都可能是部分透明的。
  • minecraft:tripwire:用于需要特殊渲染到天气目标的方块,例如绊线。
  • neoforge:item_unlit:NeoForge 新增。应当用于那些以物品形式渲染时不考虑光照方向的方块。

选择正确的渲染类型(render type)在一定程度上关系到性能。实心(solid)渲染比 cutout 渲染更快,而 cutout 渲染又比 translucent 渲染更快。因此,你应当为你的用例指定“最严格”的渲染类型,因为这通常也是最快的。

如果需要,你也可以添加自定义渲染类型。为此,需要订阅 mod bus 事件 RegisterNamedRenderTypesEvent,并通过 #register 方法注册你的渲染类型。#register 方法有三个参数:

  • 渲染类型的名称。应为以你的模组 id 作为前缀的 ResourceLocation
  • 区块渲染类型。可以使用 RenderType.chunkBufferLayers() 返回列表中的任意类型。
  • 实体渲染类型。必须是顶点格式为 DefaultVertexFormat.NEW_ENTITY 的渲染类型。

元素(Elements)

元素(element)是立方体对象的 JSON 表示。它具有以下属性:

  • from:立方体起始角的坐标,格式为 [x, y, z]。单位为方块的 1/16。例如,[0, 0, 0] 是“左下角”,[8, 8, 8] 是中心,[16, 16, 16] 是方块的“右上角”。
  • to:立方体结束角的坐标,格式为 [x, y, z]。同样以方块的 1/16 为单位。
tip

fromto 的数值在 Minecraft 中被限制在 [-16, 32] 范围内。但强烈建议不要超过 [0, 16],否则会导致光照和/或剔除问题。

  • neoforge_data: 详见 额外面数据
  • faces:这是一个包含最多 6 个面的对象,分别命名为 northsoutheastwestupdown。每个面都包含以下数据:
    • uv:面的 uv 坐标,格式为 [u1, v1, u2, v2],其中 u1, v1 是左上角的 uv 坐标,u2, v2 是右下角的 uv 坐标。
    • texture:该面使用的纹理。必须是以 # 开头的纹理变量。例如,如果你的模型有一个名为 wood 的纹理,则使用 #wood 来引用该纹理。技术上这是可选项,如果未指定则会使用缺失纹理。
    • rotation:可选。将纹理顺时针旋转 90、180 或 270 度。
    • cullface:可选。当指定方向上有一个完整方块与该面相邻时,告知渲染引擎跳过渲染该面。方向可以是 northsoutheastwestupdown
    • 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 新增的。

根变换(root transforms)可以通过两种方式指定。第一种方式是作为一个名为 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]
  • rotationleft_rotation:绕平移后原点旋转,在缩放之前应用。默认为无旋转。可以通过以下任意一种方式指定:
    • 一个 JSON 对象,键为轴,值为旋转角度,例如 {"x": 90}
    • 一个 JSON 对象数组,每个对象指定一个轴及其旋转角度,按数组顺序依次应用,例如 [{"x": 90}, {"y": 45}, {"x": -22.5}]
    • 一个包含三个值的数组,分别表示绕各轴的旋转角度,例如 [90, 45, -22.5]
    • 一个包含四个值的数组,直接指定四元数,例如 [0.38268346, 0, 0, 0.9238795](表示绕 X 轴旋转 45 度)
  • scale:相对于平移后原点的缩放。以三维向量([x, y, z])指定,若未提供则默认为 [1, 1, 1]
  • post_rotationright_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

方块状态文件用于让游戏将不同的模型分配给不同的 [方块状态][blockstates]。每个注册到游戏中的方块,必须有且只有一个方块状态文件。为方块状态指定方块模型有两种互斥的方式:variants(变体)和 multipart(多部件)。

variants 块中,每个方块状态都对应一个元素。这是将方块状态与模型关联的主要方式,也是绝大多数方块所采用的方法。

  • 键(key)是去掉方块名称后的方块状态(blockstate)字符串表示。例如,非注水的顶层台阶(slab)为 "type=top,waterlogged=false",而没有任何属性的方块则为 ""。需要注意的是,未使用的属性可以省略。例如,如果 waterlogged 属性对模型选择没有影响,那么 type=top,waterlogged=falsetype=top,waterlogged=true 这两个对象可以合并为一个 type=top 对象。这也意味着空字符串对于所有方块都是合法的键值。

  • 值(value)可以是单个模型对象,也可以是模型对象数组。如果使用模型对象数组,则会从中随机选择一个模型。一个模型对象包含以下数据:

    • model:模型文件的路径,相对于命名空间(namespace)的 models 文件夹。例如 minecraft:block/cobblestone
    • xy:模型在 x 轴/y 轴上的旋转角度。仅支持 90 度的整数倍。每个都是可选项,默认值为 0。
    • uvlock:在旋转模型时是否锁定 UV 坐标。可选项,默认值为 false。
    • weight:仅在模型对象数组中有意义。为该对象设置权重,用于随机选择模型对象时参考。可选项,默认值为 1。

相比之下,在 multipart 方块中,元素会根据方块状态(blockstate)的属性进行组合。这种方式主要被栅栏和墙体等方块使用,它们会根据布尔属性启用四个方向的部件。一个 multipart 元素由两个部分组成:when 块和 apply 块。

  • when 块用于指定方块状态的字符串表示,或必须满足的属性列表,才能应用该元素。属性列表可以命名为 "OR""AND",分别对其内容执行逻辑“或”或“与”操作。无论是单个方块状态还是列表值,都可以通过 | 分隔指定多个实际值(例如 facing=east|facing=west)。
  • apply 块指定要使用的模型对象或模型对象数组。其用法与 variants 块完全相同。

客户端物品(Client Items)

客户端物品 被游戏用于为 ItemStack 的状态分配一个或多个模型。虽然模型 JSON 中有一些特定于物品的字段,但客户端物品会根据上下文选择模型进行渲染,因此它们的大部分信息都被移动到了专门的章节中。

着色(Tinting)

某些方块,比如草地或树叶,会根据它们的位置和/或属性动态改变其纹理颜色。模型元素 可以在其面上指定着色索引(tint index),这样颜色处理器就可以对相应的面进行处理。在代码层面,这一机制通过三个事件实现:一个用于方块颜色处理器(block color handlers),一个用于基于生物群系(biome)的方块着色(与方块颜色处理器配合使用),还有一个用于物品着色源(item tint sources)。它们的工作方式非常类似,我们先来看一个方块处理器的例子:

// 客户端模组总线事件处理器
@SubscribeEvent
public static void registerBlockColorHandlers(RegisterColorHandlersEvent.Block event) {
// 参数分别为方块的状态、方块所在的世界、方块的位置以及色彩索引(tint index)。
// 世界和位置参数可能为 null。
event.register((state, level, pos, tintIndex) -> {
// 用你自己的算法替换这里。可参考 BlockColors 类获取原版实现。
// 颜色采用 ARGB 格式。通常,如果色彩索引为 -1,表示不应进行着色,应该使用默认值。
return 0xFFFFFFFF;
},
// 这里是要应用着色的方块,可变参数形式
EXAMPLE_BLOCK.get(), ...);
}

以下是一个色彩解析器(color resolver)的示例:

// 客户端模组总线事件处理器
@SubscribeEvent
public static void registerColorResolvers(RegisterColorHandlersEvent.ColorResolvers event) {
// 参数分别为当前生物群系(biome)、方块的 X 坐标、方块的 Z 坐标。
event.register((biome, x, z) -> {
// 用你自己的算法替换这里。可参考 BiomeColors 类获取原版实现。
// 颜色采用 ARGB 格式。
return 0xFFFFFFFF;
});
}

关于物品着色(item tinting),请参见 相关的客户端物品文章章节

注册额外模型(Registering Additional Models)

有些模型并不直接关联到某个方块或物品,但在其它场景下依然需要(例如 方块实体渲染器),可以通过 ModelEvent.RegisterAdditional 进行注册:

// 客户端模组总线事件处理器
@SubscribeEvent
public static void registerAdditional(ModelEvent.RegisterAdditional event) {
// 模型 ID,相对于 `assets/<namespace>/models/<path>.json`
event.register(ResourceLocation.fromNamespaceAndPath("examplemod", "block/example_unused_model"));
}