我正在尝试使用由多层材质组成的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对,材质ID为float3,每个材质id的混合因子为float3),但我在没有将网格划分为单个三角形的情况下,没有任何方法可以实现此目的
任何帮助将不胜感激。我的目标是使用C#和Direct3D 9 API的SlimDX。感谢您的阅读
P.S。:如果我在本文中犯了一些错误,我很抱歉,英语不是我的母语。
答案 0 :(得分:1)
您的ColorTextureSampler
可能使用point filtering(D3DTEXF_POINT
)。使用D3DTEXF_LINEAR
或D3DTEXF_ANISOTROPIC
来获得所需的插值效果。
我对SlimDX 9不太熟悉,但你已经有了这个想法。
BTW,很好的插图=)
更新1 以下评论中的结果似乎与您的代码相符。 看起来想要达到预期的效果,你必须改变整体方法。 它不是完整的解决方案,但我们如何在普通的3D地形中实现它:
R
通道保存T1的alpha,G
通道的T2,{{1对于T3,......等。B
,... float4 val1, val2, val3
float blend1, blend2, blend3, ...
例如,如果您的T1是草地,并且地图中间有一个大草地,那么您将在中间挥动一个大红色区域。
这个算法有点慢,因为纹理采样很多,但实现简单,给出了很好的视觉效果和最灵活。您不仅可以使用遮罩作为混合系数,还可以使用任何值:例如高度(山峰中的雪更多,山中的岩石,低地的泥土),坡度(陡峭的岩石,平坦的草地),甚至是固定值,等等或混淆所有这些。此外,您可以改变混合:使用内置float4 terrainColor = lerp( val1, val2, blend1 );
terrainColor = lerp( terrainColor, val3, blend2);
terrainColor = lerp( terrainColor, ..., blendN );
或更复杂的东西(警告!这个例子很愚蠢):
lerp
float4 terrainColor = val1 * val2 * blend1 + val2 * val3 * blend2;
使用混合算法是这个方法中最有趣的部分。你可以在谷歌找到很多技术。
不确定,但希望它有所帮助! 快乐的编码! =)