US3S8L8——镜面效果

镜面效果原理

镜面效果的原理,就是将摄像机看到的画面渲染到渲染纹理当中,再在Shader中利用该渲染纹理进行翻转渲染即可

镜面效果准备工作

  1. 创建测试场景

  2. 创建一个摄像机用来得到镜子看到的画面

    image

  3. 创建 Custom Render Texture 将其和摄像机关联

    image

自定义渲染纹理参数

Custom Render Texture(CRT)是在 Unity 5.4 版本引入的一种特殊类型的 Render Texture。
它不仅继承了 Render Texture 的所有特性,还增加了额外的功能,例如时间轴控制和空间更新模式。

关于 Custom Render Texture,详情可见:自定义渲染纹理 - Unity 手册

image

  • Dimension:渲染纹理的维度

    image

    • 2D:2D 纹理
    • 2D:2D 数组纹理
    • Cube:立方体纹理
    • 3D:3D纹理
  • Size:像素尺寸

  • Anti-aliasing:抗锯齿效果,级别越高,抗锯齿效果越好

  • Enable Compatible Format:是否启用兼容格式

    避免由于特定硬件或驱动程序不支持某些格式而引起的渲染问题

  • Color Format:渲染纹理格式

  • Depth Stencil Format:深度模板格式

  • Enable Mip Maps:是否允许渲染纹理使用

  • Mipmap Dynamic Scaling:动态缩放

    该渲染纹理根据显示分辨率或其他条件动态调整其大小。启用此选项可以帮助优化性能,特别是在高分辨率显示设备上。

  • Random Write:随机写入

    允许在计算着色器(Compute Shader)或其他GPU程序中进行随机写操作。这对于需要进行复杂计算或并行处理的任务非常有用,例如粒子系统、流体模拟或其他基于GPU的运算

  • Wrap Mode:纹理平铺模式

    image

    • Repeat:重复自身
    • Clamp:拉伸纹理边缘
    • Mirror:镜像
    • Mirror Once:首次镜像
    • Per-axis:UV指定轴向
  • Filter Mode:拉伸时的过滤模式

    image

    • Point:块状过滤
    • Bilinear:模糊过滤
    • Trilinear:类似Bilinear,但纹理也在不同 Mip 级别之间过滤
  • Shadow Sampling Mode:主要用于处理自定义渲染纹理在阴影计算中的采样模式

    image

    • None:不使用阴影采样模式。自定义渲染纹理将不会用于阴影贴图采样
    • Compare Depths:使用深度比较进行阴影采样。这种模式通常用于标准阴影映射技术,比较光源深度与当前像素深度以确定阴影
  • Material:自定义纹理材质

  • Initialization Mode:初始化纹理频率

    • OnLoad:创建时初始化一次
    • Realtime:每一帧初始化纹理
    • OnDemand:通过脚本按需初始化纹理
  • Source:纹理如何初始化

    image

    • Texture and Color:叠加颜色来初始化纹理
    • Material:使用材质初始化纹理
  • Update Mode:自定义渲染纹理的频率

    image

    • OnLoad:创建时初始化一次
    • Realtime:每一帧初始化纹理
    • OnDemand:通过脚本按需初始化纹理
  • Double Buffered:启用双缓冲技术,可在某些应用场景中提升性能和稳定性

    双缓冲技术涉及使用两个缓冲区来交替存储和处理数据,从而减少由于直接读写同一个缓冲区引起的竞争和冲突

  • Wrap Update Zones:控制更新区域的环绕方式

    对于处理需要特定边缘处理或重复性内容的渲染效果非常有用

  • Updte Zone Space:用于控制纹理坐标更新方式的选项

    它主要影响如何在Shader中处理纹理坐标,特别是在对应于动态纹理的情况下

实现镜面效果Shader

  1. 新建Shader,复用 US3S2L1——纹理颜色采样 Shader

  2. 在顶点着色器中,让UV坐标的X轴反向(坐标范围0~1,想要反向直接用 1 - uv.x​,这是为了实现镜面效果)即可

    1
    2
    3
    4
    5
    6
    7
    8
    v2f_img vert (appdata_base v)
    {
    v2f_img data;
    data.pos = UnityObjectToClipPos(v.vertex); //将顶点转换到裁剪空间下
    data.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw; //根据属性设置的缩放和偏移量,修正顶点UV坐标,确保缩放偏移后也能正确映射
    data.uv.x = 1 - data.uv.x; //由于需要镜面效果,因此纹理方向在x轴上需要反向
    return data;
    }
  3. 将渲染纹理应用到该 Shader 的纹理中

    image

  4. 添加 Fallback "Diffuse"​,使得镜子可以投射阴影

显示效果:

image

完整 Shader 效果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Shader "TeachShader/Lesson83_Mirror"
{
Properties
{
_MainTex("MainTex", 2D) = ""{}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag

#include "UnityCG.cginc"

sampler2D _MainTex;
float4 _MainTex_ST;

v2f_img vert (appdata_base v)
{
v2f_img data;
data.pos = UnityObjectToClipPos(v.vertex); //将顶点转换到裁剪空间下
data.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw; //根据属性设置的缩放和偏移量,修正顶点UV坐标,确保缩放偏移后也能正确映射
data.uv.x = 1 - data.uv.x; //由于需要镜面效果,因此纹理方向在x轴上需要反向
return data;
}

fixed4 frag (v2f_img i) : SV_Target
{
fixed4 color = tex2D(_MainTex, i.uv); //根据UV坐标,将纹理上颜色映射到模型上
return color;
}
ENDCG
}
}

Fallback "Diffuse"
}