雾效
重建世界坐标(如果需要在世界坐标系下渲染烟雾,如果只在屏幕的某一块渲染烟雾则不需要)
利用变换矩阵在片元着色器中重建
//获取深度纹理 float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv_depth); //转换坐标空间,由纹理坐标空间0-1转换到NDC float4 NDCPos = float4(i.uv.x * 2 - 1, i.uv.y * 2 - 1, depth * 2 - 1, 1); //变换到世界坐标 float4 worldPos = mul(_CurrentViewProjectionInverseMatrix, NDCPos); worldPos /= worldPos.w; |
该方法由于在片元着色器中计算,计算量大比较消耗性能
利用像素相对于摄像机的偏移量进行重建
公式
float4 worldPos = _WorldSpaceCameraPos + linearDepth * interpolatedRay; |
interpolatedRay可利用GPU的插值过程获得,这样不需要在片元着色其中逐像素计算。
因为在unity中,屏幕后处理是将渲染纹理绘制在一个四边形上,所以如果可以通过插值得到每个像素点的射线,但首先需要获得四个顶点的射线值
,TL,TR,BL,BR。
公式如下:
aspect为长宽比:Width/height
射线与偏移量的关系:
所以:
由上面公式推导出顶点像素的世界坐标公式:
float4 Vertex_worldPos = _WorldSpaceCameraPos +dist *𝑇𝐿|𝑇𝐿|=WorldSpaceCameraPos +|𝑇𝐿|𝑁𝑒𝑎𝑟 * depth *𝑇𝐿|𝑇𝐿|
=WorldSpaceCameraPos + 𝑇𝐿𝑁𝑒𝑎𝑟 * depth ;
所以TLNear = |TL|Near TL|TL|
同理:由于4个点相互对称,因此其他3个向量的模和TL相等,即我们可以使用同一个因子和单位向量相乘,得到它们对应的向量值:
雾的计算
float3 afterFog = f * fogColor + (1 - f) * origColor;
实现OnRenderImage
void OnRenderImage(RenderTexture source, RenderTexture destination) { if(material != null) { Matrix4x4 frustumCorners = Matrix4x4.identity; //获取摄像机参数 float fov = camera.fieldOfView; float near = camera.nearClipPlane; f |