先进的地形纹理喷涂

图片


在本文中,我将解释一种纹理喷涂算法,该算法可让您创建更自然的地形。 该算法可用于3D游戏的着色器以及2D游戏中。


地形纹理的最常见方法之一是混合多个平铺层。 每个图层都有一个不透明度贴图,该贴图定义了地形上纹理存在的程度。 该方法通过将不透明度贴图应用到较高级别而起作用,显示不透明度贴图部分或完全透明的下面的图层。 不透明度图以百分比度量。 当然,在地形的每个点上,由于地形不是透明的,因此所有图层的不透明度之和为百分之一百。 代替贴图纹理,不透明度贴图完全在所有地形上延伸,因此细节水平很低。


现在,我们将转到最有趣的部分-纹理混合算法。 为了简单明了,我们的地形将由沙子和大块鹅卵石组成。


图片


混合的最简单方法是将纹理颜色与不透明度相乘,然后对结果求和。


float3 blend(float4 texture1, float a1, float4 texture2, float a2) { return texture1.rgb * a1 + texture2.rgb * a2; } 

在标准地形编辑器的Unity3D中使用了这种技术。 如您所见,过渡是平滑的但不自然。 石头看起来均匀地被沙子弄脏了,但是在现实世界中,事情并非如此。 沙子不会粘在石头上,而是会掉落并填充它们之间的裂缝,从而使石头的顶部保持纯净。


让我们尝试在Excel图形中模拟这种行为。 因为我们希望沙子在鹅卵石之间“掉落”,所以对于每种纹理,我们都需要深度图。 在此示例中,我们认为深度图是从灰度图像生成的,并存储在纹理的Alpha通道中。 在Unity3D中,可以通过设置标志“来自灰度的Alpha”在纹理检查器中完成此操作。


首先,我们将考虑沙子和石头的深度图的简化模型。


图片


地块上的蓝线象征着沙子的深度图,红色是鹅卵石。 请注意,石头的顶部高于沙子的高度。 考虑到这一事实,我们将尝试绘制上面具有该纹理的像素。


 float3 blend(float4 texture1, float a1, float4 texture2, float a2) { return texture1.a > texture2.a ? texture1.rgb : texture2.rgb; } 

图片


太好了! 鹅卵石的顶部保持纯净,而沙子位于它们之间的裂缝中。 但是我们还没有考虑图层不透明度。 要使用它,我们只对深度深度图和不透明度图求和。


 float3 blend(float4 texture1, float a1, float4 texture2, float a2) { return texture1.a + a1 > texture2.a + a2 ? texture1.rgb : texture2.rgb; } 

以总和为代价,较少的透明纹理将比平常更高。


图片


图片


因此,我们有一个从沙子到石头的更自然的过渡。 如您所见,沙粒开始填充鹅卵石之间的裂缝,逐渐将它们隐藏起来。 但是,随着计算逐像素进行,伪影开始出现在纹理之间的边界上。 为了获得平滑的结果,我们将深度取为几个像素而不是一个,然后将其混合。


 float3 blend(float4 texture1, float a1, float4 texture2, float a2) { float depth = 0.2; float ma = max(texture1.a + a1, texture2.a + a2) - depth; float b1 = max(texture1.a + a1 - ma, 0); float b2 = max(texture2.a + a2 - ma, 0); return (texture1.rgb * b1 + texture2.rgb * b2) / (b1 + b2); } 

在上面的代码中,我们首先获得在一定深度处看到的部分地面。


图片


然后我们对其进行归一化以获得新的不透明性。


图片


图片


结果,我们发现了纹理融合算法,该算法使我们能够接近自然地形图像。

Source: https://habr.com/ru/post/zh-CN442924/


All Articles