闪烁的灯光
通用工作流程
闪烁的光源对象由多个组件组成。
Object Type |
命名模板 |
说明 |
|---|---|---|
| Base RendInst | industrial_lamp_steel_wall_a.lod**.dag | 这是用作创建闪烁灯的基础的模型。在某些情况下,它可能不是必需的,特别是当您从头开始设计具有内置闪烁功能的灯时。 |
| RendInst without Emissive | industrial_lamp_steel_wall_a_base.lod**.dag | 对象的分离部分,没有任何自发光属性,导出为单独的渲染实例。
这对于以下各项是必需的:
简单地说,当渲染实例被销毁时,动态模型会消失,光源会被移除,渲染实例会通过析构函数分解。 |
| DynModel with Emissive | industrial_lamp_steel_wall_a_flicker_dynmodel.lod**.dag | 整个模型的分离部分,使用动态发光着色器导出。从本质上讲,这是会发光和闪烁的部分。 |
| AnimChar | industrial_lamp_steel_wall_a_flicker_char.animChar.blk | 一个简单的 .blk 文件,其中包含对动态模型及其骨架的引用。从技术上讲,这是必要的,因为我们不能将动态模型直接放置在地图上,因为它不是静态对象。但是,可以放置 animChar。
例如:
|
| GameObj (Flickering Light) | industrial_lamp_steel_wall_a_flicker_8m_light.gameObj.blk | 一个 .blk 文件,其中包含 |
| GameObj (Flickering DynModel) | industrial_lamp_steel_wall_a_flicker_8m_mesh.gameObj.blk | 一个 .blk 文件,其中包含 |
| Composite | industrial_lamp_steel_wall_a_flicker_8m_cmp.composit.blk | 此 composite.blk 文件包括:
|
| 闪烁和光源模板
(所有模板都位于 |
industrial_lamp_steel_wall_a_flicker_8m_template | 闪烁模板。定义闪烁参数。 |
| industrial_lamp_steel_wall_a_flicker_8m_light | 闪烁光源模板。将光源链接到闪烁行为(您可以使用现成的光源或制作自己的光源)。该文件与 industrial_lamp_steel_wall_a_flicker_8m_light.gameObj.blk 文件同名。 | |
| industrial_lamp_steel_wall_a_flicker_8m_mesh | 闪烁的动态模型模板。将动态模型链接到闪烁行为(通过 AnimChar)。 该文件与 industrial_lamp_steel_wall_a_flicker_8m_mesh.gameObj.blk 文件同名。 |
Important
请注意文本中突出显示的文件名后缀,例如: industrial_lamp_steel_wall_a_**flicker_8m_light**. 请为您的文件和模板遵循相同的命名约定。
使用几何体
对于闪烁的光源,视觉模型必须分为两部分: Render Instance 和 Dynamic Model。原因已经概述:
Shadow Casting:
静态模型和动态模型的光源的阴影投射在 光源模板 中单独启用。虽然静态对象的阴影会影响性能,但影响并不那么明显。 但是,动态模型的阴影在计算上非常昂贵。这就是它们很少使用的原因。如果将整个灯具制作成动态模型,则其内部的光源不会在灯具上投下阴影。
Destruction:
渲染实例在销毁时被替换为可破坏版本. 这是一个简单的机制。相比之下,用损坏的版本替换整个灯动力学模型涉及一个新的、更复杂的管道,这并不实用。因此,我们将动态模型与渲染实例一起销毁。在这种情况下,动态模型将直接消失,并且被销毁的渲染实例将替换为动态模型部分的损坏版本,并在必要时断开。
Important
如果您正在创建稀有灯,这些灯将放置在地图上的大约 10 个位置,并且需要始终闪烁,请按照本文中概述的管道进行作。
如果要创建将在整个地图中广泛使用的灯,并且只有少数灯需要闪烁,请遵循以下方法:
为大多数放置创建具有自发光属性的标准渲染实例。
单独使用当前管道创建闪烁的灯。
例如,对于当前灯,您将有两个不同的对象:
industrial_lamp_steel_wall_a_on.lod**.dag– 持续亮起的灯的渲染实例。industrial_lamp_steel_wall_a_flicker_8m_cmp.composit.blk– 闪烁灯的合成文件。
此处使用的示例是灯industrial_lamp_steel_wall_a:

RendInst + DynModel (几何体分割)
渲染实例和动态模型之间的实际分割如下:
Dynamic Model: 包含灯泡和灯的一部分,该灯在纹理的 Alpha 通道中使用带有自发光强度遮罩的光照贴图。
Render Instance: 包括所有非自发光和投射有趣阴影的元素,例如保护灯泡网。虽然保护网可以是动态模型的一部分(因为它是被照亮的),但这会导致平坦、无趣的阴影。网络为阴影增加变化和深度。
Important
为了防止动态模型的矩阵和渲染实例之间的不同步,它们的枢轴点必须对齐(在导出到 .dag 文件之前在场景中正确定位)。在上图中,它们并排显示仅用于演示目的。
导出对象的命名
对于最初命名为industrial_lamp_steel_wall_a.lod**.dag的对象,split 渲染实例和动态模型应按如下方式命名:
RendInst:
industrial_lamp_steel_wall_a_base.lod**.dag– Non emissive base(非自发光基),其余部分将添加到该基底。Dynamic Model:
industrial_lamp_steel_wall_a_flicker_dynmodel.lod**.dag– 闪烁的动态模型。
Shaders
RendInst: 使用基于资产创建技术的标准着色器。
Dynamic Model: 使用动态自发光着色器,通常是 dynamic_emissive 着色器。
Destructions
如前所述,销毁仅适用于 render 实例。由于销毁动态模型更复杂,因此当关联的渲染实例被销毁时,只要动态模型和光源位于其边界框内,它们就会消失。
Important
光源和动态模型的“自动”销毁将仅在以下情况下发生:
它们的枢轴必须位于已销毁的渲染实例的边界框内。如果它们只是触碰边缘,则不会发生破坏。
必须在其模板中指定属性
destroyable_with_rendinst:tag{}。大多数光源 (99%) 从其基本模板继承此属性,因此通常不需要手动添加。但是,对于每个新的动态模型,您必须在模板中包含此属性,例如在industrial_lamp_steel_wall_a_flicker_8m_mesh中。
要正确配置析构,您只需:
为渲染实例创建标准
_destr。根据标准准则在
rendinst_dmg.blk中定义渲染实例析构。
Important
销毁渲染实例时,整个模型必须受到影响,这意味着销毁过程必须同时涵盖静态和动态部分。否则,动态模型将突然消失,在剩余渲染实例的几何体中留下间隙。
以下是正确的销毁过程:
Render Instance |
Dynamic Model |
Render Instance Dynamic Model Destruction |
Render Instance Dynamic Model Destruction DMG(optional) |
|---|
使用纹理和材质
一些关键注意事项:
自发光遮罩,存储在基于rendinst_emissive/dynamic_emissive着色器系统,则只能针对动态模型中包含的模型部分进行烘焙。渲染实例不支持闪烁。
因此,渲染实例不应使用自发光着色器,除非艺术设计特别要求(例如,在科幻设置中)。
请记住,闪烁的光源不考虑材质中的光色或自发光色。您必须手动调整自发光颜色以匹配所需的灯光颜色(如果要创建新灯光,则反之亦然)。它们之间没有自动同步。
除非艺术设计要求,否则请避免将彩色光烘焙到albedo纹理中。这样做将限制模型的自发光颜色选项(如果其他人希望将其与不同的颜色一起使用)。自发光效果的颜色和强度在 rendinst_emissive/dynamic_emissive 着色器设置。
因此,如果需要两个具有不同发射颜色(例如白色和红色)的相同灯,则必须创建两个具有不同自发光材质设置的单独动力学模型。如果自发光颜色被烘焙到albedo中,则无法做到这一点。
Be aware that the Asset Viewer does not accurately display emissive color and intensity. All testing should be done in-game. Do not rely on the Asset Viewer for accurate results.
配置 .folder.blk
如果您不确定系统如何处理.dag 文件以及区分动态模型和渲染实例,请参阅以下文档:
静态几何体处理
像往常一样,请遵循处理静态几何体的标准过程。唯一需要注意的是,如果您在 .folder.blk 的开头处理静态几何体,请确保 排除动态模型。否则,将导致它们被错误地处理。
例:
virtual_res_blk{
find:t="^(.*)\.lod00\.dag$"
exclude:t = "_destr\.lod00\.dag$"
exclude:t = "_dynmodel\.lod00\.dag$"
className:t="rendInst"
contents{
lod{range:r=12;}
lod{range:r=30;}
lod{range:r=80;}
allowProxyMat:b=yes
}
}
如果首先处理动态模型,则以后不需要排除(因为不会再次处理处理资源)。请记住删除不必要的 stopProcessing:b=false标志。
动态几何处理
在 Dagor Engine 的逻辑中,如果满足以下条件,则动态模型被视为动态模型:
它使用动态着色器。
它有一个骨架。
我们已经在材质中分配了动态着色器,所以现在我们需要创建骨架:
virtual_res_blk{ // 骨架创建块
find:t="^((.*)_dynmodel)\.lod00\.dag$" // 查找所有带有 _dynmodel 后缀的 LOD00
stopProcessing:b=false // 允许在下一个块中重新处理这些 .dag 文件
className:t="skeleton" // 将找到的资产视为骨架(提取数据以构建骨架资产)
name:t="$2_skeleton" // 使用动态模型名称 ($2) 和 _skeleton 后缀命名骨架
contents{ // 其他数据处理规则
addSkinNodes:b=yes
reduceNodes:b=yes
}
}
virtual_res_blk{ // 动态模型创建模块
find:t="^((.*)_dynmodel)\.lod00\.dag$" // 找到所有带有 _dynmodel 后缀的 LOD00 (由于前一个块的 stopProcessing:b=false)
stopProcessing:b=false // 这可能是一个多余的参数。
className:t="DynModel" // 将找到的资产作为动态模型进行处理(提取数据以构建动态模型资产)
name:t="$2_dynmodel" // 将动态模型命名为 $2_dynmodel(即带有 _dynmodel 后缀的动态模型名称)
contents{ // 其他数据处理规则
lod{range:r=12;} // LOD 距离
lod{range:r=30;}
lod{range:r=80;}
ref_skeleton:t="$2_skeleton" // 引用在上一个块中创建的骨架
}
}
Important
资产的命名可能会有一些混淆。我们处理带有_dynmodel后缀的对象,然后在 skeleton 和 dynamic model creation 模块中分配两个额外的后缀:
_skeleton_dynmodel
这可能会导致预期名称如下:
_dynmodel_skeleton_dynmodel_dynmodel
但是,Asset Viewer 显示正确的名称,而没有多余的_dynmodel。

这是由于 find:t="^((.*)_dynmodel)\.lod00\.dag$"语句中定义的搜索查询所致。
如果查询是 find:t="^(.*_dynmodel)\.lod00\.dag$",则整个动态模型名称(包括 _dynmodel)将被视为对象名称 ($2)。我们使用的查询确保只有最内部的组(即没有 _dynmodel 的核心对象名称)被视为对象名称。
碰撞处理
正如我们所知,冲突现在通过文件包含(如 include "#/develop/assets/_ri_collision_lod1.blk")来处理。默认情况下,此 include 也会影响动态模型,因为它不会排除它们。一种合乎逻辑的方法是首先包含动态模型碰撞块,但动态模型处理碰撞的方式不同——它们是通过损伤模型 (DM) 处理的。
因此,需要一种混合处理解决方案:
include "#/develop/assets/_ri_collision_lod1.blk" // 包括 RenderInst 碰撞处理。
"@override-last"{ // 覆盖包含文件中的参数。
"@override:find":t="^(.*)_dynmodel\.lod01\.dag$" // 查找专门用于动态模型的 LOD01。
"@override:contents"{gameResPack:t="game_logic.grp"; defCollidable:b=no;} // 为动态模型碰撞设置装配体参数。
stopProcessing:b=no // 这可能是一个多余的参数。
}
include "#/develop/assets/_ri_collision_lod1.blk" // 重复 RenderInst 碰撞处理 include。
这种混合方法可确保渲染实例和动态模型 在碰撞管道中得到适当处理。
AnimChar
从技术上讲,我们不能直接在地图上放置动态模型,也不能在我们需要的闪烁模板中使用它。但是,我们可以使用 animChar(动画角色)来实现这一点。尽管名称抽象,但它允许我们有效地管理动态资源。
实质上,animChar 文件列出了应应用于特定动画模型的动态资源(闪烁的灯光只是动画的另一种形式)。
例如,industrial_lamp_steel_wall_a_flicker_char.animChar.blk包含以下两行:
dynModel:t="industrial_lamp_steel_wall_a_flicker_dynmodel" // 动态模型
skeleton:t="industrial_lamp_steel_wall_a_flicker_skeleton" // 关联的骨架
将 animChar 文件放在动态模型旁边,以模型命名,后缀为_char.animChar.blk。不需要额外的.folder.blk处理。
GameObjects
Game Objects 本质上是与相关模板同名的占位符、容器或虚拟对象。 它们用于在环境中定位对象或将其添加到模板合成中。游戏对象提供触发声音 (SFX)、视觉效果 (VFX)、游戏触发器和光源等效果所需的矩阵信息。
通常,游戏对象与其他游戏对象一起存储在公共目录中。 例如,在基于 daNetGame 的项目中,它位于:
/<project_name>/develop/assets/common/gameRes/gameObjects/
我们需要以下内容:
industrial_lamp_steel_wall_a_flicker_8m_light.gameObj.blk– 此游戏对象表示闪烁的光源(半径为 8 米),并将作为光源放置在地图上。在.blk文件中,定义:volumeType:t="point"
industrial_lamp_steel_wall_a_flicker_8m_mesh.gameObj.blk– 此游戏对象表示闪烁的动态模型,并将作为动态对象放置在地图上。在.blk文件中,定义:volumeType:t="point" ref_dynmodel:t="industrial_lamp_steel_wall_a_flicker_dynmodel"
Important
确保引用正确的动态模型;否则,可能会加载不正确的资源。
Composite Object
要将所有内容都放置在地图上,您需要创建一个复合对象,其中包括:
基础渲染实例
闪烁的灯光游戏对象
闪烁的 Dynamic Model 游戏对象
不要忘记根据灯的配置调整光源的方向(通常,灯沿 X 轴指向侧面)。 此外,为了获得最佳的视觉效果,请在基于 daNetGame 的项目中使用 光度光源。
闪烁灯的示例合成文件:
className:t="composit"
node{
name:t="industrial_lamp_steel_wall_a_base:rendInst"
tm:m=[[1, 0, 0] [0, 1, 0] [0, 0, 1] [0, 0, 0]]
}
node{
name:t="industrial_lamp_steel_wall_a_flicker_8m_mesh:gameObj"
tm:m=[[1, 0, 0] [0, 1, 0] [0, 0, 1] [0, 0, 0]]
}
node{
name:t="industrial_lamp_steel_wall_a_flicker_8m_light:gameObj"
tm:m=[[0.961074, 0.27629, 0] [-2.08593e-08, 7.25591e-08, 1] [0.27629, -0.961074, 7.54979e-08] [0.624191, -0.270539, 0.0204315]]
}
浅色和闪烁模板
闪烁源由模板定义,类似于光源模板,并存储在<project_name>/prog 目录下的lights.blk文件中。例如:
<project_name>/prog/gameBase/content/common/gamedata/templates/lights.blk
这些模板通常扩展或使用位于”global” prog目录中的light_flicker.blk中的基本模板:
/prog/daNetGameLibs/light_flicker/templates/light_flicker.blk
这些模板使用 rendinst_emissive/dynamic_emissive 着色器。
通常,三个模板涵盖 99% 的情况,并且它们遵循特定的顺序。以我们现在的灯为例:
industrial_lamp_steel_wall_a_flicker_8m_template– 定义闪烁参数(频率、暂停、发射强度等)的闪烁模板。industrial_lamp_steel_wall_a_flicker_8m_light– 闪烁光源模板,用于将光源(现有光源或自定义光源)链接到上面定义的闪烁行为。industrial_lamp_steel_wall_a_flicker_8m_mesh– 闪烁的灯模板,它通过 animChar 将闪烁模板链接到动态模型。
这些模板之间的关系如下:
闪烁模板链接到:
闪烁的灯光模板。
闪烁的动态模型模板。
您并不总是需要从头开始创建新模板。如果您有合适的闪烁模板,则可以通过将它链接到所需的光照和动态模型来重用它。但是,每次都需要重新创建闪烁的灯模板(用于动态模型),因为它使用特定的 animChars。
闪烁和闪烁的灯光模板可以在各种组合和场景中重复使用。
Caution
所有模板都以其所针对的灯命名。可以重复使用模板,但此命名方案可能会导致混淆。由您决定是从头开始重新创建所有模板还是重用现有模板(尽管它们可能以其他对象命名)。
闪烁模板
Important
闪烁的随机化设置将同步应用于所有相同的灯。这意味着,如果您将两个相同的灯彼此相邻放置,它们将随机但同步闪烁!每个灯看起来都非常艺术,但同步闪烁可能几乎在所有情况下都不可取。
如果需要将多个相同的闪烁灯放在很近的位置,请创建多个闪烁模板(和相应的模板)以及多个合成,然后随机放置它们。
让我们回顾一下当前灯的闪烁模板
(<project_name>/prog/gameBase/content/common/gamedata/templates/lights.blk):
industrial_lamp_steel_wall_a_flicker_8m_template{
_use:t="light_flicker_with_sparks"
light_flicker__attack_time:p2 = 0.01, 0.15 // 从 “off” 到 “on” 的过渡时间
light_flicker__on_time:p2 = 1, 10 // “on” 状态的持续时间
light_flicker__release_time:p2 = 0.75, 1.25 // 从“on”到“off”的过渡时间
light_flicker__off_time:p2 = 0.01, 6 // “关闭”状态的持续时间
light_flicker__on_brightness:p2 = 1.0, 1.6 // “on” 状态下的亮度乘以 light__brightness
light_flicker__off_brightness:p2 = 0.0, 0.2 // “关闭”状态下的亮度乘以 light__brightness
light_flicker__noise_brightness_on:p2 = 0.5, 1.0 // “on”状态下的噪声幅度乘法器
light_flicker__noise_brightness_off:p2 = 0.0, 1.0 // “关闭”状态下的噪声幅度乘数
light_flicker__noise_time:r = 17.0 // 噪声频率(每秒)
}
此模板扩展了根模板_use:t="light_flicker_with_sparks",其中包含其他参数,包括火花的设置(在VFX 部分中介绍)。
了解 flicker 参数配置的关键是每个参数都有最小值和最大值,并且每个周期都会选择两者之间的随机值。这允许您创建均匀和高度随机的闪烁模式。
总体而言,闪烁效果由以下参数描述,我们将在下面详细探讨。

循环元素
light_flicker__attack_time:p2 = 0.01, 0.15: 光源从 “off” 转换为 “on” 状态所需的时间。光源点燃的时间(以秒为单位)。使用这些参数,每个新周期将需要0.01到0.15秒。light_flicker__on_time:p2 = 0.01, 0.5: “on” 状态的持续时间。光源将保持亮起的时间(以秒为单位)。light_flicker__release_time:p2 = 0.25, 0.75: 光源从 “on” 状态过渡到 “off” 状态所需的时间。光源淡出的时间(以秒为单位)。light_flicker__off_time:p2 = 0.01, 4: “off” 状态的持续时间。光源将保持关闭的时间(以秒为单位)。
亮度控制
light_flicker__on_brightness:p2 = 0.6, 1.0: “on” 状态下的亮度乘数。在灯光启用时乘以基础光源或自发光着色器的亮度。light_flicker__off_brightness:p2 = 0.0, 0.1: “off” 状态下的亮度乘数。当灯光关闭时,乘以基础光源或自发光着色器的亮度。
附加微噪声
light_flicker__noise_brightness_on:p2=0.25,1.0: 当灯光 “开启” 时低/高噪声振幅的乘数。根据light_flicker__on_brightness乘以“on”状态下的微闪烁效果。light_flicker__noise_brightness_off:p2=0.0,1.0: 当灯光 “关闭” 时低/高噪声振幅的乘数。根据light_flicker__off_brightness乘以“关闭”状态下的微闪烁效果。light_flicker__noise_time:r=50.0: 噪声频率(每秒)。微闪烁的频率。此值是确定性的,不涉及随机性。
VFX
我们可以从各种基本模板中进行选择,这些模板在我们的实现中进行了扩展。示例包括:
_use:t="light_flicker": 没有额外效果的基本模板。_use:t="light_flicker_with_sparks": 添加火花和音效,适用于室内灯具。_use:t="light_flicker_with_sparks_nightly": 仅在夜间添加火花和声音效果,这适用于室外灯光。
火花将出现,如下所示:

可以使用参数 light_flicker__sparksEffectSpawnChance:r=0.3 覆盖出现火花的几率。
其他设置嵌入在全局程序的基本模板 light_flicker.blk 中。默认情况下,使用envir_sparks_burst_tiny_smoke VFX,但未来的更新将允许自定义 VFX。
闪烁光源模板(光源)
例如,考虑industrial_lamp_steel_wall_a_flicker_8m_light:
industrial_lamp_steel_wall_a_flicker_8m_light{
_use:t="spot_light_little_b"
_use:t="light_flicker_updater_light"
light_flicker_updater__template:t="industrial_lamp_steel_wall_a_flicker_8m_template"
}
此模板包括:
_use:t="spot_light_little_b": 继承光源。但是,您可以根据需要覆盖光源参数。例如:light__max_radius:r=7 light__color:c=208, 191, 152, 255 light__brightness:r=121 light__nightly:b=no
_use:t="light_flicker_updater_light": 闪烁光源模板的必需参数。同步闪烁效果。light_flicker_updater__template:t="industrial_lamp_steel_wall_a_flicker_8m_template": 指向上一节中的闪烁设置模板。
Important
关于 _use:t="spot_light_little_b"
建议为每个新灯创建一个唯一的光源。此方法消除了在模板中覆盖的需要。在尝试修改特定光源的设置时,将扩展光源相互叠加可能会产生问题。您需要确保没有其他光源在扩展它。
或者,您可以完全在当前模板中定义光源,而不是扩展光源。但是,在这种情况下,光源将始终与闪烁的模板相关联。通常,闪烁光源用于为非闪烁光源添加变化。例如,在具有多个相同灯的走廊中,只有一些灯闪烁。对这两种变体使用单个参考光源是有意义的。
闪烁动态模型模板
例如,考虑 industrial_lamp_steel_wall_a_flicker_8m_mesh:
industrial_lamp_steel_wall_a_flicker_8m_mesh{
_use:t="light_flicker_updater_mesh"
animchar__res:t="industrial_lamp_steel_wall_a_flicker_char"
light_flicker_updater__template:t="industrial_lamp_steel_wall_a_flicker_8m_template"
"destroyable_with_rendinst:tag" {}
}
此模板包括:
_use:t="light_flicker_updater_mesh": 闪烁动态模型模板的必需参数。同步闪烁效果。animchar__res:t="industrial_lamp_steel_wall_a_flicker_char": 指定模型的动画角色。这有效地将闪烁效果传输到动态模型。light_flicker_updater__template:t="industrial_lamp_steel_wall_a_flicker_8m_template": 指向我们的闪烁设置模板。"destroyable_with_rendinst:tag" {}: 指定如果动力学模型的枢轴与已销毁的渲染实例的边界框相交,则动力学模型应消失。
Note
动态模型的所有自发光设置(可能颜色除外)都将被闪烁模板(industrial_lamp_steel_wall_a_flicker_8m_template).中的参数覆盖