雾效(fog)
unity 内置的雾效可以产生基于距离的线性或指数雾效。
然而,想要在自己编写的顶点/片元着色器中实现这些雾效,需要在shader中添加【#pragma multi_compile_fog】指令,同时还需要使用相关的内置宏,例如【UNITY_FOG_COORDS】【UNITY_TRANSFER_FOG】【UNITY_APPLY_FOG】等,缺点在于不仅需要为场景中所有物体添加相关的渲染代码,而且能够实现的效果也非常有限,当需要对雾效进行一些个性化操作时,例如使用基于高度的雾效等,仅仅使用Unity内置的雾效就变得不再可行
基于屏幕后处理的全局雾效的关键是:根据深度纹理来重建每个像素在世界空间下的位置
即构建出当前像素的NDC坐标,再通过当前摄像机的视角*投影矩阵的逆矩阵来得到世界空间下的像素坐标,但是,这样的实现需要在片元着色器中进行矩阵乘法的操作,而这通常会影响游戏性能。
本节会学习一个快速从深度纹理中重建世界坐标的方法:
这种方法首先对图像空间下的视椎体射线(从摄像机出发,指向图像上的某点的射线)进行插值,这条射线储存了该图像在世界空间下到摄像机 的方向信息,
然后我们把该射线和线性化后的视角空间下的深度值相乘,再加上摄像机的世界位置,就可以得到该像素在世界空间下的位置,当得到世界坐标后,就可以轻松使用各个公式来模拟全局雾效了。
重建世界坐标
如何从深度纹理中重建世界坐标:
坐标系中的一个顶点坐标可以通过它相对于另一个顶点坐标的偏移量来求得,重建像素的世界坐标也是基于这个想法。只需要知道摄像机在世界空间下的位置,以及世界空间下该像素相对于摄像机的偏移量,把他们相加就可以得到该像素到摄像机的世界坐标。整个过程可以用下面的代码来表示
float4 _WorldPos=_WorldSpaceCameraPos+linearDepth*interpolatedRay;
_WorldSpaceCameraPos:摄像机在世界空间下的位置,这个可以由unity内置的变量直接访问得到
linearDepth:由深度纹理得到的线性深度值(13.1.2讲过获取原理)
interpolatedRay:由定点着色器输出并插值后得到的射线,他不仅包含了该像素到摄像机的方向,也包含了距离信息
linearDepth*interpolatedRay:得到相对于摄像机 的偏移量
P278
//全局雾效 13.3
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FogWithDepthTexture : PostEffectsBase{
public Shader fogShader;
private Material fogMaterial = null;
public Material material
{
get
{
fogMaterial = CheckShaderAndCreateMaterial(fogShader, fogMaterial);
return fogMaterial;
}