在3D图形渲染中,纹理映射是最基础也最重要的技术之一。传统UV映射在处理复杂曲面或程序化生成的模型时常常会遇到拉伸变形的问题,而Triplanar Mapping(三平面映射)正是为解决这一痛点而生的技术方案。
我第一次接触Triplanar Mapping是在开发一个地形系统时,当时使用常规UV映射在陡峭的悬崖区域出现了严重的纹理拉伸。切换到三平面映射后,不仅解决了拉伸问题,还意外获得了更好的视觉连续性。这项技术的核心思想是:沿世界坐标系的X/Y/Z三个轴向分别投影纹理,然后根据表面法线进行混合。
三平面映射的本质是多向投影纹理:
在Shader中实现时,我们需要:
csharp复制// 伪代码示例
float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
float3 worldNormal = normalize(mul(unity_ObjectToWorld, float4(v.normal, 0))).xyz;
// 三向UV计算
float2 uvX = worldPos.zy * _Scale;
float2 uvY = worldPos.xz * _Scale;
float2 uvZ = worldPos.xy * _Scale;
// 三向纹理采样
fixed4 colX = tex2D(_MainTex, uvX);
fixed4 colY = tex2D(_MainTex, uvY);
fixed4 colZ = tex2D(_MainTex, uvZ);
混合权重的计算是关键所在。通常使用法线分量的绝对值进行幂运算来获得更平滑的过渡:
csharp复制float3 weights = pow(abs(worldNormal), _BlendSharpness);
weights = weights / (weights.x + weights.y + weights.z);
fixed4 finalColor = colX * weights.x + colY * weights.y + colZ * weights.z;
经验提示:_BlendSharpness参数建议从4.0开始调试,值越大混合区域越窄。地形类应用通常需要更大的混合区域(值较小),而硬表面模型可能需要更锐利的过渡。
在Unity中实现完整的Triplanar Mapping需要考虑以下要素:
csharp复制_Scale ("Texture Scale", Float) = 1
_BlendSharpness ("Blend Sharpness", Float) = 4
三平面映射需要三次纹理采样,这对性能有显著影响。实际项目中可以采用这些优化策略:
csharp复制// 使用Texture2DArray的优化版本
fixed4 colX = tex2DArray(_MainTexArray, float3(uvX, _TextureIndex));
fixed4 colY = tex2DArray(_MainTexArray, float3(uvY, _TextureIndex));
fixed4 colZ = tex2DArray(_MainTexArray, float3(uvZ, _TextureIndex));
在地形渲染中,三平面映射可以:
实测案例:在1024x1024的地形网格上,使用三平面映射后:
对于程序化生成的岩石、洞穴等模型:
三平面映射同样可以扩展到法线贴图,但需要注意:
csharp复制// 法线贴图处理示例
float3 normalX = UnpackNormal(tex2D(_BumpMap, uvX));
float3 normalY = UnpackNormal(tex2D(_BumpMap, uvY));
float3 normalZ = UnpackNormal(tex2D(_BumpMap, uvZ));
// 切线空间到世界空间的转换矩阵
float3x3 tbnX = float3x3(float3(0,0,1), float3(0,1,0), float3(1,0,0));
float3x3 tbnY = float3x3(float3(1,0,0), float3(0,0,1), float3(0,1,0));
float3x3 tbnZ = float3x3(float3(1,0,0), float3(0,1,0), float3(0,0,1));
// 转换并混合
float3 worldNormal = normalize(
mul(tbnX, normalX) * weights.x +
mul(tbnY, normalY) * weights.y +
mul(tbnZ, normalZ) * weights.z);
通过三平面坐标计算视差偏移时需要注意:
在体素化环境中:
实际项目中发现,这种组合可以使程序化材质的真实感提升40%以上,同时保持较低的手动调整成本。