# 着色器: rendinst_interior_mapping ## 概述 `rendinst_interior_mapping`着色器的开发是为了通过将内部立方体贴图投影到平面或盒子上来模拟大型窗口(和大量窗口)的内部。此着色器使用绘制的立方体贴图创建“玻璃后面”内部的错觉。玻璃上的反射可以从定制的立方体贴图或每次加载贴图时生成的环境立方体贴图进行模拟。 ## 通用参数 常用参数: - `script:t="fadeout=50, 100, 100, 200"` – Cubemap 淡化设置。前两个参数控制内部淡化,而后两个参数控制外部淡化。 - `script:t="fade_color=0.188, 0.224, 0.259, 0"` – 立方体贴图淡化期间的玻璃颜色,使用十进制值以 RGB 格式指定。 - `script:t="room_depth=1"` – 设置远墙的深度,允许将其推回以创建更大空间的错觉。 - `script:t="tile=1, 1, 1, 0"` – 控制内部立方体贴图的平铺。 此参数可用于在单个平面上创建多个房间。 - `script:t="room_size=2, 1, 0, 0"` – 定义窗口(及其后面的房间)的比例,因为房间通常与窗口的宽度和高度“匹配”)。 - `script:t="tile_space=1,1,0,0"` – 在窗口之间创建空间。前两个组件控制平铺,而后两个组件控制偏移。 - `script:t="tile_space_color=0.58,0.216,0.62,0,1"` – 定义窗口之间空间的颜色(前三个组件)和这些空间中的反射强度(第四个组件)。 - `script:t="room_selfillum=0.4"` – 控制内部的自发光。 - `script:t="illum_random=3"` – 调整内部照明的随机性。 - `script:t="illum_only_at_night=1"` – 仅在夜间启用照明。 - `script:t="convexity_slope=-0.07,0.07,2,2"` – 前两个组件控制玻璃的凹/凸度,而后两个组件调整玻璃在水平轴和垂直轴上的旋转。 - `script:t="contortion_tiling=1,1,1,1"` – 折射的平铺。前两个组件控制平铺宽度/高度,第三个组件控制最左侧磁贴的宽度,第四个组件控制底部磁贴的高度。 - `script:t="smoothness_metalness_reflection=0.5, 0.5, 1.5, 0"` – 指定平滑度、金属度和反射的值。 基于 *daNetGame* 的特定参数: - `script:t="shadow_caster=0"` – 使用此着色器禁用玻璃的阴影投射。默认情况下,它设置为 `1`(启用投射阴影)。 ## 资产要求 让我们考虑一下允许使用着色器的所有程序参数的标准要求。非标准功能将在本文末尾单独讨论。 1. 映射坐标应与资源的坐标匹配,即其 top-bottom-left-right 应对应于映射上的 top-bottom-left-right。
2. 无论窗口的比例如何,映射都必须是 “texture” 展开中的完整正方形。 3. 立方体贴图应按以下格式创建: - 1 – 左 - 2 – 右 - 3 – 顶部(旋转 180 度) - 4 – 底部(旋转 180 度) - 5 – 正面。对于内部立方体贴图,此侧应为黑色。 - 6 – 远墙。
4. 立方体贴图应以 `.tif` 格式保存。 ```{note} 在基于 *daNetGame* 的项目中,可以使用控制台命令`screencap.take_screenshot_360`创建立方体贴图。 结果将保存在 `/game/Screenshots` 目录中的 6 张图片,然后可以根据第 3 点的模板进行组合。 ``` ## 着色器设置 ### 纹理 着色器使用一个或两个纹理。 1. 第一个插槽用于内部立方体贴图(强制性纹理)。模拟玻璃后面的内部。 2. 第三个插槽用于外部立方体贴图(可选纹理)。模拟外部环境,最适合在较低楼层使用。在较高的楼层,这可能不起作用,因为立方体贴图中的对象可能会显得不成比例地大。对于较高的楼层,建议不要指定此纹理,在这种情况下,将使用环境立方体贴图。 ### 参数 #### 立方体贴图淡入淡出 1. `script:t="fadeout=50, 100, 100, 200"` – 控制立方体贴图淡入淡出。前两个参数影响内部,后两个参数影响外部。对于每个立方体贴图,第一个参数指定淡化开始的距离,第二个参数指定淡化完成的距离。 2. `script:t="fade_color=0.188, 0.224, 0.259, 0"` – 设置立方体贴图淡化期间的玻璃颜色。颜色使用十进制值以 RGB 格式指定。例如,RGB 颜色 `48, 57, 66` 将除以 255 得到 `0.188, 0.224, 0.259`。第四个参数未使用。 #### Smoothness, Metalness, 和 Reflection `script:t="smoothness_metalness_reflection=0.5, 0.5, 1.5, 0"` – 此参数直接设置平滑度、金属度和反射值。 #### 房间比例和平铺 ##### 房间深度 `script:t="room_depth=1"` – 设置远处墙壁的深度,允许将其向后移动以创建更大空间的错觉,或将其移近以模拟玻璃后面的窗帘。 ##### 内部立方体贴图平铺 `script:t="tile=1, 1, 1, 0"` – 控制内部立方体贴图的平铺,允许使用以下参数在单个平面上创建多个房间: - 前两个组件分别设置水平和垂直平铺。 - 第三个组件随机化立方体贴图旋转 (`0`/`1` 值)。 **它是如何工作的? 1. 将表面(即使是矩形)映射到方形纹理(每个 UV 1 个平铺)以实现以下效果:
2. 将水平平铺值设置为 `3` 以创建三个房间:
3. 将第三个组件设置为 `1` 以实现每个房间的随机立方体贴图旋转:
##### 房间大小 `script:t="room_size=2, 1, 0, 0"` – 设置窗口的比例(以及它后面的房间,因为房间通常与窗户的宽度和高度匹配)。 前两个组件分别控制 width 和 height。这些值可以采用任意单位,因为它们表示比例,但使用单位值更简单。 让我们使用上面的示例来检查它是如何工作的: 1. `script:t="room_size=1, 1, 0, 0"` – 为了进行测试,窗口的 width 和 height 设置为相等。这会导致 rooms 向中心弯曲:
2. 模型的宽度是其高度的两倍,因此将相应的值设置为 `script:t="room_size=2, 1, 0, 0"`:
现在,一切都按比例正确。 ```{important} 这也带来了一个挑战 - 您不能将相同的材料应用于不同比例的窗户。该示例使用平行六面体,并且具有当前材质的侧面部分看起来不正确:
``` ##### 窗口之间的间距 `script:t="tile_space=1,1,0,0"` – 此参数允许改变窗户之间的间距,这对于窗户间距不对称的建筑物非常有用。 前两个组件分别控制 X 和 Y 间距(尽管必须指定所有组件)。 1. 默认情况下,值设置为`script:t="tile_space=1,1,0,0"`:
2. 增加这些参数将减小相同区域内窗口的大小(窗口相对于其中心收缩): `script:t="tile_space=2,2,0,0"`
3. `script:t="tile_space=5,2,0,0"`
4. `script:t="tile_space=5,2,0.5,0"`
5. `script:t="tile_space=5,2,0.5,0.5"`
使用此参数涉及: 1. 计算窗户打开的数量。 2. 使用`script:t="tile=1, 1, 1, 0"`设置适当的窗口平铺。 3. 使用此参数调整窗口之间的间距。 ##### 窗口之间的间距颜色 `script:t="tile_space_color=0.58,0.216,0.62,0.1"` – 使用前三个组件设置窗口之间间距的颜色。第四个组件控制这些空间的反射强度。
#### 窗户光照参数 用于控制内部立方体贴图的光照的参数。使窗口发光的功能是通过两个参数实现的: - `script:t="room_selfillum=0.4"` – 控制自发光。该值的范围可以从 0 到任何所需的数量。 - `script:t="illum_random=3"` – 控制照明的随机性。该值表示照明状态的数量 – 数字越高,种类越多。 照明的淡化速度比内部立方体贴图本身慢。这是根据函数 `(1 - 0.8*distFade)`发生的,其中`distFade`计算为`(distance to glass)/(interior cubemap fade distance)`,但永远不会超过`1`。因此,最小照度是`1-0.8=0.2`,而不是`0`,因为从技术上讲,不可能平滑地将照度淡化到`0`——它总是会截断。因此,保留了最低限度的光线。 - `script:t="illum_only_at_night=1"` – 仅在夜间启用照明。 ```{important} 应为应亮起的所有事物指定此参数,但白天需要光照的极少数情况除外。 ``` #### 玻璃变形参数 ##### 玻璃变形 您可以设置玻璃扭曲(凸度/凹度)和旋转(在水平和垂直平面上),以在玻璃上创建不同的反射和阳光闪烁。 `script:t="convexity_slope=-0.07,0.07,2,2"` 其中: - 前两个组件定义玻璃的最大凹度(远离观察者)和凸度(朝向观察者)。指定范围内的随机值将添加到玻璃法线。通常,这些值小于 `1` (范围从百分之一到十分之一) ,应在特定窗口上进行测试。较大的全景窗口需要较小的值,而较小、不太常见的窗口可以处理较大的值。从本质上讲,这设置了失真的 “锐度” – 值越大,失真的中心就越明显。扭曲中心的位置在玻璃表面上是随机的。 - 第三个和第四个组件分别控制玻璃在水平和垂直平面上的旋转。此旋转也会添加到玻璃法线,并以度为单位指定。这些值表示绝对最大值/最小值(例如,值为 2 时,范围为`|2|`,表示介于 -2 和 +2 之间)。与失真一样,在此范围内选择一个随机值。 例如,设置 10 度旋转将在 -10 和 +10 之间随机化。 让我们看一些例子。在下图中:左 – 法线贴图,右 – 结果。 1. 所有失真参数均设为零:
2. `script:t="convexity_slope=-0.03,-0.03,0,0"` 由于值较小,法线贴图显示的变化很小,但反射表现出明显的失真。
3. `script:t="convexity_slope=0,0,10,0"` 水平旋转在法线贴图上略微明显。
4. `script:t="convexity_slope=0,0,0,10"` 垂直旋转在法线贴图上也很明显。
5. `script:t="convexity_slope=-100,100,0,0"` 使用极其夸张的值来说明失真的性质。 (另请注意,扭曲中心不在窗口的中心 - 每个窗口图块上都有一个程序偏移。
6. `script:t="convexity_slope=-0.03,0.3,10,10"` 具有失真的“分布式”窗口示例:
无失真的 “分布式” 窗口示例:
7. `script:t="convexity_slope=-100.03,100.3,100,100"` 具有夸大值的 “分布式” 窗口示例 – 演示偏移和值选择的随机性。

由于这种技术,建筑物窗户上的不同反射。 立方体贴图上的可见平铺接缝 – 在窗口上可见的法线贴图接缝。
### 失真平铺 在实践中,基本的窗户平铺通常是不够的。内部可能由一个“房间”组成,但窗框可能有多个玻璃板,每个玻璃板都需要以不同的方式反射光线。

The current area of a single reflection

The desired area of a single reflection

为此,请使用参数`script:t="contortion_tiling=1,2,1,1"`,其中: - 第一个组件控制扭曲的水平平铺。 - 第二个组件控制扭曲的垂直平铺。 - 第三个组件设置最左侧扭曲图块的宽度(作为窗口的分数)。
- 第四个组件设置最左侧较低扭曲图块的高度(作为窗口的分数)。
对于给定的窗口示例: - 水平平铺设置为`2`(表示 2 个玻璃板)。 - 垂直平铺也设置为`2`(表示 2 块玻璃)。 - 最左侧磁贴的宽度设置为`0.5`(窗口宽度的一半)。 - 底部图块的高度设置为 `0.65` (大约是窗口总高度的三分之二)。 因此,`script:t="contortion_tiling=2,2,0.5,0.65"`。此配置可确保每个玻璃窗格都有其独特的变形(在 *Asset Viewer* 中,它不是那么明显,但在游戏中,由于窗口上的反射,差异很大)。
```{important} - 第三个组件指定 **仅** 最左侧磁贴的宽度。所有其他图块将保持均匀的比例宽度。
- 第四个组件指定所有底部磁贴的高度,这意味着它会影响整个窗口。
- 因此,在程序上创建具有单个通风口的窗口是不可行的 - 每种可能的配置都需要额外的参数。 ``` ## 非标解决方案 ### 模拟大空间 根据资产要求,窗口应严格映射到方形纹理内。但是,这种映射会导致玻璃后面的房间与窗户的边缘完美对齐。如果我们想增加玻璃后面的空间,我们需要减少映射。 通过减少映射,玻璃后面的空间会显得更大。天花板、墙壁和地板被推得更远,给人一种房间比窗户大得多的印象。

Standard mapping

Reduced mapping

我们需要证明单个房间位于三个独立的窗户后面。使用默认映射时,您最终会得到三个窗口,每个窗口都显示自己的房间。通过拆分映射,您可以获得一个通过所有三个窗口可见的单个大房间。

Standard mapping

Split mapping

在前面的示例中,房间变成了一个巨大的机库,因为我们按比例减少了窗户映射。 为避免这种情况,请执行以下作: 1. 不按比例缩放映射。 2. 使用`room_size=2, 1, 0, 0`参数补偿非比例映射。

Split mapping

Compensated mapping

```{note} 默认情况下,我们使用此参数来强调几何图形的比例 - 如果宽度是高度的两倍,则设置 `room_size=2, 1`。但是,在我们的示例中,几何图形是正方形的,这意味着参数应为 `room_size=1,1`。但是我们将映射的宽度减小到大约高度的一半,因此我们通过将宽度设置为`2`和高度设置为`1`来进行补偿。在这种情况下,较小的映射端对应于较大的参数值。 ``` ### 单个窗口中的随机旋转 我们有一个用于向平铺立方体贴图添加随机性的参数:`script:t="tile=1, 1, 1, 0"`。当您有一个较大的窗口区域并在其中按程序平铺多个房间时,此选项将起作用。但是,通常情况下,每个窗口都是单独的几何体。出现两种主要情况: - 每个窗口都是单个`.dag`中的单独几何体。 - 每个窗口都是一个单独的`.dag`由合成放置在建筑物上。 让我们考虑这两种情况。 #### 窗口作为 .dag 中的单独几何体 默认情况下,在启用窗口和随机性的情况下导出`.dag`不会显示任何差异 - 所有窗口都将以相同的方式映射。但是,当对象在地图上移动时,映射将移动,但会均匀移动。

One object

A composite of three objects

随机性有效,但它有缺陷——一切都太相似了。要解决此问题,您需要手动调整每个窗口的映射。相同的映射位置越少,您实现的随机性就越高。 在垂直和水平方向上调整映射。这可以通过插件按程序完成;关键是将映射保持在纹理 “cells” 的边界内。 ```{note} 最好垂直移动相邻窗口,而不是水平移动相邻窗口。 这提高了随机性效果。 ```

One object

A composite of three objects

这里的差异可能并不明显(立方体贴图太均匀),但每个部分的所有内容都是随机旋转的。让我们替换立方体贴图以获得更好的可见性。 #### 窗口作为单独的 .dag,由合成放置 尽管情况不同,但解决方案保持不变。 在前一种情况下,在标准映射上启用随机性以分组方式工作 - 当对象移动时,所有窗口同时更改映射(因为窗口是一个大`.dag` 的一部分)。在这种情况下,同样的事情会发生,但发生在单个窗口上。窗口的放置和映射更加频繁。(让我们提前设置一个带有窗帘的立方体贴图,以便更好地看到差异。

One object

A composite of three objects

请注意,窗口具有相同的随机性,并且相对于零的偏移相同(底部的中心窗口)。(例外:左中间的窗口 - 因为一些 “魔法”)。 要避免这种情况,您可以: - 将随机性值设置为不同的 **奇数** (它不适用于偶数)。例如,将其设置为 `3` (`script:t="tile=1, 1, 3, 0"`):
- 或者移动窗口映射(我发现效果更好)。