欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#使用Shader實(shí)現(xiàn)夜幕降臨倒計(jì)時(shí)的效果

 更新時(shí)間:2016年10月26日 09:40:59   作者:凱奧斯  
這篇文章主要介紹了C#使用Shader實(shí)現(xiàn)夜幕降臨倒計(jì)時(shí)的效果,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下

最近火爆全球的PC游戲Battlerite(戰(zhàn)爭儀式)在倒計(jì)時(shí)的會(huì)生成一種類似夜幕降臨的效果,會(huì)以戰(zhàn)場(chǎng)中心為圓心,某個(gè)長度為半徑的范圍外是暗的,而這個(gè)半徑會(huì)逐漸縮小,而圓之外的陰暗部分是附著地形的,本文就嘗試使用屏幕后處理的手段來實(shí)現(xiàn)這種效果。

(暫時(shí)缺少Battlerite的截圖,稍后會(huì)補(bǔ)上)

首先看效果圖:

注:本文參考了Tasharen Fog of War插件

創(chuàng)建一個(gè)C#腳本,命名為NightFall.cs,為NightFall類創(chuàng)建一些公共變量(nightColor,center和radius),另外還需要一個(gè)NightFall.shader。

首先,我們要確定這個(gè)效果是在場(chǎng)景渲染之后還未送到屏幕顯示之前的實(shí)現(xiàn)的,所以,NightFall腳本是要掛載到主Camera上的(添加特性[RequireComponent(typeof(Camera))]),并要實(shí)現(xiàn)OnRenderImage方法。

其次,在OnRenderImage方法里,我們最終需要調(diào)用Graphics.Blit方法,而這個(gè)方法的第三個(gè)參數(shù)是Material類型,所以我們需要在代碼里創(chuàng)建一個(gè)臨時(shí)材質(zhì),這個(gè)材質(zhì)使用了NightFall.shader。

再次,我們需要在Shader里面將屏幕坐標(biāo)轉(zhuǎn)換為世界坐標(biāo),來計(jì)算與世界中心的坐標(biāo),所以我們需要MVP的逆矩陣(參考Shader山下(十六)坐標(biāo)空間與轉(zhuǎn)換矩陣)。

最后,為了附著地形,我們需要在Shader計(jì)算深度,也就是坐標(biāo)點(diǎn)與攝像機(jī)的相對(duì)距離,所以需要攝像機(jī)的位置。

C#的代碼:

using UnityEngine;

[RequireComponent(typeof(Camera))] 
public class NightFall : MonoBehaviour 
{ 
public Shader shader; 
public Color nightColor = new Color(0.05f, 0.05f, 0.05f, 0.5f); 
public Vector3 center = Vector3.zero; 
public float radius = 10; 
Camera mCam; 
Matrix4x4 mInverseMVP; 
Material mMat; 
/// The camera we're working with needs depth. 
void OnEnable () 
{ 
mCam = GetComponent<Camera>(); 
mCam.depthTextureMode = DepthTextureMode.Depth; 
if (shader == null) shader = Shader.Find("Image Effects/NightFall"); 
} 
/// Destroy the material when disabled. 
void OnDisable () { if (mMat) DestroyImmediate(mMat); } 
/// Automatically disable the effect if the shaders don't support it. 
void Start () 
{ 
if (!SystemInfo.supportsImageEffects || !shader || !shader.isSupported) 
{ 
enabled = false; 
} 
} 
// Called by camera to apply image effect 
void OnRenderImage (RenderTexture source, RenderTexture destination) 
{ 
print (nightColor); 
print (destination); 
// Calculate the inverse modelview-projection matrix to convert screen coordinates to world coordinates 
mInverseMVP = (mCam.projectionMatrix * mCam.worldToCameraMatrix).inverse; 
if (mMat == null) 
{ 
mMat = new Material(shader); 
mMat.hideFlags = HideFlags.HideAndDontSave; 
} 
Vector4 camPos = mCam.transform.position; 
// This accounts for Anti-aliasing on Windows flipping the depth UV coordinates. 
// Despite the official documentation, the following approach simply doesn't work: 
// http://docs.unity3d.com/Documentation/Components/SL-PlatformDifferences.html 
if (QualitySettings.antiAliasing > 0) 
{ 
RuntimePlatform pl = Application.platform; 
if (pl == RuntimePlatform.WindowsEditor || 
pl == RuntimePlatform.WindowsPlayer || 
pl == RuntimePlatform.WindowsWebPlayer) 
{ 
camPos.w = 1f; 
} 
} 
mMat.SetVector("_CamPos", camPos); 
mMat.SetMatrix("_InverseMVP", mInverseMVP); 
mMat.SetColor("_NightColor", nightColor); 
mMat.SetVector ("_Center", center); 
mMat.SetFloat ("_Radius", radius); 
Graphics.Blit(source, destination, mMat); 
} 
}

Shader代碼:

Shader "Image Effects/NightFall" 
{ 
Properties 
{ 
_NightColor ("Night Color", Color) = (0.05, 0.05, 0.05, 0.05) 
_Center ("Center", Vector) = (0,0,0,0) 
_Radius ("Radius", float) = 10 
} 
SubShader 
{ 
Pass 
{ 
ZTest Always 
Cull Off 
ZWrite Off 
Fog { Mode off } 
Blend SrcAlpha OneMinusSrcAlpha 
CGPROGRAM 
#pragma vertex vert_img 
#pragma fragment frag vertex:vert 
#pragma fragmentoption ARB_precision_hint_fastest 
#include "UnityCG.cginc" 
sampler2D _CameraDepthTexture; 
uniform float4x4 _InverseMVP; 
uniform float4 _CamPos; 
uniform half4 _NightColor; 
uniform half4 _Center; 
uniform half _Radius; 
struct Input 
{ 
float4 position : POSITION; 
float2 uv : TEXCOORD0; 
}; 
void vert (inout appdata_full v, out Input o) 
{ 
o.position = mul(UNITY_MATRIX_MVP, v.vertex); 
o.uv = v.texcoord.xy; 
} 
float3 CamToWorld (in float2 uv, in float depth) 
{ 
float4 pos = float4(uv.x, uv.y, depth, 1.0); 
pos.xyz = pos.xyz * 2.0 - 1.0; 
pos = mul(_InverseMVP, pos); 
return pos.xyz / pos.w; 
} 
fixed4 frag (Input i) : COLOR 
{ 
#if SHADER_API_D3D9 || SHADER_API_D3D11 
float2 depthUV = i.uv; 
depthUV.y = lerp(depthUV.y, 1.0 - depthUV.y, _CamPos.w); 
float depth = UNITY_SAMPLE_DEPTH(tex2D(_CameraDepthTexture, depthUV)); 
float3 pos = CamToWorld(depthUV, depth); 
#else 
float depth = UNITY_SAMPLE_DEPTH(tex2D(_CameraDepthTexture, i.uv)); 
float3 pos = CamToWorld(i.uv, depth); 
#endif 
// Limit to sea level 
if (pos.y < 0.0) 
{ 
// This is a simplified version of the ray-plane intersection formula: t = -( N.O + d ) / ( N.D ) 
float3 dir = normalize(pos - _CamPos.xyz); 
pos = _CamPos.xyz - dir * (_CamPos.y / dir.y); 
} 
half4 col; 
float dis = length(pos.xz - _Center.xz); 
if (dis < _Radius) 
{ 
col = fixed4(0,0,0,0); 
} 
else 
{ 
col = _NightColor; 
} 
return col; 
} 
ENDCG 
} 
} 
Fallback off 
}

需要說明的幾個(gè)點(diǎn):

1、因?yàn)槠脚_(tái)差異性,為了兼容Direct3D,所以在C#和shader里通過CamPos(_CamPos)的w分量來調(diào)整uv坐標(biāo)。

2、這里雖然沒有聲明_MainTex,但是_MainTex實(shí)際上就是即將成像的屏幕圖像,所以這里的i.uv也就是指屏幕圖像的紋理坐標(biāo)。

3、_CameraDepthTexture是攝像機(jī)的深度紋理,通過UNITY_SAMPLE_DEPTH方法獲取深度。

4、CamToWorld里面,先是根據(jù)uv坐標(biāo)和深度depth創(chuàng)建了一個(gè)float4的坐標(biāo)值pos,然后對(duì)pos乘2減1是將這個(gè)坐標(biāo)范圍從[0,1]轉(zhuǎn)換到了[-1,1],對(duì)應(yīng)世界坐標(biāo)。然后使用傳入的MVP逆矩陣_InverseMVP乘以這個(gè)坐標(biāo)值,就得到了屏幕點(diǎn)的世界坐標(biāo)。最后將pos的xyz分量除以w分量,這里w分量表示因?yàn)檫h(yuǎn)近而產(chǎn)生的縮放值。

5、在計(jì)算過世界坐標(biāo)之后,對(duì)于y小于0的坐標(biāo)要做一下處理,將效果限制在海平面(sea level)之上,使用射線平面相交方程(ray-plane intersection formula)的簡化版本來處理。

6、最后根據(jù)距離返回色彩值。

如果要實(shí)現(xiàn)夜幕降臨倒計(jì)時(shí)的效果,只需要在控制腳本(C#)中獲取Camera上的NightFall組件,根據(jù)時(shí)間修改radius變量即可。

以上所述是小編給大家介紹的C#使用Shader實(shí)現(xiàn)夜幕降臨倒計(jì)時(shí)的效果,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

  • 用C#生成不重復(fù)的隨機(jī)數(shù)的代碼

    用C#生成不重復(fù)的隨機(jī)數(shù)的代碼

    我們?cè)谧瞿茏詣?dòng)生成試卷的考試系統(tǒng)時(shí),常常需要隨機(jī)生成一組不重復(fù)的題目,在.net Framework中提供了一個(gè)專門用來產(chǎn)生隨機(jī)數(shù)的類System.Random
    2013-02-02
  • c#通過DES加密算法加密大文件的方法

    c#通過DES加密算法加密大文件的方法

    這篇文章主要介紹了c#通過DES加密算法加密大文件的方法,涉及C#文件操作與DES加密的相關(guān)技巧,需要的朋友可以參考下
    2015-05-05
  • C#如何遍歷Dictionary

    C#如何遍歷Dictionary

    這篇文章主要為大家詳細(xì)介紹了C#遍歷Dictionary的方法,.NET中的Dictionary是鍵/值對(duì)的集合,使用起來比較方便,Dictionary也可以用KeyValuePair來迭代遍歷,感興趣的小伙伴們可以參考一下
    2016-04-04
  • C#修改及重置電腦密碼DirectoryEntry實(shí)現(xiàn)方法

    C#修改及重置電腦密碼DirectoryEntry實(shí)現(xiàn)方法

    這篇文章主要介紹了C#修改及重置電腦密碼DirectoryEntry實(shí)現(xiàn)方法,實(shí)例分析了C#修改及重置電腦密碼的相關(guān)技巧,需要的朋友可以參考下
    2015-05-05
  • C#實(shí)現(xiàn)日期格式轉(zhuǎn)換的公共方法類實(shí)例

    C#實(shí)現(xiàn)日期格式轉(zhuǎn)換的公共方法類實(shí)例

    這篇文章主要介紹了C#實(shí)現(xiàn)日期格式轉(zhuǎn)換的公共方法類,結(jié)合完整實(shí)例形式分析了C#針對(duì)各種常見日期格式的轉(zhuǎn)換方法,涉及C#字符串、日期、時(shí)間相關(guān)操作技巧,需要的朋友可以參考下
    2017-01-01
  • c#實(shí)現(xiàn)輸出的字符靠右對(duì)齊的示例

    c#實(shí)現(xiàn)輸出的字符靠右對(duì)齊的示例

    下面小編就為大家分享一篇c#實(shí)現(xiàn)輸出的字符靠右對(duì)齊的示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2017-12-12
  • C# Socket通信的實(shí)現(xiàn)(同時(shí)監(jiān)聽多客戶端)

    C# Socket通信的實(shí)現(xiàn)(同時(shí)監(jiān)聽多客戶端)

    這篇文章主要介紹了C# Socket通信的實(shí)現(xiàn)(同時(shí)監(jiān)聽多客戶端),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • C#實(shí)現(xiàn)簡單學(xué)生成績管理系統(tǒng)

    C#實(shí)現(xiàn)簡單學(xué)生成績管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)簡單學(xué)生成績管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • C#如何修改項(xiàng)目名圖文詳解

    C#如何修改項(xiàng)目名圖文詳解

    最近開發(fā)工作接近尾聲,客戶來要求更換項(xiàng)目的名稱,差不多要變更整個(gè)解決方案中項(xiàng)目名稱,引用等等,這個(gè)工作量還是很大的,這篇文章主要給大家介紹了關(guān)于C#如何修改項(xiàng)目名的相關(guān)資料,需要的朋友可以參考下
    2023-01-01
  • C#編程自學(xué)之流程控制語句

    C#編程自學(xué)之流程控制語句

    本文主要介紹流程控制語句,主要包括條件控制語句和循環(huán)控制語句的使用。讀者學(xué)習(xí)本文后,應(yīng)該熟練掌握C#控制語句的主要用途和使用方法,了解這些控制語句的區(qū)別。
    2015-10-10

最新評(píng)論