Chapter13_使用深度和法線紋理

深度紋理

深度紋理實際就是一張渲染紋理,只不過它裏邊存儲的是像素值不是顏色值,而是一個高精度的深度值。

頂點座標轉化到NDC(歸一化的設備座標)下的座標的z分量就是頂點的深度值。NDC中,z分量範圍在[-1,1],爲了讓z分量可以存到一張紋理中,需要使用公式將z分量映射:

                                                                          d = 0.5 * \large z_{ndc} + 0.5

Unity獲取深度紋理方式分爲兩種方式:

在Unity中,可以讓攝像機生成一張深度紋理或是深度+法線紋理。

1.當只生成一張深度紋理時,Unity在使用延遲渲染路徑時(渲染路徑決定了光照如何應用到Shader中,決定了把光源信息和處理後的光照信息放到那些數據中。),直接從G-buffer中獲取深度緩存

2.在使用前向渲染路勁時,渲染深度紋理通過使用着色器替換技術,渲染需要的不透明物體,並使用它投射陰影時使用的Pass(即LightMode 設置爲ShadowCaster 的Pass)來得到深度紋理。具體實現是,Unity會使用着色器替換技術渲染那些渲染類型(即SubShader的RenderType標籤)爲Opaque的物體,判斷它們使用的渲染隊列是否 <= 2500,如果滿足,就把它渲染到深度和法線紋理中。

深度紋理的精度通常是24位活16位。如果選擇生成一張深度+法線紋理,Unity會創建一張和屏幕分辨率相同,精度爲32位(每個通道8位)的紋理。法線信息存到R和G通道。深度信息存到B和A通道。

  • 使用延遲渲染路徑時:Unity只需要合併深度和法線緩存即可。
  • 使用前向渲染路勁時:默認不會創建法線緩存。因此Unity底層使用了一個單獨的Pass把整個場景再次渲染一遍。這個Pass被放在一個內置Shader中。

代碼具體獲取深度紋理步驟:

  1. camera.depehtTextureMode = DepthTextureMode.Depth; //獲取深度紋理
  2. Shader中直接訪問特定紋理名稱(_CameraDepthTexture)即可。

camera.depehtTextureMode = DepthTextureMode.DepthNormals;//獲取深度紋理 + 法線紋理

camera.depehtTextureMode |= DepthTextureMode.Depth;

camera.depehtTextureMode = DepthTextureMode.DepthNormals; 以上兩句獲取一張深度紋理 + 一張深度+法線紋理

採樣深度紋理,非線性變線性推導。。。以後補上。。

當攝像機遠裁剪平面的距離過大,會導致距離攝像機較近的物體被映射的深度值非常小,生成的深度紋理變"黑"。相反,遠裁剪平面過大,會導致距離攝像機較近的物體被映射的深度值偏大。生成的深度紋理變"白"。


實踐:

1.運動模糊

速度映射圖模擬運動模糊。速度映射圖中存儲了每個像素的速度,然後使用這個速度決定模糊的方向和大小。

生成速度映射紋理有兩種方式:

  1. 把場景中所有物體都渲染到一張紋理中,不過這種方法需要修改場景所有的Shader。
  2. 使用深度紋理在片元着色器中爲每個像素計算世界空間下的位置(使用當前幀的視角*投影矩陣的逆矩陣計算)。當得到世界空間下的頂點座標後,然後使用前一幀視角*投影矩陣對其進行變換,得到該頂點位置在前一幀的NDC座標。當前幀頂點的NDC座標 - 前一幀的NDC位置得到該像素的速度。優點是屏幕後統一處理計算,缺點是兩次矩陣變換,效率低。

 

Shader "Chan/Chapter 13/Motion Blur With Depth Texture" {
	Properties
	{
		_MainTex("Base Tex",2D) = "white"{}
		_BlurSize("Blur Size",float) = 1.0
	}
		SubShader
		{
			CGINCLUDE

			#include "UnityCG.cginc"

			sampler2D _MainTex;
			half4 _MainTex_TexelSize;
			//通過_CameraDepthTexture 直接就能訪問到當前攝像機的深度紋理
			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;

				//多張渲染紋理,可能uv採樣座標會出問題 需要根據平臺判斷
				# 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
			{
				//不同平臺要通過uv採樣深度紋理得到深度值,可能有差異。使用宏定義 內部處理了。SAMPLE_DEPTH_TEXTURE 
				float d = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv_depth);
				//歸一化設備座標系下的座標[-1,1],紋理通道值[0,1] 所以存儲到深度紋理時,進行了映射。此處爲反映射
				//歸一化設備座標系下的座標座標(x,y值由uv映射而來,z值由深度值映射而來)
				float4 h = float4(i.uv.x * 2 - 1,i.uv.y * 2 - 1,d * 2 - 1,1);
				//歸一化設備座標系下的座標 乘以當前攝像機 * 投影矩陣的逆矩陣 得到世界空間座標系的座標
				float4 D = mul(_CurrentViewProjectionInverseMatrix,h);
				//世界空間座標系的座標
				float4 worldPos = D / D.w;

				//當前世界座標乘以 當前攝像機視角 * 投影矩陣 得到上一幀時候在歸一化設備座標系下的座標
				float4 currentPos = h;
				float4 previousPos = mul(_PreviousViewProjectionMatrix,worldPos);
				previousPos /= previousPos.w;

				//得到速度
				float2 velocity = (currentPos.xy - previousPos.xy) / 2.0f;

				float2 uv = i.uv;
				float4 c = tex2D(_MainTex,uv);
				uv += velocity * _BlurSize;//控制紋理採樣距離
				//採樣三地方,取了個平均值
				for (int it = 1; it < 3; it++, uv += velocity * _BlurSize)
				{
					float4 currentColor = tex2D(_MainTex,uv);
					c += currentColor;
				}
				c /= 3;

				return fixed4(c.rgb,1.0);
			}

			ENDCG

		Pass
			{
				//屏幕後處理的標配
				ZTest Always Cull Off 
				ZWrite Off
				CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				ENDCG
			}
		}
		Fallback Off
}

配合使用的C#腳本:

 

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;
            //1.當前幀的(視角 * 投影矩陣)的逆矩陣,用於將頂點座標從歸一化的設備座標變換到世界空間下
            //2.世界空間下的座標,經過上一幀的 攝像機視角 * 投影矩陣轉換,得到上一幀的歸一化設備座標
            //3.當前幀的歸一化設備空間座標 - 上一幀的歸一化設備空間座標 = 當前頂點的速度     
            Matrix4x4 currentViewProjectionInverseMatrix = currentViewProjectionMatrix.inverse;
			material.SetMatrix("_CurrentViewProjectionInverseMatrix", currentViewProjectionInverseMatrix);
			previousViewProjectionMatrix = currentViewProjectionMatrix;

			Graphics.Blit (src, dest, material);
		} else {
			Graphics.Blit(src, dest);
		}
	}
}

註解:

   歸一化設備座標系(NDC)下的座標(x,y值由uv映射而來,z值由深度值映射而來)

   NDC(歸一化的設備座標)下的座標的z分量就是頂點的深度值。NDC中,z分量範圍在[-1,1],爲了讓z分量可以存到一張紋理中,需要使用公式將z分量映射:

                                                                          d = 0.5 * \large z_{ndc} + 0.5

  因此採樣深度紋理後,需要進行反映射:\large z_{ndc} = d * 2 - 1


2.全局霧效 

基於屏幕後處理。根據深度紋理來重建每個像素在世界空間中的位置。

2.1重建世界座標

float4 worldPos = _WorldSpaceCameraPos + linearDepth * interpolatedRay;首先獲取世界空間下的攝像機位置WorldSpaceCameraPos 。linearDepth * interpolatedRay 該像素相對於攝像機位置的偏移量。

  • 攝像機位置WorldSpaceCameraPos 。
  • linearDepth  = 深度紋理得到的線性深度值。\large z_{ndc} = d * 2 - 1
  • interpolatedRay 頂點着色器輸出並插值後得到的射線,它不僅包含了該像素到攝像機的方向,也包含了距離信息。

 

 

scale = |TL|/Near 

 

2.2霧的計算

使用一個霧效係數 f ,混合原始顏色和霧的顏色。

float3 afterFog = f * fogColor + ( 1 - f ) * origColor;

Unity內置霧效,有三種方式計算次數f:

  • Linear(線性):

     \LARGE f = \tfrac{(d_{max} - |z|)}{(d_{max}-d_{min})}

dmax 和 dmin表示受霧影響的最大最小距離。

  • Exponential(指數): 

\LARGE f = e^{-d*|z|}

d 控制霧的濃度。 b 

  • Exponential Squared(指數): 

\LARGE f = e^{-(d-|z|)^{2}}

d 控制霧的濃度。

本文采樣類似線性霧效計算方式。

\LARGE f = \tfrac{(H_{end} - y)}{(H_{end}-H_{start})}

Hend 和 Hsart分辨代表受霧影響的起始高度和終止高度。 

 

Shader "Chan/Chapter 13/Fog With Depth Texture" {
	Properties
	{
		_MainTex("Main Tex",2D) = "white"{}
		//霧密度
		_FogDensity("Fog Density",float) = 1.0
		//霧顏色
		_FogColor("Fog Color",Color) = (1,1,1,1)
		//霧開始高度
		_FogStart("Fog Start",float) = 0.0
		//霧結束高度
		_FogEnd("Fog End",float) = 1.0
	}
	SubShader
	{
		CGINCLUDE

		#include "UnityCG.cginc"

			float4x4 _FrustumCornersRay;
			sampler2D _MainTex;
			half4 _MainTex_TexelSize;
			//深度紋理
			sampler2D _CameraDepthTexture;

			half _FogDensity;
			fixed4 _FogColor;
			float _FogStart;
			float _FogEnd;

			struct v2f
			{
				float4 pos:SV_POSITION;
				half2 uv:TEXCOORD0;
				half2 uv_depth:TEXCOORD1;
				//存儲
				float4 interpolateRay:TEXCOORD2;
			};

			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

				//屏幕後全局所用的模型是一個四邊形網格,只包含四個頂點
				//判斷當前頂點是哪個頂點,此處使用uv紋理座標判斷。左下->右下->右上->左上
				int index = 0;
				if (v.texcoord.x < 0.5 && v.texcoord.y < 0.5)
				{
					index = 0;
				}
				else if (v.texcoord.x > 0.5 && v.texcoord.y < 0.5)
				{
					index = 1;
				}
				else if (v.texcoord.x > 0.5 && v.texcoord.y > 0.5)
				{
					index = 2;
				}
				else
				{
					index = 3;
				}	

				//平臺,設置差異 可能導致左下->右下->右上->左上錯亂,跟c#腳本對不上,差異化處理
				#if UNITY_UV_STARTS_AT_TOP
				if (_MainTex_TexelSize.y < 0)
				{
					index = 3 - index;
				}
				#endif
				o.interpolateRay = _FrustumCornersRay[index];
				return o;
			}

			fixed4 frag(v2f i) :SV_Target
			{
				//不同平臺要通過uv採樣深度紋理得到深度值,可能有差異。使用宏定義 內部處理了。SAMPLE_DEPTH_TEXTURE 
				float linearDepth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv_depth));
			    //計算得到某個像素點的世界座標
				float3 worldPos = _WorldSpaceCameraPos + linearDepth * i.interpolateRay.xyz;
				//根據公式,霧效密度
				float fogDensity = (_FogEnd - worldPos.y) / (_FogEnd - _FogStart);
				fogDensity = saturate(fogDensity * _FogDensity);
				fixed4 finalColor = tex2D(_MainTex,i.uv);
				//原始紋理顏色混合霧效顏色 = 最終顏色
				finalColor.rgb = lerp(finalColor.rgb,_FogColor.rgb,fogDensity);
				return finalColor;
			}
		ENDCG

		Pass
		{
			ZTest Always Cull Off
			ZWrite Off

			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			ENDCG
		}
	}

	FallBack Off
}

註解:

                //不同平臺要通過uv採樣深度紋理得到深度值,可能有差異。使用宏定義 內部處理了。SAMPLE_DEPTH_TEXTURE 
                float linearDepth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv_depth));
                

                //計算得到某個像素點的世界座標 
                //攝像機世界座標 + 像素點相對於攝像機的偏移量(linearDepth * i.interpolateRay.xyz) = 像素的世界座標
               //linearDepth * i.interpolateRay.xyz = dist = depth * scale
                float3 worldPos = _WorldSpaceCameraPos + linearDepth * i.interpolateRay.xyz;

 

配合使用的C#腳本: 

using UnityEngine;
using System.Collections;

public class FogWithDepthTexture : PostEffectsBase {

	public Shader fogShader;
	private Material fogMaterial = null;

	public Material material {  
		get {
			fogMaterial = CheckShaderAndCreateMaterial(fogShader, fogMaterial);
			return fogMaterial;
		}  
	}

	private Camera myCamera;
	public Camera camera {
		get {
			if (myCamera == null) {
				myCamera = GetComponent<Camera>();
			}
			return myCamera;
		}
	}

	private Transform myCameraTransform;
	public Transform cameraTransform {
		get {
			if (myCameraTransform == null) {
				myCameraTransform = camera.transform;
			}

			return myCameraTransform;
		}
	}

    //霧效密度上限
	[Range(0.0f, 3.0f)]
	public float fogDensity = 1.0f;

    //霧效顏色
	public Color fogColor = Color.white;

    //霧效起始高度
	public float fogStart = 0.0f;
    //霧效結束高度
	public float fogEnd = 2.0f;

	void OnEnable() {
		camera.depthTextureMode |= DepthTextureMode.Depth;
	}
	
	void OnRenderImage (RenderTexture src, RenderTexture dest) {
		if (material != null) {
			Matrix4x4 frustumCorners = Matrix4x4.identity;

			float fov = camera.fieldOfView;
			float near = camera.nearClipPlane;
			float aspect = camera.aspect;

			float halfHeight = near * Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad);
			Vector3 toRight = cameraTransform.right * halfHeight * aspect;
			Vector3 toTop = cameraTransform.up * halfHeight;

			Vector3 topLeft = cameraTransform.forward * near + toTop - toRight;
			float scale = topLeft.magnitude / near;

            // 與採樣後的深度值相乘得到四個點相對於攝像機的偏移量
			topLeft.Normalize();
			topLeft *= scale;

			Vector3 topRight = cameraTransform.forward * near + toRight + toTop;
			topRight.Normalize();
			topRight *= scale;

			Vector3 bottomLeft = cameraTransform.forward * near - toTop - toRight;
			bottomLeft.Normalize();
			bottomLeft *= scale;

			Vector3 bottomRight = cameraTransform.forward * near + toRight - toTop;
			bottomRight.Normalize();
			bottomRight *= scale;

			frustumCorners.SetRow(0, bottomLeft);
			frustumCorners.SetRow(1, bottomRight);
			frustumCorners.SetRow(2, topRight);
			frustumCorners.SetRow(3, topLeft);

            //將攝像機近裁剪平面的 左下->右下->右上->左上 計算出來後,傳入shader中
            material.SetMatrix("_FrustumCornersRay", frustumCorners);

			material.SetFloat("_FogDensity", fogDensity);
			material.SetColor("_FogColor", fogColor);
			material.SetFloat("_FogStart", fogStart);
			material.SetFloat("_FogEnd", fogEnd);

			Graphics.Blit (src, dest, material);
		} else {
			Graphics.Blit(src, dest);
		}
	}
}

 

3.邊緣檢測

使用Sobel卷積算子進行邊緣,物體的紋理,陰影可以能被描邊。使用Roberts算子來替代。

Roberts算子本質是計算左上角-右下角的差值,乘以右上角-左下角的差值,作爲評估邊緣的依據。

具體代碼操作:

通過uv採樣深度+法線紋理的某點的相鄰上下左右四點信息,然後比較左上-右下,右上-左下的深度值和 "法線"值,當深度值和法線值小於某個閾值,證明此點爲邊緣點。

Shader "Chan/Chapter 13/Edge Detection Normals And Depth" {
	Properties {
		_MainTex ("Base (RGB)", 2D) = "white" {}
		//邊緣和原圖混合比例
		_EdgeOnly ("Edge Only", Float) = 1.0
		//邊緣顏色
		_EdgeColor ("Edge Color", Color) = (0, 0, 0, 1)
		//背景色
		_BackgroundColor ("Background Color", Color) = (1, 1, 1, 1)
		//採樣距離
		_SampleDistance ("Sample Distance", Float) = 1.0
		//xy分量 分別對應了法線和深度的檢測靈敏度
		_Sensitivity ("Sensitivity", Vector) = (1, 1, 1, 1)
	}
	SubShader {
		CGINCLUDE
		
		#include "UnityCG.cginc"
		
		sampler2D _MainTex;
		half4 _MainTex_TexelSize;
		fixed _EdgeOnly;
		fixed4 _EdgeColor;
		fixed4 _BackgroundColor;
		float _SampleDistance;
		half4 _Sensitivity;
		
		//深度+法線 紋理
		sampler2D _CameraDepthNormalsTexture;
		
		struct v2f {
			float4 pos : SV_POSITION;
			half2 uv[5]: TEXCOORD0;
		};
		  
		v2f vert(appdata_img v) {
			v2f o;
			o.pos = UnityObjectToClipPos(v.vertex);
			
			half2 uv = v.texcoord;
			o.uv[0] = uv;
			
			#if UNITY_UV_STARTS_AT_TOP
			if (_MainTex_TexelSize.y < 0)
				uv.y = 1 - uv.y;
			#endif
			
			//採樣相鄰的四個區域,以便進行卷積計算
			o.uv[1] = uv + _MainTex_TexelSize.xy * half2(1,1) * _SampleDistance;
			o.uv[2] = uv + _MainTex_TexelSize.xy * half2(-1,-1) * _SampleDistance;
			o.uv[3] = uv + _MainTex_TexelSize.xy * half2(-1,1) * _SampleDistance;
			o.uv[4] = uv + _MainTex_TexelSize.xy * half2(1,-1) * _SampleDistance;
					 
			return o;
		}
		
		half CheckSame(half4 center, half4 sample) {

			//因爲值比較兩點的法線差值,因此不需要吧xy分量轉化爲整整的法線
			half2 centerNormal = center.xy;
			//將存在紋理信息zw分量中的深度值轉化爲float
			float centerDepth = DecodeFloatRG(center.zw);
			
			half2 sampleNormal = sample.xy;
			float sampleDepth = DecodeFloatRG(sample.zw);
			
			// difference in normals
			// do not bother decoding normals - there's no need here
			half2 diffNormal = abs(centerNormal - sampleNormal) * _Sensitivity.x;
			//傳入的兩個參數的“法線”差值小於0.1,判定法線有差異
			int isSameNormal = (diffNormal.x + diffNormal.y) < 0.1;
			// difference in depth
			float diffDepth = abs(centerDepth - sampleDepth) * _Sensitivity.y;
			//傳入的兩個參數的深度差值小於0.1,判定深度有差異
			int isSameDepth = diffDepth < 0.1 * centerDepth;
			
			// return:
			// 1 - 差異比較小,不判定爲邊緣點
			// 0 - 差異比較大,判定爲邊緣點
			return isSameNormal * isSameDepth ? 1.0 : 0.0;
		}
		
		fixed4 fragRobertsCrossDepthAndNormal(v2f i) : SV_Target {
			//通過uv 採樣四個點
			half4 sample1 = tex2D(_CameraDepthNormalsTexture, i.uv[1]);
			half4 sample2 = tex2D(_CameraDepthNormalsTexture, i.uv[2]);
			half4 sample3 = tex2D(_CameraDepthNormalsTexture, i.uv[3]);
			half4 sample4 = tex2D(_CameraDepthNormalsTexture, i.uv[4]);
			
			half edge = 1.0;
			
			//深度和法線值相差都很大的情況下,才認爲此點爲邊緣點
			edge *= CheckSame(sample1, sample2);
			edge *= CheckSame(sample3, sample4);
			
			fixed4 withEdgeColor = lerp(_EdgeColor, tex2D(_MainTex, i.uv[0]), edge);
			fixed4 onlyEdgeColor = lerp(_EdgeColor, _BackgroundColor, edge);
			
			return lerp(withEdgeColor, onlyEdgeColor, _EdgeOnly);
		}
		
		ENDCG
		
		Pass { 
			ZTest Always Cull Off 
		    ZWrite Off
			
			CGPROGRAM      
			
			#pragma vertex vert  
			#pragma fragment fragRobertsCrossDepthAndNormal
			
			ENDCG  
		}
	} 
	FallBack Off
}

配合使用的C#腳本:

using UnityEngine;
using System.Collections;

public class EdgeDetectNormalsAndDepth : PostEffectsBase {

	public Shader edgeDetectShader;
	private Material edgeDetectMaterial = null;
	public Material material {  
		get {
			edgeDetectMaterial = CheckShaderAndCreateMaterial(edgeDetectShader, edgeDetectMaterial);
			return edgeDetectMaterial;
		}  
	}

	[Range(0.0f, 1.0f)]
	public float edgesOnly = 0.0f;

	public Color edgeColor = Color.black;

	public Color backgroundColor = Color.white;

    //採樣距離
	public float sampleDistance = 1.0f;
    //深度值靈敏度
	public float sensitivityDepth = 1.0f;
    //法線值靈敏度
	public float sensitivityNormals = 1.0f;
	
	void OnEnable() {
        //獲取深度+法線紋理
		GetComponent<Camera>().depthTextureMode |= DepthTextureMode.DepthNormals;
	}

	[ImageEffectOpaque]
	void OnRenderImage (RenderTexture src, RenderTexture dest) {
		if (material != null) {
			material.SetFloat("_EdgeOnly", edgesOnly);
			material.SetColor("_EdgeColor", edgeColor);
			material.SetColor("_BackgroundColor", backgroundColor);
			material.SetFloat("_SampleDistance", sampleDistance);
			material.SetVector("_Sensitivity", new Vector4(sensitivityNormals, sensitivityDepth, 0.0f, 0.0f));

			Graphics.Blit(src, dest, material);
		} else {
			Graphics.Blit(src, dest);
		}
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章