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

标签 c++ user-interface textures direct3d9 tiling

如果之前有人问过这个问题,请原谅我,我一整天都在寻找这个问题的答案,我想得到的只是关于基于图 block 的 2D 游戏的帮助。 x~x

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

我觉得我错过了一些非常明显的东西,但我该如何简单地平铺而不是拉伸(stretch)?我最好的猜测是它与拥有不止一组纹理坐标有关,但从那里开始,我不确定该去哪里。

该项目目前使用固定功能管道,所以如果可能的话,我更喜欢使用它的答案,但如果这是唯一的方法,我不会拒绝使用着色器的答案。

最佳答案

我知道你只想平铺纹理的一个子集,对吧?然后事情就变得复杂了。

假设我们想在 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 不完全相同,但对于非负数是正确的)。

关于c++ - 我如何在屏幕空间中平铺纹理的一部分?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9655524/

相关文章:

c++ - MFC:CFormView 派生类的 OnInitialUpdate 函数

android - 使用 GalleryView 选择多个图像

python - 在 Maya 中将着色器存储为 Python 变量

cuda - 将 CUDA 纹理绑定(bind)到 float 图像

c++ - 您可以使用 CRTP 和以接口(interface)作为参数的函数吗?

c++ - 在 n 处计算六次独立运行的斐波那契数的最大和最小时间

c++ - 我只是很困惑

c# - 如何在不调整控件大小的情况下将控件居中? (.net Winforms)

user-interface - wxpython 使用 time.sleep() 不阻塞完整的 GUI

c++ - 如何在cocos2d-x中制作清晰的纹理