【问题标题】:Multi-Texturing - Interpolation between two layers of an 3D texture多纹理 - 3D 纹理的两层之间的插值
【发布时间】:2013-05-07 20:01:27
【问题描述】:

我正在尝试使用由多层材质组成的 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。感谢阅读。
P.S.:如果我在这篇文章中出现了一些错误,我很抱歉,英语不是我的母语。

【问题讨论】:

    标签: directx textures hlsl texture-mapping volume-rendering


    【解决方案1】:

    可能,您的ColorTextureSampler 使用point filtering (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);

    使用混合算法是这种方法中最有趣的部分。您可以在 google 中找到许多技术。

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

    【讨论】:

    • 感谢您的回答 :) 不幸的是,几乎没有任何变化 - 我只是得到相同的图像,但经过平滑处理,正如您在 this screenshot 中看到的那样。
    • 哇,很棒的更新。似乎我没有明确说明我的地形由“块”(体素)组成,并且不能使用基于高度的方法,因为我希望用户通过添加其他材料来编辑地形。但是贴图遮罩看起来很有趣,也许我会尝试它来实现溅射效果。我希望 ps_3_0 中有足够的纹理采样器,我会研究一下。谢谢,它变得更清楚了,我会及时通知你我的进展:)
    • 我通过混合你和我的方法做到了。我没有使用不同的采样器,而是将我的纹理打包到一个 3D 纹理中(就像我之前所做的那样),并通过我在问题中描述的因素混合它们。它给了我一个简单的平滑纹理,我期待使用您描述的“纹理遮罩”使材质之间的过渡更具吸引力:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-28
    • 2012-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-04
    • 2014-08-12
    相关资源
    最近更新 更多