我跟着一篇名为"基于GPU的地形纹理算法"并说它如下:
应用三平面纹理的主要算法非常简单。 首先,我们以相同的方式检查斜率是否相对较大 我们用基于斜率的纹理来做。这些地区坡度较高 将是该算法所影响的唯一区域。然后我们检查一下 正常的较大分量是x和z。如果x是 更大的组件,我们使用几何z坐标作为纹理 坐标s,几何y坐标作为纹理坐标 吨。如果z是较大的组件,我们使用几何x坐标作为 纹理坐标s和几何y坐标作为纹理 协调t。
所以我试着实现它。这是我的身高图:
请注意,我在边框中添加了仅用于实验的白线,所以现在我的地图周围有最大高度的墙。
现在关注文章,这里是顶点着色器中的实现:
#version 430
uniform mat4 ProjectionMatrix;
uniform mat4 CameraMatrix;
uniform vec3 scale;
layout(location = 0) in vec3 vertex;
layout(location = 1) in vec3 normal;
out vec3 fsVertex;
out vec3 fsNormal;
out vec2 fsUvs;
void main()
{
fsVertex = vertex;
fsNormal = normalize(normal);
if(fsNormal.y < 0.75) {
if(fsNormal.x > fsNormal.z)
fsUvs = vertex.zy * scale.zy;
else
fsUvs = vertex.xy * scale.xy;
}
else
fsUvs = vertex.xz * scale.xz;
gl_Position = ProjectionMatrix * CameraMatrix * vec4(vertex * scale, 1.0);
}
Here's片段着色器,如果有帮助的话。
这就是我得到的:
Here's a further look,比例。 顶部和左侧墙壁(高度贴图)呈现正常,底部和右侧墙壁仍然受到拉伸。我还在墙的开头旁边看到了这些奇怪的延伸点。
这可能是什么原因?
答案 0 :(得分:2)
如果您想检查普通的x或z坐标是否更长,则应使用abs
函数:
if(abs(fsNormal.x) > abs(fsNormal.z))
此外,y > 0.75
似乎是粗略的近似,在大多数情况下可能已经足够好了。实际上,abs(x), abs(y), abs(z)
的最大值可以为您提供正确的平面。
答案 1 :(得分:-1)
这是我使用的DX11 / HLSL实现。 GLSL转换应该很容易。 使用指数值,您可以调整边界处的混合速度。我使用了类似于3.
的东西float3 SampleTriplanarTexture(Texture2D<float4> tex1, Texture2D<float4> tex2, Texture2D<float4> tex3, float3 normal, float3 pos, float exponent)
{
//triplanar projection
float mXY = pow(abs(normal.z), exponent);
float mXZ = pow(abs(normal.y), exponent);
float mYZ = pow(abs(normal.x), exponent);
float total = 1.0f / (mXY + mXZ + mYZ);
mXY *= total;
mXZ *= total;
mYZ *= total;
return tex1.SampleLevel(linearSampler2, pos.xz, 0) * mXZ +
tex2.SampleLevel(linearSampler2, pos.xy, 0) * mXY +
tex3.SampleLevel(linearSampler2, pos.yz, 0) * mYZ;
}