玻璃效果
一、基本原理
透明可以做出透明的效果,但是它存在很多缺陷
- 无法实现复杂的光学效果 玻璃不仅仅是透明的,它还具有反射,折射等光学效果,使用透明无法实现这些效果
- 透明物体往往会遇到深度排序的问题 渲染顺序不正确时,会导致视觉错误
所以 我们会使用渲染纹理来制作玻璃效果 基本原理是
- 在渲染效果物体纹理之前,获取到当前屏幕图像
- 将当前图像储存在渲染纹理之中
- 当处理该玻璃效果物体时,再利用储存的渲染纹理实现透明折射的效果
注意: 该纹理中并不会真正的使用混合相关知识,而是直接进行颜色相乘或相加来进行颜色的叠加
二、使用的知识点
特殊渲染通道 GrabPass GrabPass 的作用就是捕获当前屏幕上已经渲染的内容并存储到一张渲染纹理中 使用方法:
- 大括号中什么都不写 默认会把屏幕内容写入一个叫做 _GrabTexture 的纹理变量中 直接写在 CG 语句中声明 _GrabTexture 纹理变量中,即可使用抓取内容
- 大括号中写入自定义的变量名字符串,会把对应屏幕内容写入该自定义纹理变量中 在 CG 语句中声明对应纹理变量,即可使用抓取内容
内置函数 ComputeGrabScreenPos 该内置函数可以计算屏幕空间的位置 所以我们用该函数得到顶点的相对屏幕的坐标,从而从捕获的渲染纹理中进行采样 参数:顶点的裁剪空间的位置 返回值: float4
- X:屏幕坐标的 X
- Y:屏幕坐标的 Y
- Z:裁剪空间的深度,一般用于表示顶点距离摄像机的相对深度
- W:裁剪空间的 W 分量,通常用于透视除法 即:X/W 或者 Y/W 的范围在 0~1 之间
模拟内置函数的自定义计算
三、基础实现
1.实现思路
- 这里我们基于反射的基础实现进行修改实现
- 修改属性相关
- 添加主纹理属性(用于处理物体自身的颜色)
- 添加立方体纹理(用于处理反射)
- 将反射率修改为折射程度(用于控制折射的程度,0 表示完全不折射,1 代表完全折射)
- 要让玻璃对象之后渲染 修改 Tags 相关内容 RenderType 还是 Opaque 因为本质上该渲染的物体还是不透明物体 渲染队列 Queue 更改为 Transparent 这样捕获的屏幕内容,将包含这些更早的渲染的内容
- 加入 GrabPass 并添加对应的渲染纹理变量
- 修改 v2f 结构体
- 加入相对于屏幕坐标的 float4 成员
- 加入 uv 坐标 用于采样物体的颜色
- 修改顶点着色器
- 使用 ComputerGrabScreenPos 方法,计算顶点在屏幕坐标的位置
- 计算纹理的缩放偏移
- 修改片元着色器
- 使用 uv 坐标采样主纹理
- 将屏幕坐标转为裁剪坐标 (即:使用透视除法 将坐标限制到 0~1 之间),再对捕获的纹理进行采样(这里可以进行自定义偏移,以实现折射的效果)
- 用反射再立方体纹理中进行采样,用结果乘以主纹理 并进行颜色叠加
- 用折射程度参与最终颜色的计算 折射程度的变化值决定了最终效果的表现(可以使用 lerp 函数进行限制)
2.实现示例
1 | Shader "Unlit/GlassBase" |
四、带法线纹理效果实现
1.实现思路
- 这里通过改玻璃的基础实现
- 整合标准法线漫反射 Shader 中关于法线相关的计算整合进来 注意:不需要_BumpScale 来控制凹凸程度,这里默认最大
- 修改反射向量计算规则 由于法线需要从法线纹理中获取 因此需要将反射向量的计算放入片元着色器中
2.实现示例
1 | Shader "Unlit/GlassReflaction" |