繁体   English   中英

如何在屏幕空间中平铺纹理的一部分?

[英]How would I tile a section of a texture in screen space?

如果以前曾问过这个问题,请原谅我,我一直在寻找答案,而我所提供的只是基于图块的2D游戏的帮助。 X - X

我正在尝试使用XML文件在Direct3D 9中创建可换皮肤的GUI,该文件具有每个元素的位置以及用于拉伸或平铺它们的选项。 拉伸是一个非常简单的过程,但是我一直无法找到一种方法来平铺纹理的一小部分。 传统上平铺纹理时,我只会将UV坐标设置为> 1.0,但是源纹理坐标只会是整个纹理的一小部分,例如0.4到0.5。

我有一种感觉,我确实错过了一些显而易见的事情,但是我将如何简单地平铺而不是拉伸呢? 我最好的猜测是,它与多于一组的纹理坐标有关,但是从那里,我不确定要去哪里。

该项目当前使用固定功能管道,因此,如果可能的话,我宁愿使用它,但是如果那是唯一的方法,我不会拒绝使用着色器的答案。

我了解您只希望平铺纹理的一部分,对吗? 然后事情变得复杂了。

假设我们要在u1和u2值之间平铺u坐标,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并不完全相同,但适用于非负数)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM