Unity中URP实现水体效果(水的深度)


前言

在之后的文章中,我们在URP下实现水面的效果。
在该文章中,我们来看一下水的深度是怎么实现的。


一、搭建预备场景

1、新建一个面片,使其倾斜一个角度,来模拟水底和岸边的效果

在这里插入图片描述

2、随便创建几个物体,作为与水面接触的物体

在这里插入图片描述

3、再新建一个面片,作为水面

在这里插入图片描述


二、开始编写水体的Shader效果

1、新建一个URP基础Shader

//水的深度
Shader "MyShader/URP/P4_7_2"
{
    Properties {}
    SubShader
    {
        Tags
        {
            //告诉引擎,该Shader只用于 URP 渲染管线
            "RenderPipeline"="UniversalPipeline"
            //渲染类型
            "RenderType"="Opaque"
            //渲染队列
            "Queue"="Geometry"
        }
        Pass
        {
            Name "Universal Forward"
            Tags
            {
                // LightMode: <None>
            }

            Cull Back
            Blend One Zero
            ZTest LEqual
            ZWrite On
          
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // Pragmas
            #pragma target 2.0
            
            // Includes
            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl"

            //struct appdata
            //顶点着色器的输入
            struct Attributes
            {
                float3 positionOS : POSITION;
            };
            //struct v2f
            //片元着色器的输入
            struct Varyings
            {
                float4 positionCS : SV_POSITION;
            };
            //v2f vert(Attributes v)
            //顶点着色器
            Varyings vert(Attributes v)
            {
                Varyings o = (Varyings)0;
                float3 positionWS = TransformObjectToWorld(v.positionOS);
                o.positionCS = TransformWorldToHClip(positionWS);
                return o;
            }
            //fixed4 frag(v2f i) : SV_TARGET
            //片元着色器
            half4 frag(Varyings i) : SV_TARGET
            {
                //水的深度
                
                //水的高光

                //水的反射

                //水的焦散

                //水下的扭曲
                half4 c;
                c.rgb = 0.5;
                c.a = 1;
                return c;
            }
            ENDHLSL
        }
    }

    FallBack "Hidden/Shader Graph/FallbackError"
}

2、把水体Shader分解为以下几个部分

  • 水的深度
  • 水的高光
  • 水的反射
  • 水的焦散
  • 水下的扭曲
  • 水面泡沫

三、实现水的深度效果

这个可以利用深度图,仿照之前能量罩交接处高光的效果来做

1、在URP管线设置下,打开深度图

在这里插入图片描述

2、在SubShader中,申明深度图纹理和采样器

//申明深度图的 纹理 和 采样器
TEXTURE2D(_CameraDepthTexture);SAMPLER(sampler_CameraDepthTexture);

3、修改水体渲染为半透明队列

Tags
{
//告诉引擎,该Shader只用于 URP 渲染管线
“RenderPipeline”=“UniversalPipeline”
//渲染类型
“RenderType”=“Transparent”
//渲染队列
“Queue”=“Transparent”
}

4、在Pass中关闭深度写入

ZWrite Off

5、获取水体顶点在观察空间下的坐标

  • 在Varyings结构体,定义positionVS变量,用于存储顶点在观察空间下的坐标

struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
float3 positionVS : TEXCOORD1;
};

  • 在顶点着色器中,对把顶点转化到观察空间下

o.positionVS = TransformWorldToView(positionWS);

6、把采样到的深度图转化到观察空间下

float depthScene = LinearEyeDepth(depthTex,_ZBufferParams);

7、最后,用观察空间下的 深度图 和 水体顶点坐标的Z值相加即可

float4 depthWater = depthhScene + i.positionVS.z;


四、最终代码 及 效果

1、最终效果

在这里插入图片描述

2、最终代码

//水的深度
Shader "MyShader/URP/P4_8_2"
{
    Properties {}
    
    SubShader
    {
        Tags
        {
            //告诉引擎,该Shader只用于 URP 渲染管线
            "RenderPipeline"="UniversalPipeline"
            //渲染类型
            "RenderType"="Transparent"
            //渲染队列
            "Queue"="Transparent"
        }
        //Blend One One
        ZWrite Off
        Pass
        {
            Name "Unlit"
          
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // Pragmas
            #pragma target 2.0
            
            // Includes
            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl"

            CBUFFER_START(UnityPerMaterial)
            
            CBUFFER_END

            
            TEXTURE2D(_CameraDepthTexture);SAMPLER(sampler_CameraDepthTexture);
            //struct appdata
            //顶点着色器的输入
            struct Attributes
            {
                float3 positionOS : POSITION;
                float2 uv : TEXCOORD0;
            };
            //struct v2f
            //片元着色器的输入
            struct Varyings
            {
                float4 positionCS : SV_POSITION;
                float2 uv : TEXCOORD0;
                float4 screenPos : TEXCOORD1;
                float3 positionVS : TEXCOORD2;
            };
            //v2f vert(Attributes v)
            //顶点着色器
            Varyings vert(Attributes v)
            {
                Varyings o = (Varyings)0;
                float3 positionWS = TransformObjectToWorld(v.positionOS);
                o.positionVS = TransformWorldToView(positionWS);
                o.positionCS = TransformWViewToHClip(o.positionVS);
                
                o.screenPos = ComputeScreenPos(o.positionCS);
                return o;
            }
            //fixed4 frag(v2f i) : SV_TARGET
            //片元着色器
            half4 frag(Varyings i) : SV_TARGET
            {
                //1、水的深度
                //获取屏幕空间下的 UV 坐标
                float2 screenUV = i.positionCS.xy / _ScreenParams.xy;
                half depthTex = SAMPLE_TEXTURE2D(_CameraDepthTexture,sampler_CameraDepthTexture,screenUV).x;
                //深度图转化到观察空间下
                float depthScene = LinearEyeDepth(depthTex,_ZBufferParams);
                float4 depthWater = depthScene + i.positionVS.z;
                
                //获取水面模型顶点在观察空间下的Z值(可以在顶点着色器中,对其直接进行转化得到顶点观察空间下的坐标)
                
                //2、水的高光

                //3、水的反射

                //4、水的焦散

                //5、水下的扭曲

                //6、水面泡沫
                return depthWater;
            }
            ENDHLSL
        }
    }
    FallBack "Hidden/Shader Graph/FallbackError"
}
  • 22
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

楠溪泽岸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值