基於 Unity 引擎的遊戲開發進階之 場景渲染 & 光照進階

Unity 三維場景渲染

真實世界中陽光照射到樹木表面,經過樹木表面反射的光線,進入相機鏡頭。經過鏡頭的光線,最後照射到相機的感光元件上,感光元件記錄這些光線信息,保存為膠捲,或者量化為圖像文件。

遊戲場景是採用計算機技術描述的一個虛擬世界,這個虛擬世界與真實世界類似,場景中包含光、 物體以及相機、遊戲中的物體與場景光源發出的光線,發生反射或者折射現象,這些反射或者折射的光線,經過場景渲染過程,由虛擬相機記錄下來,生成虛擬相機所拍攝的照片。虛擬相機拍攝的照片顯示在電腦屏幕上,我們就看到了遊戲場景畫面。三維場景的渲染,本質上就是將計算機技術描述的 3D 場景,經過一系列計算過程,最終以 2D 圖像的形式呈現在顯示屏幕的過程。

Unity 場景渲染的要素:

  • 光源
  • 可繪製的遊戲對象
  • 材質
  • 攝像機

Unity 的四種基本光源:

  • 點光源(Point Light)
  • 方向光(Directional Light)
  • 聚光燈(Spot Light)
  • 面光源(Area Light)

我們通過設置光源的顏色、 強度以及它們在場景中的位置等參數,營造遊戲場景不同的光照效果。

可繪製的遊戲對象

大部分可繪製的遊戲對象都包含三個基本組件:

  • Transform
  • Mesh Filter
  • Mesh Renderer

其中 Transform 描述了物體的位置、 朝向和縮放比;Mesh Filter 指定了物體模型的網格信息;Mesh Renderer 指定了物體的渲染方式,物體的材質在 Mesh Renderer 組件中設置。

材質

在 Unity 中,我們用材質定義物體與光線相互作用後 產生的視覺效果。

攝像機

在 Unity 中我們藉助虛擬相機來觀察遊戲場景,虛擬相機的參數給出了觀察者在何處以何種角度和投影方式,來觀察遊戲場景。

Unity 渲染技術

添加了光源、 可繪製的物體、 材質和相機後,Unity 引擎可以渲染出對應的遊戲場景畫面。在遊戲開發中,把這些簡單的要素堆積在一起,無法獲得逼真的遊戲畫面,為了獲得更佳酷炫、 逼真的遊戲視覺畫面,需要在遊戲場景中使用 Unity 引擎的高級渲染技術,比如說,全局光照,著色器技術。


Unity 光照進階

光源類型和屬性

如上文所說,Unity 的四種基本光源分別是點光源,方向光,聚光燈,面光源。

點光源:

  • 從光源位置向所有方向發射出強度相等的光線
  • 在傳輸過程中不斷的衰減,當傳輸距離達到預設的極限距離 range 時,光線強度衰減為0
  • 適合模擬燈籠,火把等局部光源

方向光:

  • 不會衰減,它以相同的強度和方向,照亮空間中的所有物體
  • 位置信息沒有任何意義
  • 常用來模擬那些體積較大,距離遊戲場景非常遠的光源,比如日光和月光

聚光燈:

  • 聚光燈從光源位置開始向某個特定方向照射,照亮一個圓錐體的空間區域,在傳播過程中不斷衰減
  • 通常用於模擬人造光源,比如手電筒,車燈,探照燈等

面光源:

  • 使用一個矩形來定義,光線將從矩形的正面出發,照亮矩形前的一片區域
  • 適用於模擬廣告燈箱等光源
  • 不能作為實時光源

光源的屬性:

  • 類型以及類型相關的屬性
  • 烘培(Baking:烘培屬性 )
  1. 實時(Realtime)
  2. 烘培(Baked)
  3. 混合(Mixed)
  • 顏色
  1. Color:光源的顏色
  2. Intensity:光源的強度
  3. Bounce Intensity:間接光照的強度
  • 強度/反射強度
  • 陰影
  1. 無陰影(No Shadows)
  2. 硬陰影(Hard Shadows)
  3. 軟陰影(Soft Shadows)
  • 渲染類型
  • Cookies:通過紋理,給光源添加一層遮罩,改變光斑形狀

Halo

勾選 Halo 屬性,Unity 會在光源所在位置繪製一個球形的光暈。

Flare

設置光源產生的鏡頭光暈效果。

Render Mode

光源的渲染方式

  • 自動(Auto)
  • 重要(Important)
  • 不重要(Not Important)

對於重要的光源,Unity 會以逐像素的方式渲染被照射到物體。這種渲染更加精細,能夠產生陰影,但需要消耗較多的計算資源。對於不重要的光源, Unity 會以逐頂點,或者逐對象的方式來渲染被照射到的物體。這種渲染方式速度較快,但是質量不如逐向式的渲染方式,不能產生陰影。 Unity 會自動為重要程度為 Auto 的光源。

Culling Mask

選擇渲染方式 Culling Mask 設置光源所能照射到物體類型,可選項為當前項目中的 Layer。 只有被選中 Layer 包含的遊戲對象,才能受到這個光源的影響。

使用 Spot Light 模擬 FPS 遊戲中的手電筒效果。

這裡介紹一下 Flash Light Controller 腳本:

//玩家手電筒控制腳本public class FlashLightController : MonoBehaviour { private Light mylight; void Start () { //獲取玩家的聚光燈對象 mylight = GetComponent<Light> (); } void Update () { //根據玩家的輸入,開啟或關閉手電筒(調整聚光燈對象的亮度) if (CrossPlatformInputManager.GetButtonDown ("Fire3")) { if (mylight.intensity < 0.1) mylight.intensity = 5f; else mylight.intensity = 0.0f; } }}

陰影

陰影的產生

光線從光源出發,沿直線進行傳播。 在傳播過程中,光線遇到場景中的物體,在物體表面發生反射或者折射現象, 照亮了物體表面。 反射或折射發生後,如果光線改變傳播方向, 無法照射後續的物體,被照射物體就在後續物體區域產生了陰影。

我們換一種方式來理解陰影,假設有一台相機, 它和光源具有相同的位置,面向場景,此時相機觀察到的場景區域 就是被照亮的區域;反之,如果被相機觀察到的區域就會出現陰影。 Unity 也利用這種方法來渲染陰影。 它首先在光源位置放了一台臨時攝像機,渲染一遍場景, 渲染過程只計算當前視角下可見的物體的深度信息, 並以 shadowMap 的方法保存下來。shadowMap 記錄了場景中哪些物體離光源最近, 能夠被光線直接照射到。 場景中不在 shadowMap 圖像上的部分都是陰影區域。 最後當場景攝像機正式繪製場景時,參考這張 shadowMap 繪製出陰影。

Unity 渲染陰影的方法

  • 設置光源的 Shadow Type 為 Hard Shadows 或者 Soft Shadows
  • 設置 Shadow 的相關屬性
  • 設置光源的 Render Mode 為 Auto 或者 Important
  • 對於遮擋光線並在其他物體上產生陰影的對象,設置其 Mesh Renderer 組件的 Cast Shadows 為 On
  • 對於接收陰影的物體,在 Mesh Renderer 組件中,勾選其 Receive Shadows 屬性

有時,即使正確地設置了光源和遊戲對象的相關屬性, 也依然無法看到陰影。 羅列了造成該問題的一些原因供大家檢查。

  1. 顯卡可能過於古老,不支持陰影的渲染;
  2. 項目質量設置中關閉了陰影;
  3. 產生陰影的光源的 Rendering Mode 設置為 Auto, 有些情況下 Auto 光源會被 Unity 自動判定為非 Important 光源, 或者無法產生陰影。 如果認為這個光源的陰影效果很重要, 可以把它強制改為 Important 光源;
  4. Unity 中的透明物體是無法產生陰影的;
  5. 接收陰影的物體使用了 Standard Shader,並且 Rendering Mode 改為 Transparent, 這種情況下無法生成陰影;
  6. 接收陰影的物體的材質使用了其它逐頂點的著色器,無法產生陰影。

日常開發過程中開啟了陰影之後,我們會發現物體表面上出現一些奇怪的條紋或者斑點, 這是由於 Unity 在計算陰影時,ShadowMap 的精度不足造成的。 我們把這種錯誤的條紋稱為馬赫帶。 我們在光源對象 Light 組件中,稍微調高 Bias 屬性的值,可以消除馬赫帶。 這裡需要注意,如果 Bias 值設置過大,會導致陰影面積減小,或者消失。

推薦閱讀:

版本一席談:你挑擔來我牽馬,下路版本或將回歸
《大神》的背景故事:天照大神和勾鏡劍三神器
影游聯姻還有戲?華誼兄弟擬再購入英雄互娛股份
盤點S6番外篇:就是你了!我的宿敵

TAG:Unity游戏引擎 | 游戏 | 3D渲染 |