2012-03-11 60 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