|
原教程,素材网址,推荐先阅读原教程:
这里只重点讲URP下如何获取和使用_CameraDepthTexture 和 _CameraNormalsTexture, 其它部分 URP 和默认管线并无区别,大家看原教程即可
本文中使用的 Unity 版本为 : 2020.3.33f1c2, URP版本 : 10.8.1
前期准备:
切换为URP渲染管线, 将 ToonLit.shader 改写为 URP 版本, 将 Assets/Materials/Shoreline 材质的 shader 也切换为 ToonLit.shader:
将 ToonWater.shader 也改写为 URP 版本, 并将渲染队列调整为透明物体:
SubShader
{
Tags
{
"Queue" = "Transparent"
"RenderPipeline" = "UniversalPipeline"
}
......
}一. 采样 _CameraDepthTexture, 计算水深度
先在管线中开启深度图:
在 ToonWater.shader 中声明深度图:
TEXTURE2D(_CameraDepthTexture); SAMPLER(sampler_CameraDepthTexture);在 顶点着色器 中计算屏幕空间坐标:
// xy存储为未经透除的uv通道,zw正常存储
output.positionSS.xy = output.positionHCS.xy * 0.5 + 0.5 * output.positionHCS.w;
output.positionSS.zw = output.positionHCS.zw;在 片元着色器 中进行透视除法, 对 _CameraDepthTexture 进行采样, 并转为线性深度:
input.positionSS.xy /= input.positionSS.w;
#ifdef UNITY_UV_STARTS_AT_TOP
input.positionSS.y = 1 - input.positionSS.y;
#endif
half existingDepth01 = SAMPLE_DEPTH_TEXTURE(
_CameraDepthTexture,
sampler_CameraDepthTexture,
input.positionSS.xy).r;
half existingDepthLinear = LinearEyeDepth(existingDepth01, _ZBufferParams);直接用水面深度减去采样得到的深度,就可以得到水面与水下物体的深度差:
half depthDifference = existingDepthLinear -
LinearEyeDepth(input.positionHCS.z, _ZBufferParams);注意,只有渲染队列 < 2500 的材质才会出现在 _CameraDepthTexture 上
另外 unity 2020.3.33f1c2 版本有BUG, 深度图无法在 Scene 窗口正常显示, 不过在 Game 窗口显示正常
结果如下 :
然后对两个颜色进行插值,得到结果:
half waterDepthDifference01 = saturate(depthDifference / _DepthMaxDistance);
half4 waterColor = lerp(_DepthGradientShallow, _DepthGradientDeep,
waterDepthDifference01);
二.采样 _CameraNormalsTexture, 计算泡沫大小
1.在 URP 渲染器上添加 Renderfeature(SSAO), 打开 depth normals:
SSAO只对有光照的物体生效,其它情况需要自定义 renderfeature
2.为 ToonLit.shader 添加 DepthNormals 渲染通道, 只有有DepthNormals 渲染通道并且 渲染队列 < 2500才会出现在 _CameraNormalsTexture 上:
直接从内置的 Lit.shader 中直接复制代码即可,这里就不贴了
// This pass is used when drawing to a _CameraNormalsTexture texture
Pass {....}下面就可以采样_CameraNormalsTexture了,和默认渲染管线不同的是,这里还需要进行一下解码:
float4 existingNormal = SAMPLE_TEXTURE2D(_CameraNormalsTexture,
sampler_CameraNormalsTexture,
input.positionSS.xy);
float3 existingNormal_unpack =
UnpackNormalOctRectEncode(existingNormal);整个场景的 normal_Viewspace 如下图所示:
最后的结果如下,最大阈值为0.4,最小阈值为0.04:
补充:
(1).如果使用其它计算屏幕空间坐标的方法,采样时可以用 input.positionHCS.xy / _ScreenParams.xy 验证是否计算正确, 但是input.positionHCS.xy / _ScreenParams.xy 受 RenderScale 影响,平时不建议用
(2).申明和采样 _CameraDepthTexture 和 _CameraNormalsTexture 也可以直接用:
#include &#34;Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl&#34;
#include &#34;Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareNormalsTexture.hlsl&#34;这篇文章还参考了以下教程:
丁彦清:基于深度与法线贴图的屏幕后处理——Unity URP“_CameraDepthTexture”和“_CameraNormalsTexture”使用讲解
urp管线的自学hlsl之路 第十六篇 屏幕深度制作护盾特效
完整工程:
所有美术素材均来自原教程
欢迎大家讨论和分享其它教程 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|