2

我正在尝试使用由多层材料组成的 3D 纹理来实现地形纹理,并在材料之间进行平滑混合。

也许我的插图会更好地解释它:
美丽的照片

试想一下,每种颜色都是很酷的地形纹理,比如草、石头等。
我想让它们正确混合,但是用目前的方法,除了我想要出现的纹理之外,我还得到了请求之间的所有纹理(这似乎是合乎逻辑的,因为我读过,3D 纹理被视为三维数组而不是纹理柱)。
当前(显然是愚蠢的)方法很简单(“当前”结果是使用点插值渲染的,所需的结果是手绘的):

顶点:
Vertex 1: Position = Vector3.Zero, UVW = Vector3.Zero
Vertex 2: Position = Vector3(0, 1, 0), UVW = Vector3(0, 1, 0.75f)
Vertex 3: Position = Vector3(0, 0, 1), UVW = Vector3(1, 0, 1)
如您所见,三角形的第一个顶点使用第一种材质(红色的),第二个顶点使用第三种材质(蓝色的),第三个顶点使用最后的第四种材质(黄色的)。

这就是它在像素着色器中的完成方式(UVW 直接传递而无需更改):
float3 texColor = tex3D(ColorTextureSampler, input.UVW);
return float4(texColor, 1);
我选择的原因是我的地形结构。地形是使用行进立方体从体素(每个体素都有材质 ID)生成的。每个顶点都是“焊接的”,因为网格非常大,我不想让每个三角形都独立(但如果无法使用连接顶点解决我的问题,我仍然可以这样做)。
我最近想到了在每个顶点中存储三角形其他两个顶点的材质 ID 及其混合因子(我会有一个 float2 UV 对,float3 用于材质 ID,float3 用于每个材质 ID 的混合因子),但我如果不将我的网格分成单独的三角形,则看不到任何方法来实现这一点。
任何帮助将不胜感激。我的目标是使用 C# 和 Direct3D 9 API 的 SlimDX。谢谢阅读。
PS:如果我在这篇文章中犯了一些错误,我很抱歉,英语不是我的母语。

4

1 回答 1

1

可能,您ColorTextureSampler使用点过滤( D3DTEXF_POINT)。使用D3DTEXF_LINEARD3DTEXF_ANISOTROPIC来获得所需的插值效果。我对 SlimDX 9 不是很熟悉,但你明白了。

顺便说一句,很好的插图=)

更新 1 您在下面的评论中的结果似乎适合您的代码。看起来要获得预期的效果,您必须改变整体方法。这对您来说不是完整的解决方案,但我们可以在普通的 3D 地形中制作它:

  • 每个顶点有 1 对 (u, v) 纹理坐标
  • 您有 n 个纹理要采样到 (T1, T2, T3, ..., Tn) 中,它们代表不同的地形层:沙子、草、岩石等。
  • 您总共有 n 个通道的遮罩纹理,它在其通道中存储每个纹理 T 的混合系数:R通道为 T1 保存 alpha,G为 T2 保存通道,B为 T3 保存...等。
  • 在像素着色器中,您像往常一样对图层纹理进行采样,并获取颜色值float4 val1, val2, val3,...
  • 然后你为相应的混合系数采样蒙版纹理并得到float blend1, blend2, blend3, ...
  • 然后你应用某种混合算法,例如简单的线性插值:
float4 terrainColor = lerp( val1, val2, blend1 );
terrainColor = lerp( terrainColor, val3, blend2);
terrainColor = lerp( terrainColor, ..., blendN );

例如,如果您的 T1 是草,并且您的地图中间有一个大草场,那么您将在中间挥动一个大的红色场地。

这个算法有点慢,因为纹理采样很多,但实现简单,视觉效果好,最灵活。您不仅可以使用掩码作为混合系数,还可以使用任何值:例如高度(在山峰中采样更多的雪,在山中采样更多的岩石,在低地中的泥土),坡度(陡峭的岩石,平坦的草地),甚至是固定值,等等。或者混合所有这些。此外,您可以改变混合:使用内置lerp或更复杂的东西(警告!这个例子很愚蠢):

float4 terrainColor = val1 * val2 * blend1 + val2 * val3 * blend2;
terrainColor = saturate(terrainColor);

使用混合算法是这种方法中最有趣的部分。你可以在谷歌找到很多很多的技术。

不确定,但希望它有帮助!快乐编码!=)

于 2013-05-13T18:46:31.630 回答