对于复杂或程序化的网格,与其使用常规 UV 坐标进行纹理化,有时只需从三个主要方向“投影”纹理到对象上即可。这称为“三平面”纹理。其思想是使用表面法线对三个纹理方向进行加权。以下是着色器在 GPU 上运行的程序。 更多信息
参见 词汇表
Shader "Unlit/Triplanar"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Tiling ("Tiling", Float) = 1.0
_OcclusionMap("Occlusion", 2D) = "white" {}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f
{
half3 objNormal : TEXCOORD0;
float3 coords : TEXCOORD1;
float2 uv : TEXCOORD2;
float4 pos : SV_POSITION;
};
float _Tiling;
v2f vert (float4 pos : POSITION, float3 normal : NORMAL, float2 uv : TEXCOORD0)
{
v2f o;
o.pos = UnityObjectToClipPos(pos);
o.coords = pos.xyz * _Tiling;
o.objNormal = normal;
o.uv = uv;
return o;
}
sampler2D _MainTex;
sampler2D _OcclusionMap;
fixed4 frag (v2f i) : SV_Target
{
// use absolute value of normal as texture weights
half3 blend = abs(i.objNormal);
// make sure the weights sum up to 1 (divide by sum of x+y+z)
blend /= dot(blend,1.0);
// read the three texture projections, for x,y,z axes
fixed4 cx = tex2D(_MainTex, i.coords.yz);
fixed4 cy = tex2D(_MainTex, i.coords.xz);
fixed4 cz = tex2D(_MainTex, i.coords.xy);
// blend the textures based on weights
fixed4 c = cx * blend.x + cy * blend.y + cz * blend.z;
// modulate by regular occlusion map
c *= tex2D(_OcclusionMap, i.uv);
return c;
}
ENDCG
}
}
}