【Unity Shader实例】 水体WaterEffect(五) 水的折射

Unity Shader实现水体的折射效果

水是透明物体,站在清澈的水边,我们可以透过水看到水中的物体。且随着水波晃动,水下的景象会随着水波扭曲。

前面我们实现了水的环境映射、水的反射效果,现在我们来做水的折射效果。

效果展示

这里写图片描述

透明/半透明物体折射效果的实现

原理

先把透明物体隐藏起来,实时获取摄像机渲染的图像,然后对图像进行扭曲处理,然后再把水的模型显示出来,把处理好的图像用屏幕uv的方式作为贴图贴上去

实现要点

1. GrabPass捕捉屏幕纹理

Unity提供了一个ShaderLab命令— GrabPass,用来实现一种特殊的Pass以获取屏幕图像。
GrabPass支持两种形式:

《Unity Shader入门精要》

  • 直接使用GrabPass{},然后在后续的Pass中直接使用_GrabTexture来访问屏幕图像。但是当场景中有多个物体都使用了这种形式来抓取屏幕时,这种方法的性能消耗比较大,因为对于每一个使用它的物体,Unity都会为它单独进行一次昂贵的屏幕抓取动作。但这种方法可以让每个物体得到不同的屏幕图像,这取决于它们的渲染队列以及它们渲染时当前的屏幕缓冲区中的颜色。

  • 使用GrabPass{ “TextureName” },我们可以在后续的Pass中使用TextureName来访问屏幕图像。使用这种方法同样可以抓取屏幕,但Unity只会在每一帧时为第一个使用名为TextureName的纹理的物体执行一次抓取屏幕的操作,而这个纹理同样可以在其他Pass中被访问。这种方法更高效,因为不管场景中有多少物体使用了该命令,每一帧中Unity都只会执行一次抓取操作,但这也意味着所有物体都会使用同一张屏幕图像。

GrabPass示例

新建一个3D Object(Plane)放在屏幕的左上角的位置,将GrabPass采集的纹理作为Plane的纹理,效果如下所示:
这里写图片描述

GrabPass示例shader代码
Shader "Hidden/TestGrabPass"
{
    Properties{}
    SubShader
    {
        GrabPass{ "_GrabTex" }
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            sampler2D _MainTex;
            sampler2D _GrabTex;
            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_GrabTex, 1-i.uv);
                // just invert the colors
                // col = 1 - col;
                return col;
            }
            ENDCG
        }
    }
}
为什么GrabPass的uv是反的?

这是坐标系差异所致:
Unity3D从左下角为(0,0)

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值