目录

  • 1 场景搭建与实现思路
  • 2 深度图获取与原理
    • 获取方式
    • 深度图计算原理
    • 变换过程
  • 3 重建世界坐标
    • 采样深度图
    • 重建方法1
    • 重建方法2
  • 4 结果

仅做学习,如有错误望指正
涉及的知识点:depthmap, ComputeWorldSpacePositionComputeScreenPos

1 场景搭建与实现思路


两个plane如图交叉,将在水平plane中实现基本的风格化水表面

泡沫是在两个plane的相交处生成的,== 换句话说当水面和地面的距离小于一定的阈值,则产生泡沫 ==。
现在的问题是如何得到水面和地面的距离呢?
其中一个方法从深度图信息反推出地面的顶点世界坐标
这是一个比较暴力但合理的方法。
这里提供了两种,一种是使用unity提供的接口,另一种是自行反推。

2 深度图获取与原理


获取方式

urp提供了获取深度图的方法,在管线设置中勾选depth texture

在debugger中,找到对应的深度图名字,这样可以直接在shader中调用_CameraDepthTexture

此实验是在dx平台下建立的,深度图是近红远黑

深度图计算原理

需要知道基本的计算流程,才能够了解后面的反推过程,如果对此部分不感兴趣,可跳过这个部分。
因为算式打起来比较麻烦,这里只显示必要的重点。详细,可参考这个文章 link
观察空间坐标→裁剪空间v的坐标z范围为:-n-f(far clippng planes)
裁剪空间→ndc坐标的z范围(透视除法):-1-1-》0-1
ndc→屏幕坐标,x分量为例: p o s . x = ( v x 2 ⋅ v w + 0.5 ) ∗ p i x e l w i d t h pos.x =(\frac{v_x}{ 2\cdot{v_w}} + 0.5) * pixel_{width} pos.x=(2⋅vw​vx​​+0.5)∗pixelwidth​

变换过程

MVP矩阵得到的是裁剪空间坐标。 坐标除以w之后(称为透视除法),得到了NDC坐标最后通过线性变换,得到最终的屏幕空间坐标

3 重建世界坐标


根据CameraDepthTex获得观察空间下的坐标,然后通过逆变换变成世界空间的坐标数据。如果能够办到,后面的流程就会容易很多

采样深度图

这里需要提一下ComputeScreenPos 这一个函数,这个函数输入裁剪空间的坐标数据,然后返回齐次坐标系下的屏幕坐标值的xy数据,z,w保持不变。而想获得归一化屏幕坐标的数据还要再进行一次齐次除法,获得(0,1)范围的数据

o.x = (pos.x * 0.5 + pos.w * 0.5)
o.y = (pos.y * 0.5 * _ProjectionParams.x + pos.w * 0.5)

ComputeScreenPos 思路如上,可对比ndc→屏幕坐标的过程。
使用这个函数,可以直接获取屏幕归一化的坐标值float4 screenPos = i.scrPos / i.scrPos.w;,其中xy分量能作为采样_CameraDepthTexture的uv坐标
这一步已经考虑到平台差异性了,因此不需要考虑额外的东西

  • 采样
float4 screenPos = i.scrPos / i.scrPos.w;
float sceneRawDepth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler_CameraDepthTexture, screenPos.xy);

下面提供了两种写法来实现世界坐标的重建。

重建方法1

但是_CameraDepthTexture只提供单通道的z数据,也就是说我们无法正确得到除z值外的其他分量的信息。这一步和平台也有关系,opengl的ndc z分量范围是-1,1,dx则是0,1。
上步得到的 sceneRawDepth范围为0,1,ndz实际的坐标会根据平台差异性处理也会不同
由于实验是在dx下搭建的,于是,ndc数据还原为:

 float4 ndc = float4(screenPos.x * 2 - 1,screenPos.y * 2 - 1, sceneRawDepth, 1);

注意这一步需要考虑差异性,dx与opengl 坐标颠倒,因此在采样的过程中,已经对y进行了处理。在还原ndc的过程中我们还需要对y分量进行bug处理

#if UNITY_UV_STARTS_AT_TOP// Our world space, view space, screen space and NDC space are Y-up.// Our clip space is flipped upside-down due to poor legacy Unity design.// The flip is baked into the projection matrix, so we only have to flip// manually when going from CS to NDC and back.ndc.y *= -1;
#endif

现在可以根据之前所提到的变换过程,ndc*w然后进行逆变换;然而投影变换过程是一个非线性的过程,其中会带来不稳定的非线性损失。因此这里使用worldPos.w=1来反推出实际需要加入计算的w,因此式子变为如下

                float4 worldPos = mul(UNITY_MATRIX_I_VP, ndc);//ndc to worldworldPos /= worldPos.w;

最后得到水面与水底的深度差值

float RawDepth = PosW.y-worldPos.y;
  • 最终的代码如下所示
            float4 frag_depth(v2f i) : SV_Target{float3 PosW = i.posW;float4 screenPos = i.scrPos / i.scrPos.w;float sceneRawDepth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler_CameraDepthTexture, screenPos.xy);float4 ndc = float4(screenPos.x * 2 - 1,screenPos.y * 2 - 1, sceneRawDepth, 1);//0,1->-1,1#if UNITY_UV_STARTS_AT_TOPndc.y *= -1;#endiffloat4 worldPos = mul(UNITY_MATRIX_I_VP, ndc);//ndc to worldworldPos /= worldPos.w;float RawDepth = PosW.y-worldPos.y;return float4(RawDepth.xxx, 1);      }

重建方法2

urp 直接可以调用此函数ComputeWorldSpacePosition获得重建坐标,方法1就是方法2的复现

                float4 screenPos = i.scrPos / i.scrPos.w;// screenPos.z = (UNITY_NEAR_CLIP_VALUE >=0)?screenPos.z:screenPos.z* 0.5 + 0.5;float sceneRawDepth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler_CameraDepthTexture,screenPos.xy);float3 worldPos = ComputeWorldSpacePosition(screenPos.xy, sceneRawDepth, UNITY_MATRIX_I_VP);float RawDepth = PosW.y-worldPos.y;

4 结果

【unity shader/风格化水表面渲染/基础笔记】urp代码版01-水面与水底的深度判断相关推荐

  1. 【unity shader/风格化水表面渲染/基础笔记】urp代码版03-水表面颜色

    前言 上一节生成了岸边的泡沫.本节主要梳理水表面的上色过程,这部分涉及半透明渲染和fresnel颜色 颜色 首先,岸边_ShallowCol和远离岸边_DeepCol的颜色应该有所区分.这里依旧利用上 ...

  2. 【unity shader/风格化水表面渲染/基础笔记】urp代码版05-焦散模拟

    前言 前面4章完成了波浪动画.上色.岸边泡沫的生成.本章梳理水底的焦散模拟. 焦散模拟 我们可以使用类似的水纹的贴图作色散分离,或者直接使用分离的三通道贴图. 下面的代码设置了宏_DISPERSION ...

  3. 【unity shader/风格化水表面渲染/基础笔记】urp代码版02-岸边泡沫的生成

    前言 上一节,达成了水面与水底的深度判断,结果用RawDepth表示.这一节梳理利用深度关系生成岸边的泡沫. 设计函数_getFoam(RawDepth) float sinWave = _getFo ...

  4. 《Unity Shader 入门精要》读书笔记

    <Unity Shader 入门精要>读书笔记 --记录一下自己看书时遇到的一下困惑的地方和自己的一些想法,愿明天的我更加强大 1.要正确获得阴影和光照衰减效果,需要#pragma mul ...

  5. Unity Shader 龙珠Z卡通渲染分析

    Unity Shader 龙珠Z卡通渲染分析 一.角色渲染效果整体分析角色渲染效果整体分析 二.轮廓线效果 三.三阶梯度漫反射 四.高光 一.角色渲染效果整体分析角色渲染效果整体分析 渲染效果整体截图 ...

  6. 《Unity Shader入门精要》学习笔记

    简单说明 为控制渲染过程提供一层抽象,避免许多繁琐配置:用ShaderLab编写,使用一些嵌套在{}的语义: 定义了要显示材质所需的全部,不仅仅是着色器代码 Unity Shader != Shade ...

  7. Unity Shader入门精要 | 渲染路径、光源类型和阴影

    目录 渲染路径 前向渲染 (Forward Rendering) 顶点照明渲染 (Vertex Lit Rendering) 延迟渲染 (Deferred Rendering) 光源类型 平行光 (D ...

  8. 《Unity Shader入门精要》学习笔记第11章 让画面动起来

    本文章用于帮助自己学习,因此只记录一些个人认为比较重要或者还不够熟悉的内容. 原作者:http://blog.csdn.net/candycat1992/article/ 第十一章 让画面动起来 11 ...

  9. 《Unity Shader入门精要》学习笔记第5章 开始Unity Shader学习之旅

    本文章用于帮助自己学习,因此只记录一些个人认为比较重要或者还不够熟悉的内容. 原作者:http://blog.csdn.net/candycat1992/article/ 第五章 开始Unity Sh ...

最新文章

  1. 2020 AI DEBATE即将召开, Judea Pearl、李飞飞等10多位顶级科学家参与 | AI日报
  2. 深入Java泛型(四):RxJava中泛型的使用分析
  3. 仿抖音底部导航效果(一)
  4. [leetcode] 68.二叉树的最近公共祖先
  5. 使用@host获得宿主元素注入器里注入的内容
  6. Android NDK学习(七):NDK 编译支持 C++特有的库
  7. mysql pid_mysql pid文件是什么用途
  8. Cell封面文章:跑步短短10分钟,身体近10000个分子大变样!蛋白组学破解运动有益健康之谜...
  9. javaweb框架--自定义标签与freemaker结合
  10. Kotlin 一统天下?Kotlin/Native 开始支持 iOS 和 Web 开发
  11. centos 7 更换yum源
  12. zabbix 安装和基础监控
  13. PMP考试题型是如何分布的?
  14. JDK动态代理(通俗白话)
  15. inSSIDer无线信号扫描工具
  16. 股票量化交易这些劣势你知道吗?
  17. Qt 根据PCM获取分贝 并自动调节电脑音量
  18. 2018年的最后一周,说些心里话
  19. 花菁染料(cas773041-79-5|cas427882-78-8|cas14134-81-7)结构图及合成路线图
  20. Laravel框架-迁移文件

热门文章

  1. Flutter的AppBar的按钮组件
  2. 近十万台路由器组成僵尸网络,专门向WordPress网站发起撞库攻击
  3. 橙优设计:云计算是什么?Java云计算大数据方向怎么样?
  4. shell basename 可以去除文件名后缀
  5. python设计一个Circle(圆)类,包括圆心位置`,半径,颜色等属性。编写构造方法和其他方法,计算周长和面积。
  6. 专访中国工程院院士杜祥琬,可控核聚变美国成了吗?
  7. php addslashes 数组,PHP函数漏洞审计之addslashes函数-
  8. Android调试神器stetho使用详解和改造 1
  9. android取QQ昵称,Android仿QQ复制昵称效果的实现方法
  10. web前端开发技术实验与实践(第三版)储久良编著 项目5 综合编程岗位介绍