自定义渲染纹理是一种特殊类型的纹理,通过它可以使用着色器更新纹理。它们是渲染纹理的扩展。可以使用自定义渲染纹理创建复杂的模拟,如焦散、雨水效果的波纹模拟和液体喷溅。
自定义渲染纹理功能提供脚本和着色器框架,以协助进行复杂的配置,如改变更新频率、部分或多通道更新。
若要使用此框架,需要向自定义渲染纹理资源分配材质。自定义渲染纹理需要兼容的材质。有关更多信息,请参阅为自定义渲染纹理编写着色器。
若要将兼容材质分配给自定义渲染纹理资源,请执行以下操作:
此材质会根据其参数更新纹理的内容。
本页包含以下信息:
下表描述了自定义渲染纹理功能与每个渲染管线之间的兼容性:
功能 | 内置渲染管线 | 通用渲染管线 (URP) | 高清渲染管线 (HDRP) | 自定义可编程渲染管线 (SRP) |
---|---|---|---|---|
自定义渲染纹理 | 是 (1) | 是 (1) | 是 (1) | 是 (1) |
注意:
自定义渲染纹理 Inspector 窗口显示许多与渲染纹理 Inspector 相同的属性,以及一些特定于自定义渲染纹理的属性。
属性: | 功能: |
---|---|
Dimension | 渲染纹理的尺寸。 |
2D | 使渲染纹理成为二维。 |
Cube | 使渲染纹理成为立方体贴图。 |
3D | 使渲染纹理成为三维。 |
Size | 渲染纹理的大小(以像素为单位)。 |
Color Format | 渲染纹理的格式。 |
sRGB (Color Render Texture) | 启用可允许渲染纹理使用 sRGB 读/写转换(只读)。 |
Enable Mip Maps | 启用此属性可允许渲染纹理使用 Mipmap。 |
Auto generate Mip Maps | 启用此属性可自动生成 MipMap。 |
Wrap Mode | 定义纹理平铺时的行为方式。 |
Repeat | 纹理以瓦片形式重复自身。 |
Clamp | Unity 会拉伸纹理的边缘。 |
Filter Mode | 定义当纹理在通过 3D 变换拉伸时 Unity 如何过滤纹理。 |
Point | 纹理在靠近时变为块状。 |
Bilinear | 纹理在靠近时变得模糊。 |
Trilinear | 与 Bilinear 类似,但纹理也在不同的 Mip 级别之间模糊。 |
Aniso Level | 以大角度查看纹理时提高纹理质量。适用于地板和地面纹理。 |
这些属性是自定义渲染纹理独有的。自定义纹理参数分为三个类别:
属性: | 功能: |
---|---|
Material | Unity 用于更新自定义渲染纹理的材质。 |
Shader Pass | Unity 用于更新自定义渲染纹理的着色器通道。下拉列表会显示材质中可用的所有通道。 |
Initialization Mode | Unity 初始化纹理的频率。 |
OnLoad | Unity 在创建时初始化纹理一次。 |
Realtime | Unity 在每一帧初始化纹理。 |
OnDemand | Unity 通过脚本按需初始化纹理。 |
Source | Unity 纹理如何初始化纹理。 |
Texture and Color | Unity 使用纹理叠加颜色来初始化纹理。 |
Initialization Color | 定义 Unity 用于初始化自定义渲染纹理的颜色。如果还提供了初始化纹理,则 Unity 会使用颜色和纹理的叠加来初始化自定义渲染纹理。 |
Initialization Texture | 定义 Unity 用于初始化自定义渲染纹理的纹理。如果还提供了初始化颜色,则 Unity 会使用颜色和纹理的叠加来初始化自定义渲染纹理。 |
Material | Unity 使用材质初始化纹理。 |
Initialization Material | 定义 Unity 用于初始化自定义渲染纹理的材质。 |
Update Mode | 着色器更新自定义渲染纹理的频率。 |
OnLoad | 着色器在创建时更新纹理一次。 |
Realtime | 着色器在每一帧更新纹理。 |
OnDemand | 着色器通过脚本按需更新纹理。 |
Period | Unity 更新实时纹理的时间量(以秒为单位)。值 0.0 会更新每一帧。仅当 Update Mode 属性设置为 Realtime 时,此属性才可用。 |
Double Buffered | 对纹理进行双缓冲。每次更新都会交换两个缓冲区。这样可以在着色器中读取先前更新的结果。 |
Wrap Update Zones | 启用此属性允许部分更新区域包围纹理的边框。 |
Cubemap Faces | (仅限立方体贴图)通过一系列开关允许用户对每个立方体贴图面启用/禁用更新。 |
Update Zone Space | Unity 用于定义更新区域的坐标系。 |
Normalized | 所有坐标和大小都在 0 到 1 之间,左上角从 (0, 0) 开始。 |
Pixel | 所有坐标和大小都以像素宽度和高度所限制的像素表示。左上角从 (0, 0) 开始。 |
Update Zone List | 纹理的更新区域列表。有关更多信息,请参阅更新区域。 |
可以通过 Export 菜单将自定义渲染纹理导出到 PNG 或 EXR 文件(具体取决于纹理格式)。
Unity 更新自定义渲染纹理时,默认情况下会使用材质立即更新整个纹理。自定义渲染纹理允许定义部分更新的区域。可以使用此功能根据需要定义多个区域以及处理这些区域的顺序。
可以将更新区域用于各种用途。例如,可以使用多个小区域在纹理上绘制水滴,然后执行完整通道以模拟波纹。此外,如果不需要更新完整纹理,也可以使用此功能作为优化手段。
更新区域具有各自的属性集。Update Zone Space 会出现在显示中。坐标取决于纹理的 Dimension 属性:对于 2D 和立方体纹理为 2D,对于 3D 纹理为 3D。
属性: | 功能: |
---|---|
Center | 更新区域中心的坐标。 |
Size | 更新区域的大小。 |
Rotation | 更新区域的方向(以度为单位,3D 纹理中不可用)。 |
Shader Pass | 定义用于此更新区域的着色器通道。如果将此属性设置为默认值,则此更新区域会使用在检视面板主要部分中定义的着色器通道。否则,它会使用提供的着色器通道。 |
Swap (Double Buffer) | (仅适用于双缓冲纹理)启用了此属性时,Unity 在处理此更新区域之前会交换缓冲区。 |
可以在脚本 API 中访问大多数自定义渲染纹理功能。还可以使用脚本更改材质参数、更新频率、更新区域、请求更新等。
当 Unity 更新或初始化自定义渲染纹理时,它会使用当前属性来渲染下一帧。这种机制可保证使用此纹理的任何材质都具有最新结果。例如,在以下脚本中,Unity 使用第二个更新区域数组执行两次更新:
customRenderTexture.updateZones = updateZones1;
customRenderTexture.Update();
customRenderTexture.updateZones = updateZones2;
customRenderTexture.Update();
注意:Unity 不会在调用 Update()
或 Initialize()
的同时更新或初始化自定义渲染纹理。这是因为 Unity 始终在下一帧开始时更新和初始化自定义渲染纹理。
可以对自定义渲染纹理进行双缓冲。为此,请在自定义渲染纹理组件中启用 Double Buffered,或使用 CustomRenderTexture.doubleBuffered
。
双缓冲意味着在一个自定义渲染纹理内有两个纹理,Unity 可以在每次更新后交换它们。这种机制可让用户在自定义渲染纹理中写入新结果时读取上次更新的结果。
如果着色器需要使用 Unity 已在纹理中写入的内容但不能将值与经典混合模式混合,则双缓冲尤其有用。如果着色器必须对前一结果中的不同像素进行采样,也需要用到此功能。
性能警告:双缓冲当前涉及每次交换时进行纹理的复制,这可能导致性能下降,具体取决于其执行频率和纹理分辨率。
可以将自定义渲染纹理链接在一起。为此,请使用自定义渲染纹理作为在另一个自定义渲染纹理中分配给 Material 或者 Initialization Mode > Texture 的材质的输入。
可以使用链接的自定义渲染纹理来生成具有多个步骤的模拟。
链接的自定义渲染纹理相互依赖。Unity 会自动计算此依赖关系,以便每次更新都按正确顺序进行。为此,它会查看在自定义渲染纹理 Inspector 窗口中分配给 Material 和 Initialization Mode > Texture 属性的材质。
若要手动更新自定义渲染纹理,可以编写专门的自定义渲染纹理着色器。
为了帮助编写自定义渲染纹理着色器,此处提供了两个示例框架,其中包含实用程序函数和内置辅助变量。
以下着色器示例使用颜色叠加颜色的方式填充纹理。为自定义渲染纹理编写着色器时,必须执行以下操作:
#include "UnityCustomRenderTexture.cginc"
。CustomRenderTextureVertexShader
。v2f_customrendertexture
。Shader "CustomRenderTexture/Simple"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_Tex("InputTex", 2D) = "white" {}
}
SubShader
{
Lighting Off
Blend One Zero
Pass
{
CGPROGRAM
#include "UnityCustomRenderTexture.cginc"
#pragma vertex CustomRenderTextureVertexShader
#pragma fragment frag
#pragma target 3.0
float4 _Color;
sampler2D _Tex;
float4 frag(v2f_customrendertexture IN) : COLOR
{
return _Color * tex2D(_Tex, IN.localTexcoord.xy);
}
ENDCG
}
}
}
以下示例是可用于初始化自定义渲染纹理的材质的着色器。为初始化材质编写着色器时,必须执行以下步骤:
#include "UnityCustomRenderTexture.cginc"
CustomRenderTextureVertexShader
v2f_customrendertexture
。Shader "CustomRenderTexture/CustomTextureInit"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_Tex("InputTex", 2D) = "white" {}
}
SubShader
{
Lighting Off
Blend One Zero
Pass
{
CGPROGRAM
#include "UnityCustomRenderTexture.cginc"
#pragma vertex InitCustomRenderTextureVertexShader
#pragma fragment frag
#pragma target 3.0
float4 _Color;
sampler2D _Tex;
float4 frag(v2f_init_customrendertexture IN) : COLOR
{
return _Color * tex2D(_Tex, IN.texcoord.xy);
}
ENDCG
}
}
}
#include "UnityCustomRenderTexture.cginc"
提供对一组内置值的访问。这包括全局值、v2f_customrendertexture
结构中的值以及 v2f_init_customrendertexture
结构中的值。
v2f_customrendertexture
结构接受以下输入:
名称 | Type | 值 |
---|---|---|
localTexcoord |
float3 |
相对于当前正在处理的更新区域的纹理坐标。 |
globalTexcoord |
float3 |
相对于自定义渲染纹理本身的纹理坐标 |
primitiveID |
uint |
当前正在处理的更新区域的索引。 |
direction |
float3 |
对于立方体自定义渲染纹理,立方体贴图内当前像素的方向。 |
v2f_init_customrendertexture
结构接受以下输入:
名称 | Type | 值 |
---|---|---|
texcoord |
float3 | 相对于自定义渲染纹理本身的纹理坐标。 |
以下结构是全局值:
名称 | Type | 值 |
---|---|---|
_CustomRenderTextureWidth |
float |
自定义纹理的宽度(以像素为单位) |
_CustomRenderTextureHeight |
float |
自定义纹理的高度(以像素为单位) |
_CustomRenderTextureDepth |
float |
自定义纹理的深度(以像素为单位,仅适用于 3D 纹理,否则将始终等于 1)。 |
_CustomRenderTextureCubeFace |
float |
Unity 处理的当前立方体贴图面的索引(-X、+X、-Y、+Y、-Z、+Z)。这仅适用于立方体贴图。 |
_CustomRenderTexture3DSlice |
float |
正在处理的当前 3D 切片的索引。这仅适用于 3D 纹理。 |
_SelfTexture2D |
Sampler2D |
仅适用于双缓冲纹理:该纹理包含上次交换之前的上次更新的结果。 |
_SelfTextureCube |
SamplerCUBE |
仅适用于双缓冲纹理:该纹理包含上次交换之前的上次更新的结果。 |
_SelfTexture3D |
Sampler3D |
仅适用于双缓冲纹理:该纹理包含上次交换之前的上次更新的结果。 |