文章目录
深度纹理实际就是一张渲染纹理,它里面存储的像素值是一个高精度的深度值,范围是[0,1],非线性分布;
如何获取
脚本中:
深度:camera.depthTextureMode = DepthTextureMode.Depth
深度+法线:camera.depthTextureMode = DepthTextureMode.DepthNormals
深度和深度+法线:camera.depthTextureMode | = DepthTextureMode.Depth
camera.depthTextureMode | = DepthTextureMode.DepthNormals
采样:SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv)——绝大多数情况tex2D也可以,这里防止某些平台特殊处理;
查看
在片元着色器中用代码输出深度和法线值后如果画面全黑或全白,将摄像机的远剪裁平面调小;
运动模糊
运动模糊的另一种方法是速度映射图:利用深度纹理在片元着色器中为每个像素计算其在世界空间下的位置,计算前一帧和当前帧的位置差,生成该像素的速度。
脚本
using UnityEngine;
using System.Collections;
public class MotionBlurWithDepthTexture : PostEffectsBase {
public Shader motionBlurShader;
private Material motionBlurMaterial = null;
public Material material {
get {
motionBlurMaterial = CheckShaderAndCreateMaterial(motionBlurShader, motionBlurMaterial);
return motionBlurMaterial;
}
}
private Camera myCamera;
public Camera camera {
get {
if (myCamera == null) {
myCamera = GetComponent<Camera>();
}
return myCamera;
}
}
[Range(0.0f, 1.0f)]
public float blurSize = 0.5f;
//保存上一帧的视角*投影矩阵
private Matrix4x4 previousViewProjectionMatrix;
void OnEnable() {
camera.depthTextureMode |= DepthTextureMode.Depth;
previousViewProjectionMatrix = camera.projectionMatrix * camera.worldToCameraMatrix;
}
void OnRenderImage (RenderTexture src, RenderTexture dest) {
if (material != null) {
material.SetFloat("_BlurSize", blurSize);
material.SetMatrix("_PreviousViewProjectionMatrix", previousViewProjectionMatrix);
Matrix4x4 currentViewProjectionMatrix = camera.projectionMatrix * camera.worldToCameraMatrix;
//当前帧的视角*投影
Matrix4x4 currentViewProjectionInverseMatrix = currentViewProjectionMatrix.inverse;
material.SetMatrix("_CurrentViewProjectionInverseMatrix", currentViewProjectionInverseMatrix);
previousViewProjectionMatrix = currentViewProjectionMatrix;
Graphics.Blit (src, dest, material);
} else {
Graphics.Blit(src, dest);
}
}
}
shader
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Unity Shaders Book/Chapter 13/Motion Blur With Depth Texture" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {
}
_BlurSize ("Blur Size", Float) = 1.0
}
SubShader {
CGINCLUDE
#include "UnityCG.cginc"
sampler2D _MainTex;
half4 _MainTex_TexelSize;
//unity传递的深度纹理
sampler2D _CameraDepthTexture;
//脚本传递的矩阵
float4x4 _CurrentViewProjectionInverseMatrix;
float4x4 _PreviousViewProjectionMatrix;
half _BlurSize;
struct v2f {
float4 pos : SV_POSITION;
half2 uv : TEXCOORD0;
half2 uv_depth : TEXCOORD1;
};
v2f vert(appdata_img v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.texcoord;
o.uv_depth = v.texcoord;
//平台差异化处理
#if UNITY_UV_STARTS_AT_TOP
if (_MainTex_TexelSize.y < 0)
o.uv_depth.y = 1 - o.uv_depth.y;
#endif
return o;
}
fixed4 frag(v2f i) : SV_Target {
// 对深度纹理采样得到深度值
float d = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv_depth);
//将深度值重新映射回NDC
float4 H = float4(i.uv.x * 2 - 1, i.uv.y * 2 - 1, d * 2 - 1, 1);
// 视角*投影逆矩阵变换
float4 D = mul(_CurrentViewProjectionInverseMatrix, H);