文章目录
- 前言
- 一、搭建预备场景
- 1、新建一个面片,使其倾斜一个角度,来模拟水底和岸边的效果
- 2、随便创建几个物体,作为与水面接触的物体
- 3、再新建一个面片,作为水面
- 二、开始编写水体的Shader效果
- 1、新建一个URP基础Shader
- 2、把水体Shader分解为以下几个部分
- 三、实现水的深度效果
- 1、在URP管线设置下,打开深度图
- 2、在SubShader中,申明深度图纹理和采样器
- 3、修改水体渲染为半透明队列
- 4、在Pass中关闭深度写入
- 5、获取水体顶点在观察空间下的坐标
- 6、把采样到的深度图转化到观察空间下
- 7、最后,用观察空间下的 深度图 和 水体顶点坐标的Z值相加即可
- 四、最终代码 及 效果
- 1、最终效果
- 2、最终代码
前言
在之后的文章中,我们在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分解为以下几个部分
- 水的深度
- 水的高光
- 水的反射
- 水的焦散
- 水下的扭曲
- 水面泡沫
三、实现水的深度效果
这个可以利用深度图,仿照之前能量罩交接处高光的效果来做
- Unity中URP下实现能量罩(交接处高亮)
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"
}