Unity2017 中新加入的 CustomRenderTexture类用户手册翻译
2017-09-25 15:43
477 查看
由于最近研究一些使用熔岩等粘稠流体模拟技术,需要计算生成一张中间纹理,并用相应的shader实时更新中间纹理中的信息,以实现流体模拟。使用GLSL可以实现,在UnityShader中的实现需要依赖Unity2017新加入的CustomRenderTexture类,来自定义中间纹理,保存需要的信息。这样使用UnityShader同样可以方便的将一些中间信息保存到纹理中,实现更加丰富的模拟效果。
下面现根据官方手册介绍一下新CustomRenderTexture类。边看便翻译的,水平有限,各位凑合着看
https://docs.unity3d.com/2017.2/Documentation/Manual/CustomRenderTextures.html
一、CustomRenderTexture类
CustomRenderTexture是继承自Unity之前版本中的RenderTexture类。RenderTexture的使用需要结合相机,将这个相机所看到的图像渲染到RenderTarget中,这个RenderTarget就是一张RenderTexture类的纹理,这一技术常用语模拟镜面效果(具体应用参考《UnityShader入门精要》一书)。CustomRenderTexture类是对RenderTexture类的一个扩充。我们可以使用Shader来实时地更新纹理,将我们需要的信息保存在纹理中,以方便使用。这一技术可以用来进行很多复杂的模拟,比如:腐蚀、水面产生的涟漪、刚体表面的粘稠流体(血液、熔岩)等等。我们还可以通过脚本,来配置更新纹理使用的Shader的通道、更新区域、以及更新频率等等,来实现许多逼真的模拟效果。
CustomRenderTexture的属性面板展示了RenderTexture已有的许多属性,同时也加入了一些新的独特的属性:
Render Texture:
Custom Texture:
Custom Texture自己独有的属性可以分为三类:
Material: 指定了更新这个纹理所使用的shader.
Initialization: 指定初始化时使用的纹理
Update:用来控制Shader如何更新这张纹理.
Custom Render Texture可以使用Export菜单导出为png格式的或者EXR格式的文件
UpdateZones
默认情况下CustomRenderTexture整体更新,但可以通过设置或者脚本控制选择更新区域列表,而实现纹理的部分更新,这一点对于实现雨滴涟漪的模拟十分有效,比如用UpdateZones来定义雨滴坠落点,在使用一个全局整体更新的pass来实现涟漪(官方给出的示例中正是这样做的)。这同样可以作为一种优化技术使用,比如当你确信并不需要更新整张纹理的全部像素时,只需要指定更新区域即可。
在属性面板上可以对UpDateZones进行配置:
Double Buffered Custom Textures
双重缓存技术
CustomRenderTexture可以使用双重缓存技术,在内部实现上,实际上存在两张纹理,但从开发者的家排毒看他们是一样的。在每一次更新之后,他们的位置将被交换,这样我们可以在更新CustomRenderTexture时使用上一次的结果,这在许多模拟渲染中经常用到。我们可以读取使用上一次已经写入纹理缓存的数据,但我们不能用传统的混合模式来更新其中的值。
性能警告:由于这一技术在内存中实际还拥有一份该纹理的拷贝,在交换时也会影响一定的性能,同时纹理的分辨率大小,交换的频率都可能导致使用双重缓存技术造成性能上的下降。
将CustomRenderTexture连起来
CustomRenderTexture需要使用一个材质(一份Shader实例)来进行更新,这个材质同样可以使用一张纹理作为输入(比如法线纹理,高度纹理等等),这张纹理同样可以是CustomRenderTexture。也就是说我们可以使用一张CustomRenderTexture作为射程或者更新另一张CustomRenderTexture的输入,这样我们就可以使用一个CustomRenderTexture链来完成一些复杂的多步模拟,Unity引擎将会为我们管理好这些纹理更新的先后顺序。
给Custom Render Texture写一个更新Shader
更新CustomRenderTexture的Shader和我们在RenderTexture中使用的2D处理类似,并没有什么特别的不同,官方手册为我们提供了简单的例子:
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
}
}
}
上面的例子中必须的步骤是:
1、 #include “UnityCustomRenderTexture.cginc”
2、使用内置的顶点着色器函数:CustomRenderTextureVertexShader
3、使用内置的是结构体作为片元着色器的输入: v2f_customrendertexture
除此之外,我们可以自由的编写我们需要的像素着色器函数
下面的例子为我们提供了一个简单的初始化CustomRenderTexture的Shader:
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
{ _Color * tex2D(_Tex, IN.texcoord.xy); }
ENDCG }
}
}
与更新Shader一样,下面三个地方是我们必须做的:
1、包含 “UnityCustomRenderTexture.cginc”文件
2、使用内置顶点着色器函数:InitCustomRenderTextureVertexShader
3、使用内置的片元着色器输入结构:v2f_init_customrendertexture
下面是我们为了方便开发者提供的内置数据结构和相关函数,以及他们的说明
v2f_customrendertexture结构体:
v2f_init_customrendertexture 结构体:
全局变量:
我们可以通过C#脚本来对CustomRenderTexture进行控制
上面属性面板中的多种设置都可以通过脚本来进行控制。有一件事要始终注意的就是:任何根据当前CustomRenderTexture当前状态对CustomRenderTexture的更新请求都是发生在这一帧的开始时,这可以保证所有使用这个纹理作为输入的材质都能获取最新的结果。例如:
customRenderTexture.updateZones = updateZones1;customRenderTexture.Update();customRenderTexture.updateZones = updateZones2;customRenderTexture.Update();
这样的代码将不会向我们书写逻辑一样先对updateZones1更新,在对updateZones2更新,而是对updateZones2调用两次Update()。
这样的规则的好处在于:确保了脚本中任何对CustomRenderTexture的属性配置的改变只会在下一帧的更新时起作用。
翻译水平有限,边看便翻译,大家凑合着看。之后分享官方发布的使用CustomRenderTexture的示例程序WaterSimulation分析
下面现根据官方手册介绍一下新CustomRenderTexture类。边看便翻译的,水平有限,各位凑合着看
https://docs.unity3d.com/2017.2/Documentation/Manual/CustomRenderTextures.html
一、CustomRenderTexture类
CustomRenderTexture是继承自Unity之前版本中的RenderTexture类。RenderTexture的使用需要结合相机,将这个相机所看到的图像渲染到RenderTarget中,这个RenderTarget就是一张RenderTexture类的纹理,这一技术常用语模拟镜面效果(具体应用参考《UnityShader入门精要》一书)。CustomRenderTexture类是对RenderTexture类的一个扩充。我们可以使用Shader来实时地更新纹理,将我们需要的信息保存在纹理中,以方便使用。这一技术可以用来进行很多复杂的模拟,比如:腐蚀、水面产生的涟漪、刚体表面的粘稠流体(血液、熔岩)等等。我们还可以通过脚本,来配置更新纹理使用的Shader的通道、更新区域、以及更新频率等等,来实现许多逼真的模拟效果。
CustomRenderTexture的属性面板展示了RenderTexture已有的许多属性,同时也加入了一些新的独特的属性:
Render Texture:
Property: | Function: |
Dimension | Render Texture的维度类型 |
2D | 2D的Render Texture |
Cube | CubeMap的Render Texture |
3D | 3D的Render Texture |
Size | 纹理分辨率大小 |
Color Format | Render Texture的数据格式及类型 |
sRGB (Color Render Texture) | 是否开启sRGB转换 |
[b]Enable Mip Maps | 是否开启MipMaps(多级纹理映射) |
Auto generate Mip Maps | 是否自动生成MipMaps(多级纹理) |
Wrap Mode | 纹理映射方式 |
Repeat | 重复平铺 |
Clamp | 拉伸 |
Filter Mode | 平滑处理模式 |
Point | 单像素 |
Bilinear | 双线性 |
Trilinear | 三线性 |
Aniso Level | 各向异性等级(越高消耗性能越大) |
Custom Texture自己独有的属性可以分为三类:
Material: 指定了更新这个纹理所使用的shader.
Initialization: 指定初始化时使用的纹理
Update:用来控制Shader如何更新这张纹理.
Property: | Function: |
Material | Material used to update the Custom Render Texture |
Shader Pass | 更新所调用的Pass |
Initialization Mode | 纹理初始化模式 |
OnLoad | 被创建时初始化 |
Realtime | 每一帧都初始化一次 |
OnDemand | 脚本中控制,调用时才初始化. |
Source | 纹理初始化使用的资源 |
Texture and Color | 初始化纹理的像素值与Color值相乘得到最终纹理颜色 |
Initialization Color | Color值 |
Initialization Texture | 初始化纹理 |
Material | 使用一个material来初始化纹理 |
Initialization Material | 初始化纹理使用的材质 |
Update Mode | 更新模式 |
OnLoad | 创建时更新 |
Realtime | 每帧更新 |
OnDemand | 通过脚本控制更新 |
Period | (RealTime模式下可用) 多少秒更新一次 (0.0表示每帧更新) |
Double Buffered | 是否开启(Double Buffered)双重缓存技术,交替使用。这允许我们使用上一帧渲染纹理中的信息来进行模拟 |
Wrap Update Zones | 更新区域是否可以包含边界 |
Cubemap Faces | (Cubemap类纹理可用)一些分别控制更新六个面的开关 |
Update Zone Space | 自定义纹理的更新区域(可以通过脚本控制) |
Normalized | 归一化后坐标在(0,1)范围内,左上角是纹理的原点 |
Pixel | 使用像素位置作为坐标,左上角是原点 |
Update Zone List | 更新区域列表(可以通过脚本控制) |
UpdateZones
默认情况下CustomRenderTexture整体更新,但可以通过设置或者脚本控制选择更新区域列表,而实现纹理的部分更新,这一点对于实现雨滴涟漪的模拟十分有效,比如用UpdateZones来定义雨滴坠落点,在使用一个全局整体更新的pass来实现涟漪(官方给出的示例中正是这样做的)。这同样可以作为一种优化技术使用,比如当你确信并不需要更新整张纹理的全部像素时,只需要指定更新区域即可。
在属性面板上可以对UpDateZones进行配置:
Property: | Function: |
Center | updateZone的中心 |
Size | update zone.的大小 |
Rotation | 旋转度数(3D类型的纹理不可用) |
Shader Pass | 使用的Shader中的Pass。默认情况下使用上面主面板上的Pass配置 |
Swap (Double Buffer) | (只在 Double Buffered模式下可用)如果勾选的话,缓存Buffer将在这个UpdateZone执行之前交换 |
双重缓存技术
CustomRenderTexture可以使用双重缓存技术,在内部实现上,实际上存在两张纹理,但从开发者的家排毒看他们是一样的。在每一次更新之后,他们的位置将被交换,这样我们可以在更新CustomRenderTexture时使用上一次的结果,这在许多模拟渲染中经常用到。我们可以读取使用上一次已经写入纹理缓存的数据,但我们不能用传统的混合模式来更新其中的值。
性能警告:由于这一技术在内存中实际还拥有一份该纹理的拷贝,在交换时也会影响一定的性能,同时纹理的分辨率大小,交换的频率都可能导致使用双重缓存技术造成性能上的下降。
将CustomRenderTexture连起来
CustomRenderTexture需要使用一个材质(一份Shader实例)来进行更新,这个材质同样可以使用一张纹理作为输入(比如法线纹理,高度纹理等等),这张纹理同样可以是CustomRenderTexture。也就是说我们可以使用一张CustomRenderTexture作为射程或者更新另一张CustomRenderTexture的输入,这样我们就可以使用一个CustomRenderTexture链来完成一些复杂的多步模拟,Unity引擎将会为我们管理好这些纹理更新的先后顺序。
给Custom Render Texture写一个更新Shader
更新CustomRenderTexture的Shader和我们在RenderTexture中使用的2D处理类似,并没有什么特别的不同,官方手册为我们提供了简单的例子:
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
}
}
}
上面的例子中必须的步骤是:
1、 #include “UnityCustomRenderTexture.cginc”
2、使用内置的顶点着色器函数:CustomRenderTextureVertexShader
3、使用内置的是结构体作为片元着色器的输入: v2f_customrendertexture
除此之外,我们可以自由的编写我们需要的像素着色器函数
下面的例子为我们提供了一个简单的初始化CustomRenderTexture的Shader:
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
{ _Color * tex2D(_Tex, IN.texcoord.xy); }
ENDCG }
}
}
与更新Shader一样,下面三个地方是我们必须做的:
1、包含 “UnityCustomRenderTexture.cginc”文件
2、使用内置顶点着色器函数:InitCustomRenderTextureVertexShader
3、使用内置的片元着色器输入结构:v2f_init_customrendertexture
下面是我们为了方便开发者提供的内置数据结构和相关函数,以及他们的说明
v2f_customrendertexture结构体:
Name | Type | Value |
localTexcoord | float3 | 当前正在处理的UpdateZone的纹理坐标 |
globalTexcoord | float3 | Custom Render Texture纹理坐标 |
primitiveID | uint | 当前正在处理的update zone 的ID索引 |
direction | float3 | 对Cube Custom Render Texture,表示像素在CubeTexture中的方向 |
Name | Type | Value |
texcoord | float3 | Custom Render Texture纹理坐标 |
Name | Type | Value |
_CustomRenderTextureWidth | float | 纹理宽度(像素) |
_CustomRenderTextureHeight | float | 纹理高度(像素) |
_CustomRenderTextureDepth | float | 纹理深度 (只是对 3D纹理有效,其他情况下为1). |
_CustomRenderTextureCubeFace | float | 只对 Cubemaps有效,返回正在处理的纹理面的ID (-X, +X, -Y, +Y, -Z, +Z). |
_CustomRenderTexture3DSlice | float | 只对3D纹理有效: 返回正在处理的3D Slice |
_SelfTexture2D | Sampler2D | 双重缓存技术有效: 返回最近交换前上一次更新的纹理结果 |
_SelfTextureCube | SamplerCUBE | 同上 |
_SelfTexture3D | Sampler3D | 同上 |
上面属性面板中的多种设置都可以通过脚本来进行控制。有一件事要始终注意的就是:任何根据当前CustomRenderTexture当前状态对CustomRenderTexture的更新请求都是发生在这一帧的开始时,这可以保证所有使用这个纹理作为输入的材质都能获取最新的结果。例如:
customRenderTexture.updateZones = updateZones1;customRenderTexture.Update();customRenderTexture.updateZones = updateZones2;customRenderTexture.Update();
这样的代码将不会向我们书写逻辑一样先对updateZones1更新,在对updateZones2更新,而是对updateZones2调用两次Update()。
这样的规则的好处在于:确保了脚本中任何对CustomRenderTexture的属性配置的改变只会在下一帧的更新时起作用。
翻译水平有限,边看便翻译,大家凑合着看。之后分享官方发布的使用CustomRenderTexture的示例程序WaterSimulation分析
相关文章推荐
- Box2D v2.1.0用户手册翻译 - 第10章 世界(World Class)
- Box2D v2.1.0用户手册翻译 - 第03章 公共模块(Common)
- vBox用户手册第9章 高级主题 翻译资料(一)
- Box2D v2.1.0用户手册翻译 - 目录,第01章 导言(Introduction)
- Unity3D用户手册翻译(与Unity3D圣典同步)—— 优化手机的实用指南 - 未来及高端设备
- Box2D v2.1.0用户手册翻译 - 第07章 物体(Bodies)
- Box2D v2.1.0用户手册翻译 - 第10章 世界(World Class)
- v4l2 API手册(规范),官方英文原版规范的,总结翻译版(原创,加入了自己的理解,未完待续)
- ovs-appctl 用户手册中文翻译
- Box2D v2.1.0用户手册翻译 - 第08章 关节(Joints)
- Box2D v2.1.0用户手册翻译 - 第11章 杂项(Loose Ends)
- OpenVMS用户手册目录翻译
- Box2D v2.1.0用户手册翻译 - 第04章 碰撞模块(Collision Module)
- Unity 用户手册iOS 开发入门iOS 报告崩溃错误
- Unity 用户手册iOS 开发入门应用程序预备“内购”
- unity用户手册中的shader部分总结
- Box2D v2.1.0用户手册翻译 - 第09章 接触(Contacts)
- Box2D v2.1.0用户手册翻译 - 第08章 关节(Joints)
- Box2D v2.1.0用户手册翻译 - 第10章 世界(World Class)
- activiti-5.16用户手册翻译完毕