2012-03-11 85 views
2

如果之前有人問過我,請原諒我,我一直在尋找這一整天的答案,而我所提出的全部內容都是基於瓦片的2D遊戲的幫助。我想在Direct3D 9中創建一個可換膚的圖形用戶界面,使用一個XML文件,每個元素都有位置,並有一個選項可以拉伸或平鋪它們。拉伸是一個足夠簡單的過程,但我一直無法找到一種方法來平鋪紋理的一小部分。傳統上來說,我要將UV座標設置爲> 1.0,但源紋理座標只是整個紋理的一小部分,例如0.4到0.5。我將如何平鋪屏幕空間中的紋理部分?

我有一種感覺,我錯過了一件非常明顯的事情,但我會如何簡單地平鋪而不是伸展?我最好的猜想是它與擁有多組紋理座標有關,但從那裏,我不確定要去哪裏。

該項目目前使用固定功能流水線,因此如果可能的話,我更願意使用該答案,但如果這是唯一方法,我不會拒絕使用着色器的答案。

回答

1

我知道你只想平鋪紋理的一個子集,對吧?然後事情變得複雜。

假設我們想要平鋪u1和u2值之間的u-coord,u1 < u2。

然後,我們需要一個函數f(u),使

f(0.0) = u1 
f(0.5) = (u1+u2)/2 
f(0.9999) = u2 
f(1.0) = u1 
f(1.5) = (u1+u2)/2 
f(1.9999) = u2 
f(2.0) = u1 
and so on... 

適當的功能是f(u) = frac(u) * (u2-u1) + u1

同樣爲V-座標,f(v) = frac(v) * (v2-v1) + v1

請注意,這是平鋪不鏡像。如果需要鏡像,那麼函數應該是一個三角波函數,即t(x) = arcsin(sin(pi*(x-0.5)))/pi+0.5f(u) = t(u) * (u2-u1) + u1。使用三角函數可能會很昂貴。

我不知道是否有可能與固定管道,但你可以在像素着色器(HLSL代碼)輕鬆地做到這一點:

// float2 tex_coord -> (u,v) from vertex shader, in [0,n] range, 
//      n - number of repetitions 
// float2 tex1, tex2 -> constants, subrange of [0,1] coords that will be tiled 

// no mirroring 
float4 color = tex2D(sampler, frac(tex_coord) * (tex2-tex1) + tex1); 

// mirroring, t(x) = arcsin(sin(pi*(x-0.5)))/pi+0.5 
float4 color = tex2D(sampler, t(tex_coord) * (tex2-tex1) + tex1); 

編輯: 更好計算三角波函數的方法:t1(x) = abs(2(0.5x-floor(0.5x+0.5)))t2(x) = abs(2(frac(0.5x+0.5))-1)(與t1不完全相同,但對於非負數是正確的)。

+0

我看過的所有內容都顯示,在固定功能管道中實現它是不可能的,但很遺憾,看到你爲像素着色器代碼做出了超越和超越的事情。感謝您的迴應:D – Addi 2012-05-11 11:29:34