一個基於Ogre,適合2.5D遊戲比較完美的陰影解決方案
這是我以前升級Ogre引擎,實現的一個方案,願意拿出來分享下經驗。
每個精通Ogre的程式設計師,都會對Ogre自帶的陰影方案感到失望,不管是模板陰影,還是投影陰影,都是固定渲染管線的陰影,效果都不好。
暢遊《天龍八部》都升級到3了,還採用以前的陰影方案,說明要找個理想的方案替換以前的真是很難。
天龍的方案是,人物用模板陰影,場景用靜態烘培的陰影貼圖貼地形上。效果一般般,這是以前很多遊戲的做法。由於模板陰影是基於模型頂點的,沒法支援alpha test。
那麼樹葉這種帶有alpha test的模型的陰影用不了。而靜態烘培的光照圖,精度決定了用在樹木這種模型上的效果很不好,而且都不支援自投影,
而投影陰影,本身有3個缺陷,比如反向投影,無自投影,和地形穿插的投影有穿幫等bug,也不太實用,很早就被天龍拋棄了。
固定管線的陰影方案遲早都要被淘汰,而基於shader實現的shadow map陰影技術是比較主流的高階陰影技術。
shadow map的技術分支,就太多了,幾十種都有,但每種技術都是不完美的,也有各種各樣的問題。國外次世代遊戲多用VSM和CSM這種。
我要考慮的前提效率。 效率必須是第一位,在國內開發引擎,任何NB的效果,如果效率有問題,就沒任何適用價值。
權衡一下,結合了自己2.5D鎖視角遊戲的實際情況,我選擇了傳統的depth shawow map。
傳統的陰影很多問題,需要很多技術來改進才有實用價值。
比如陰影精度問題,邊緣鋸齒,某些視角陰影自走樣等等。
改進質量的方法:
1)攝像機聚焦到可視區域,提高陰影的精度。
2)陰影紋理大小採用1024或2048來提高陰影的精度。
3)由於看不到很遠的地方,可以控制陰影距離,再次提高陰影精度,如果是純3D遊戲大場景,能看很遠,就需要換成PSSM技術。
4)4X4的PCF濾波來實現簡單的軟陰影,消除生硬的邊緣。
5)採用基於梯度的深度偏移減少自投影走樣
改進效率的方法:
1)只支援單光源的陰影,那麼就不需要迭代每個光源,陰影貼花的時候採用modulate的方式,而不是add,這樣只需增加一個紋理單元,而不會增加渲染pass
,由於一個pass,那麼陰影和霧也可以完美結合。
其他要解決的問題
1)樹木這種alpha test的模型的投射和接受陰影。
效果圖
陰影質量令人滿意,且支援自投影,alpha test的竹子,也支援陰影。以上效果都在我筆記本上用地形編輯器測試的
效率方面,和傳統的投影陰影相比,也是渲染一張陰影圖,在貼花方面並沒有增加渲染批次,材質指令碼也簡單
// 2012.12.5 luoyinan
// 陰影投射材質 浮點紋理
material Ogre/DepthShadowmap/Caster/Float
{
technique
{
scheme shadow_map
pass
{
fog_override true none
vertex_program_ref Ogre/DepthShadowmap/CasterVP
{
}
fragment_program_ref Ogre/DepthShadowmap/CasterFP
{
}
}
}
}
// 基本的自投影材質
material Ogre/DepthShadowmap/BasicTemplateMaterial
{
technique
{
scheme shadow_map
pass
{
// Vertex program reference
vertex_program_ref Ogre/DepthShadowmap/ReceiverVP_Entity
{
}
// Fragment program
fragment_program_ref Ogre/DepthShadowmap/ReceiverFP_Entity
{
}
texture_unit
{
content_type shadow
tex_address_mode border
tex_border_colour 1 1 1
}
texture_unit
{
texture_alias <baseTexture>
}
}
}
technique
{
pass
{
diffuse vertexcolour
texture_unit
{
texture_alias <baseTexture>
}
}
}
}
// 支援alpha test和雙面的 陰影自投影材質,
material Ogre/DepthShadowmap/AlphaTestTemplateMaterial
{
technique
{
scheme shadow_map
pass
{
alpha_rejection greater 128
cull_hardware none
// Vertex program reference
vertex_program_ref Ogre/DepthShadowmap/ReceiverVP_Entity
{
}
// Fragment program
fragment_program_ref Ogre/DepthShadowmap/ReceiverFP_Entity
{
}
texture_unit
{
content_type shadow
tex_address_mode border
tex_border_colour 1 1 1
}
texture_unit
{
texture_alias <baseTexture>
}
}
}
technique
{
pass
{
diffuse vertexcolour
alpha_rejection greater 128
cull_hardware none
texture_unit
{
texture_alias <baseTexture>
}
}
}
}
cg檔案暫時保密。