1. 程式人生 > >遊戲模型模糊高亮邊緣效果實現shader

遊戲模型模糊高亮邊緣效果實現shader

遊戲中因為有時怪物太多,常常需要對攻擊的怪物高亮,對於遊戲體驗都有很大的提升,也增加了玄幻色彩,如下所示:


網上也有不少實現這種效果的例子,《introduce  to DirectX3D game programming》 書中介紹有法線放大的方法,這種方法對於規則模型,比如茶壺(teapot)是有很好的效果,見部落格中所示, 但是遊戲中也有不少NPC 是穿有衣服,衣袂飄飄, 此時這種片狀的模型在邊緣是沒有法線的,所以往往無法描邊,最後的效果必然是不完整的。


鑑於此,重新思考法線放大方法。因為法線放大最終的效果就是為了實現把單色渲染的模型背景圖沿周圍擴大,我們可以採用別的方法達到同樣的效果。對影象熟悉的應該會想到膨脹(inflation)。所以下面所講的模糊高亮效果就是通過下面幾個步驟實現:

1. 單色渲染模型到一張RTT_1

2.  設定currentTarget 為RTT_2,  getTargetTexture(RTT_1),   進行膨脹

3. 設定currentTarget 為RTT_1,  getTargetTexture(RTT_2),   進行高斯模糊

3. 最後一步就是把處理後的紋理貼到遊戲中

下面具體講解下shader 書寫:

1. 單色渲染pass, 在頂點pass 中,主要是做座標轉換

// rimback pass

struct Rimback_VS_OUTPUT
{
	float4 pos : POSITION0;
	float2 uv  : TEXCOORD0;
};

Rimback_VS_OUTPUT Rimback_vs(VertexInput input)
{
	// localspace轉換到worldspace,並且蒙皮
	WorldVertex wv = VertexInputToWorld(input);
	Rimback_VS_OUTPUT output;

	float3 pos = wv.worldPos.xyz;

	output.pos = mul(float4(pos, 1), vp_mat);
	output.uv = input.uv0;
	return output;
}

float4 Rimback_ps(float2 uv : TEXCOORD0): color0   
{
	float4 color = tex2D(modelTex, uv);
	clip(color.a-0.5);  
	color.xyz= edgeColor.xyz;
	//clip(color.a);  
	return float4(color.rgb,1);
}

其中 VertexInputToWorld(VertexInput input) 函式實現描邊隨人物移動而移動,相當於給描邊加上骨骼,函式中主要也是實現input 和 骨骼矩陣 之間的運算

2. 膨脹,關於膨脹原理,就是通過周圍搜尋,增加畫素,填補空白。本例子中,是通過求取周圍畫素的alpha 值,因為步驟1得到單色渲染紋理的alpha為1,周圍取到的alpha值是0,這樣通過計算,得到邊緣部分的alpha 在0~1 之間。通過閾值可以控制膨脹效果。

float4 pengzhang_ps(float2 uv : TEXCOORD0) : color0
{
	const float2 flation[25] =
	{
		-2.70,-2.70,
		-2.70,-1.70,
		-2.70, 0.70,
		-2.70, 1.70,
		-2.70, 2.70,
		-1.70,-2.70,
		-1.70,-1.70,
		-1.70, 0.70,
		-1.70, 1.70,
		-1.70, 2.70,
		0.70,-2.70,
		0.70,-1.70,
		0.70, 0.70,
		0.70, 1.70,
		0.70, 2.70,
		1.70,-2.70,
		1.70,-1.70,
		1.70, 0.70,
		1.70, 1.70,
		1.70, 2.70,
		2.70,-2.70,
		2.70,-1.70,
		2.70, 0.70,
		2.70, 1.70,
		2.70, 2.90,
	};
	float4 outColor = tex2D(blurTex, uv);

		for(int i = 0; i< 25; i++)
		{
			float4 color = tex2D(blurTex, uv + flation[i].xy * viewport_inv_size.xy);
				// add color to flation
				if(color.a >= 0.98)
					outColor = color;
		}

		return outColor;
}

3. 高斯膨脹,原理比較簡單,可以自己網上查詢資料
float4 edegblur_ps(float2 uv : TEXCOORD0) : color0
{
    // 0.7 is for pixel bias
	const float4 samples[9] = {
		-3.70, -3.70, 0, 1.0/16.0,
		-3.70,  3.70, 0, 1.0/16.0,
		3.70, -3.70, 0, 1.0/16.0,
		3.70,  3.70, 0, 1.0/16.0,
		-3.70,  0.70, 0, 2.0/16.0,
		3.70,  0.70, 0, 2.0/16.0,   
		0.70, -3.70, 0, 2.0/16.0,
		0.70,  3.70, 0, 2.0/16.0,
		0.70,  0.70, 0, 4.0/16.0
	};

	float4 col = float4(0, 0, 0, 0);
		//Sample and output the averaged colors
		for(int i=0;i<9;i++)
			col += samples[i].w * tex2D(blurTex, uv + samples[i].xy * viewport_inv_size.xy);
	return float4(edgeColor.r,edgeColor.g,edgeColor.b,col.a);
}

4. 貼圖,
struct SceneBlend_VS_OUTPUT
{
	float4 pos	: POSITION0;
	float2 uv	: TEXCOORD0;
	float4 uvProj : TEXCOORD1;
};

VS_OUTPUT  scene_blend__vs(VS_INPUT vert)
{
	VS_OUTPUT vsout;

	vsout.pos = float4(vert.pos,1);
	vsout.uv  = vert.uv;

	vsout.pos.z = 1.0f;

	return vsout;
}


float4 scene_blend_ps(VS_OUTPUT input):color0
{
	float alpha = tex2D(blurTex,input.uv).a;
	clip(1.0 - (alpha + 0.2f));// 此處是實現顯示輪廓邊緣,中間部分alpha>0.8 的不顯示
	return tex2D(blurTex, input.uv);
}


最後,關於遮擋描邊的效果,在步驟1,即單色渲染的時候,只需要開啟深度檢測,這樣渲染的紋理,僅僅是模型可見部分,而不可見部分就沒有渲染進去,當然後面的膨脹,模糊都沒有它們的事情了。最後的效果圖,如下所示:


關於pass最後的效率情況,如果bur效果不明顯,可以通過重複blur。如果pass影響遊戲幀數,耗記憶體太多,可以考慮對blur 進行橫向以及縱向分開pass。

以上思路僅供參考,希望對遊戲中開發有所啟示。

參考資訊:

http://www.gamedev.net/topic/655543-outline-glow-effect/

http://wiki.unity3d.com/index.php/Silhouette-Outlined_Diffuse

https://en.wikipedia.org/wiki/Gaussian_blur

https://software.intel.com/en-us/blogs/2014/07/15/an-investigation-of-fast-real-time-gpu-based-image-blur-algorithms


相關推薦

遊戲模型模糊邊緣效果實現shader

遊戲中因為有時怪物太多,常常需要對攻擊的怪物高亮,對於遊戲體驗都有很大的提升,也增加了玄幻色彩,如下所示: 網上也有不少實現這種效果的例子,《introduce  to DirectX3D game programming》 書中介紹有法線放大的方法,這種方法對於規則模型

自定義函式實現百度搜索關鍵字在網頁中匹配字元顯示效果

    自定義函式實現類似百度搜索關鍵字在網頁中匹配字元高亮顯示效果。完全用php來實現簡單但很有趣的效果。函式如下: <?php /**     * @param $wd 搜尋的詞語

關於springDataSolr搜尋關鍵字的實現

關於springDataSolr搜尋高亮關鍵字的實現 com.pinyougou.search.service.impl;/* ClassName:ItemSearchServiceImpl Author: Lzc Company:www.lzc.com Date: 2018/11/12 1

iOS中一種字串關鍵字檢索的簡易實現

前言 原文連結:kukumalucn.github.io/blog/2018/1… 本文Demo地址:Demo ,喜歡請star 我的Demo集合:JXT_iOS_Demos ,喜歡請star 平時開發中,我們總會不時的和富文字打交道。有時,我們需要用富文字高亮某句話中的某個關鍵字,如果這個關鍵

sublime外掛Syntax Highlight:使vue效果不錯

效果如圖: 步驟: Ctrl+shift+p撥出sublime安裝外掛視窗: 1.安裝Package Control 2.執行Install Package 3.安裝Vue Syntax High

Android 禁止系統休眠,使螢幕不變暗,保持遊戲中螢幕

Android禁止系統休眠,使螢幕不變暗,保持遊戲中螢幕高亮 實現這一功能的方法有兩種,一種是在Manifest.xml檔案裡面宣告,一種是在程式碼裡面修改LayoutParams的標誌位。具體如下: 1、在Manifest.xml檔案裡面用user-permission宣告。程式碼如下:    &l

JS實現查詢關鍵詞效果

var newHtml = html.replace(regExp, "<span class='highlight'>" + searchText + '</span>'); //將找到的關鍵字替換,加上highlight屬性;

Android關鍵字模糊查詢,並帶有效果

主要功能程式碼在aftertextchange方法中操作,之前用 SpannableStringBuilder方法會出現錯誤,不能被序列化,所以只好用html拼接的方法 privateTextWatchermTWatcher=newTextWatcher(){ @Ove

selector實現按鈕選中效果原理

按鈕選中高亮常規程式碼如下: <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android">

模糊效果實現方案及效能對比

高斯模糊實現方案探究 現在越來越多的app在背景圖中使用高斯模糊效果,如yahoo天氣,效果做得很炫。 這裡就用一個demo來談談它的不同實現方式及各自的優缺點。 1. RenderScript 談到高斯模糊,第一個想到的就是RenderScript。RenderScrip

關於使用PorterDuff.Mode.CLEAR實現喪心病狂的效果

最近專案裡面要做引導頁,然後美工出圖了,看到效果圖的第一眼我覺得還是很容易的 抱著試一試的態度,我去看了2個庫;然後發現ShowTipsView不就有我的想要的效果的麼。 好吧,扯了那麼久,終於要進入主題了(你他麼真是囉嗦的啊)。 要實現這種相交區域高

zTree實現模糊搜尋並顯示

zTree是一個常用的樹外掛,本身對搜尋功能封裝的不是太完美,為了實現下列效果我對其進行了二次封裝。 首先,在定義tree時我們將它高亮和普通顯示的樣式定義好。 var setting = { view:

angularjs 水平滾動選中按鈕顯示 swiper和回到頂部指令的實現ionic

cor load sse component 邏輯 return position col href 首先安裝 swiper npm install --save swiper 或者 bower install --save swiper <link rel=

兩種簡單實現菜單顯示的JS類(轉載)

on() pos 菜單高亮 href 不同的 index body -m ear 兩種簡單實現菜單高亮顯示的JS類 近期在寫一個博客管理後臺的前端,涉及在同一頁面兩種高亮顯示當前菜單的需求.記得當年寫靜態頁時,為了實現高亮都是在每個頁面加不同的樣式,呵.高亮

如何實現Sublime Text3中vue文件顯示的最有效的方法

添加 查找 mov down spa 裏的 family star 解決方法 今天第一次使用Sublime Text3軟件,在實現vue文件高亮顯示的過程中一直報錯,經過了半天時間的不停嘗試終於找到了最有效的一種解決方法!錯誤提示如下: 剛開始嘗試了很多方法都不行,只要打

JavaScript實現段落文本

round strong center 右鍵 listener 進行 onkeyup charset mfc 代碼: <!doctype html> <html lang="en"> <head> <meta http-e

在 Microsoft Word 文檔 中粘貼代碼實現語法的方法

文檔 clas com mage board 分享 實現 pex nbsp 1.下載notepad++。 2.將代碼粘貼進notepad++,或者直接用notepad++打開。 3.點擊頂欄 ===> 插件 ===> NppExport ===> c

利用jQuery實現表格的隔行變色、顯示

his padding idt font pad adding har asc itl <!DOCTYPE html><html><head><meta charset="utf-8"><title&

JS原生代碼實現導航

meta 樣式 添加 代碼 所有 wid 因此 margin position 一 實現原理 根據當前頁面滾動條的高度判斷當前頁面應當與導航欄中哪個導航相關聯,並對相應的導航設置高亮樣式。 二 代碼解析 先簡單寫一個頁面頂端的導航欄:<nav> <ul&

Android基於RecyclerView實現搜索列表

新生代 gil char 能力 hub != AD listview 主動 這篇應該是RecycleView的第四篇了,RecycleView真是新生代的寵兒能做這麽