西西軟件園多重安全檢測(cè)下載網(wǎng)站、值得信賴的軟件下載站!
軟件
軟件
文章
搜索

首頁(yè)編程開(kāi)發(fā)其它知識(shí) → 使用投影紋理進(jìn)行模型貼花(Mesh Decals)

使用投影紋理進(jìn)行模型貼花(Mesh Decals)

相關(guān)軟件相關(guān)文章發(fā)表評(píng)論 來(lái)源:BoYueGame時(shí)間:2011/1/7 11:46:31字體大。A-A+

作者:BoYueGame點(diǎn)擊:359次評(píng)論:6次標(biāo)簽: 紋理

  • 類型:圖像處理大。50.0M語(yǔ)言:中文 評(píng)分:10.0
  • 標(biāo)簽:
立即下載

在游戲中貼花最常見(jiàn)的地方就是用鼠標(biāo)選擇一個(gè)目標(biāo)后,地上出現(xiàn)的一個(gè)圓圈,或者范圍魔法在施放時(shí)的提示區(qū)域。
這個(gè)紋理會(huì)隨著模型和地圖的表面進(jìn)地扭曲,而非一個(gè)平面,所以,我們不論怎么做,都會(huì)進(jìn)行一個(gè)“投影”的思想,才能讓貼上去的紋理在某一個(gè)方向上看的時(shí)候,是一個(gè)完整的畫(huà)面。(我們地上的圈,就是從上往下貼的,所以你從上往下看時(shí),會(huì)看到一個(gè)完整無(wú)扭曲的圖片)。
什么? 地上是一圈?是的,但是呢,我們的紋理是方的。 我們看到是圈,并不表示我們要把紋理貼到一個(gè)圈上。
下面是我在RenderMonkey里測(cè)試的結(jié)果。

 


OK,圍觀完畢,下面簡(jiǎn)單說(shuō)一下如何實(shí)現(xiàn)。


用投影紋理進(jìn)行貼花分為三部。

1、正常渲染模型。

無(wú)它!

2、根據(jù)投影方向,投影半徑找到投影時(shí)需要渲染的三角形組。

這種貼花的效率損耗就是花在這里了,所以三角形剔除算法要比較高效才行。

3、將此三角形組進(jìn)行渲染,紋理映射時(shí)采用投影紋理。

渲染時(shí),要打開(kāi)全局混合開(kāi)關(guān)。

下面是投影紋理的HLSL代碼,以及相關(guān)解釋。
VS:

struct VS_INPUT
{
float4 Position : POSITION0;
float2 Texcoord : TEXCOORD0;
};

struct VS_OUTPUT
{
float4 Position : POSITION0;
float2 Texcoord : TEXCOORD0;
float3 WorldPos : TEXCOORD1;
};

VS_OUTPUT vs_main( VS_INPUT Input )
{
VS_OUTPUT Output;

Output.Position = mul( Input.Position, matViewProjection );
Output.Texcoord = Input.Texcoord;
Output.WorldPos = Input.Position;
return( Output );
}

VS所做的工作并沒(méi)有什么特別的,僅是需要多向PS傳遞一個(gè)空間位置。

PS:
sampler2D baseMap;
sampler2D Texture1; //貼這張紋理時(shí),其UV尋址方式最好為CLAMP
struct PS_INPUT
{
float2 Texcoord : TEXCOORD0;
float3 WorldPos : TEXCOORD1;
};

float4 ps_main( PS_INPUT Input ) : COLOR0
{
float3 Center = float3(0, 0, 20);//投影中心,Y值被忽略。
float Radius = 4;//投影范圍
float3 UVector = float3(1, 0, 0)/(2 * Radius);//將世界坐標(biāo)變換到紋理投影空間坐標(biāo)并規(guī)范化到0-1之間(正投影)
float3 VVector = float3(0, 0, 1)/(2 * Radius);//同上
float2 coord;
coord.x = dot(Input.WorldPos - Center, UVector) + 0.5;
coord.y = dot(Input.WorldPos - Center, VVector) + 0.5;
// if(coord.x < 1 && coord.y < 1 && coord.x>0 && coord.y>0)
return tex2D( Texture1, coord);
//else
//return 0;
}

PS所做的工作就是將世界坐標(biāo)轉(zhuǎn)換到投影空間,再轉(zhuǎn)換為紋理坐標(biāo)。

需要說(shuō)明一點(diǎn)的是,為了測(cè)試方便,我僅假設(shè)此時(shí)攝相機(jī)觀察和投影方向?yàn)?Y方向。所以

dot(Input.WorldPos - Center, UVector)+0.5

上面這句話其實(shí)相當(dāng)于是mul(Input.WorldPos,matProjTexture)/2.0+0.5;

另外,對(duì)于

// if(coord.x < 1 && coord.y < 1 && coord.x>0 && coord.y>0)

這句話,我寫(xiě)在這里,是作為裁剪使用,若沒(méi)有這個(gè). 就算你設(shè)置為了CLAMP,那么當(dāng)你的紋理邊緣的ALPHA不為0時(shí),你會(huì)看到

紋理會(huì)左右延伸。


而若你未選擇CLAMP尋址方式,那你的效果就百般神奇了。 也可以將上面屏蔽的代碼解開(kāi),用于裁剪。

 結(jié)尾:

一、投影紋理進(jìn)行模型貼花時(shí),主要是進(jìn)行三角面剔除,使在渲染貼花時(shí),提交最少的三角面。

二、在貼花PASS中,需要將全局混合開(kāi)啟,并設(shè)置相應(yīng)的SRCBLEND(SRC_ALPHA)和DESTBLEND(DEST_ALPHA)值。括號(hào)內(nèi)為我用的值。

當(dāng)然,如果你不想讓貼花與場(chǎng)景(模型)混合,則可以不開(kāi)啟!

三、請(qǐng)注意紋理的尋址方式以及紋理邊緣的ALPHA情況!∪艏y理邊緣ALPHA不為0,則可以手工進(jìn)行裁剪。

四、本文僅是采用了固定的投影方向和SHADER內(nèi)部定義變量的方式來(lái)進(jìn)行貼花渲染!〔⑶,并未進(jìn)行模型三角面剔除。所以若要使用,則需要注意第一個(gè)問(wèn)題。

五、本文靈感來(lái)源于此貼:http://forums.create.msdn.com/forums/p/34339/198791.aspx

六、支持郵件交流:BoYueGame#Gmail#com

    相關(guān)評(píng)論

    閱讀本文后您有什么感想? 已有人給出評(píng)價(jià)!

    • 8 喜歡喜歡
    • 3 頂
    • 1 難過(guò)難過(guò)
    • 5 囧
    • 3 圍觀圍觀
    • 2 無(wú)聊無(wú)聊

    熱門評(píng)論

    最新評(píng)論

    第 1 樓 重慶九龍坡聯(lián)通 網(wǎng)友 客人 發(fā)表于: 2011/1/7 9:49:39
    你可以轉(zhuǎn)載,但為何要故意隱藏出處,并且刪掉我文中的所有鏈接? 大家可以看原文 http://www.cppblog.com/Leaf/archive/2011/01/07/138093.html

    支持( 0 ) 蓋樓(回復(fù))

    發(fā)表評(píng)論 查看所有評(píng)論(6)

    昵稱:
    表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
    字?jǐn)?shù): 0/500 (您的評(píng)論需要經(jīng)過(guò)審核才能顯示)