赞
踩
前排感谢评论区西瓜与拖鞋的指正,原本对于顶点着色器中得到的interpolatedRay的定义有误解,经过指正已经修改博文中的描述
游戏特效,后处理是必不可少的,而后处理经常需要我们得到当前画面的像素对应世界空间的所有信息。
//csharp脚本部分
Matrix4x4 matrix = camera.projectionMatrix * camera * worldToCameraMatrix;
Matrix4x4 InverseMatrix = matrix.inverse;
//shader部分
float d = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv_depth);
float4 H = float4(i.uv.x * 2 - 1, i.uv.y * 2 - 1, d * 2 - 1, 1);
float D = mul(InverseMatrix, H);
float worldPos = D/D.w
计算量比较大,一般用下面的方法。
2. 通过得到相机的坐标和世界空间下像素和相机的偏移量相加得到像素的世界坐标。这里偏移量通过顶点的线性深度乘以顶点着色器输出并被插值后所得的相机指向像素的射线来得到。
float4 worldPos = _WorldSpaceCameraPos + linearDepth * interpolatedRay;
接下来来介绍这种办法计算的过程。
我们很容易计算出相机到近平面四个顶点的向量方向以及世界空间下的长度,只需要得到相机记录的fov,aspect等信息
我们要得到的是像素的世界坐标。
这里有个很重要的点,相机能看到这个像素,必然说明原本的世界坐标的点和在近平面的投影点(像素位置)处于相机相机指向像素的射线的方向上。也就是下面13.7图。
所以问题转为如何得出相机到像素所对应的世界坐标的向量的长度,
很幸运的是我们拥有深度纹理,所以13.7图的depth是已知的。
那么如何通过depth来得到dist,这里书本上举例的是TL点的计算。
书本上的interpolatedRay的长度并不是相机点指向近平面像素的长度,相机点指向近平面像素的真正向量是
dist * nor(interpolatedRay)
而在顶点着色器之中我们计算的是
i.interpolatedRay.xyz = scale * nor(interpolatedRay)
depth通过顶点着色器到片元着色器的过程中进行插值,且dist = scale * depth
从而在片元着色器上取得
depth * i.interpolatedRay.xyz
这里把interpolatedRay理解成相机点指向近平面像素的真正向量就行。
单单看这个点的计算是没问题的,自己手画一个就能得出结果。但关键是为什么所有点都满足,这里设世界坐标下任意一点A。
其和相机的连线经过近平面并产生交点
画出near向量
延长near到长度和A点的z变量,也就是depth一样长,并且做三角形OAB和ODC
这张有点乱,希望大家不要嫌弃,真的不太懂怎么安排线
很容易发现三角形ODC ~ 三角形OAB
得到长度关系
|near| / |interpolatedRay| = |depth| / |dist|
对任意点都是适用的
上文提到书本上的interpolatedRay是 scale * nor(interpolatedRay),
所以在片元着色器中乘上depth
对应书上片元着色器的部分就是这部分代码。
可能只想要得到近平面的像素点(平面本身构成的图片的像素)在世界空间下的位置,只需要计算出相机到近平面的四个顶点的向量直接插值,无需任何深度纹理的信息。
也就是书上的这部分代码无需乘scale
并且计算公式变为
float4 worldPos = _WorldSpaceCameraPos + interpolatedRay;
这样子的情况下,雾效的产生将和相机直接挂钩,相机的近平面就是雾效产生的地方,可以在2D游戏中使用。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。