找回密码
 立即注册
查看: 142|回复: 0

[简易教程] Unity URP 新手教程 _CameraDepthTexture 和 ...

[复制链接]
发表于 2022-11-14 13:52 | 显示全部楼层 |阅读模式
原教程,素材网址,推荐先阅读原教程:
这里只重点讲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 "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareNormalsTexture.hlsl"这篇文章还参考了以下教程:
丁彦清:基于深度与法线贴图的屏幕后处理——Unity URP“_CameraDepthTexture”和“_CameraNormalsTexture”使用讲解
urp管线的自学hlsl之路 第十六篇 屏幕深度制作护盾特效

完整工程:
所有美术素材均来自原教程

欢迎大家讨论和分享其它教程

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-5-2 19:53 , Processed in 0.235905 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表