我之前做了一个有关平面贴图的教程。 该技术的最大缺点是,它只能从一个方向工作,并且我们绘制的表面如果未对准要映射的方向时会断裂(在上一个示例中为向上)。 改进自动uv生成的一种方法是,我们从不同的方向进行三次映射,并在这三种颜色之间进行混合。
本教程将基于平面贴图着色器(这是一个未着色的着色器)建立的,但是您可以将该技术用于许多着色器,包括表面着色器
计算投影平面
要生成三组不同的UV坐标,我们首先更改获取UV坐标的方式。 从顶点着色器返回返回世界位置,然后在片段着色器中生成UV坐标。
//从顶点传递到片段着色器的数据同时被光栅化插值
struct v2f
{
float4 position:SV_POSITION;
float4 worldPos: TEXCOORD0;
};
//顶点着色器方法
v2f vert(appdata v)
{
//顶点着色器阶段处理
v2f o;
//将顶点位置信息从模型空间转换到剪切空间
o.position = UnityObjectToClipPos(v.vertex);
//将纹理变换应用于UV坐标,并将其传递给v2f结构
//计算模型顶点在世界空间的位置
float4 worldPos = mul(unity_ObjectToWorld,v.vertex);
o.worldPos =worldPos;
return o;
}
像以前一样使用transform tex来应用纹理的平铺和偏移。 在着色器中,我使用xy和zy,因此两个纹理的世界up轴都映射到纹理的y轴,而不是相对于彼此旋转它们( 顶部的UV映射是任意的)。
//片段着色器方法
fixed4 frag(v2f i):SV_TARGET
{
//三个方向计算uv坐标
float uv_front = TRANSFORM_TEX(i.worldPos.xy,_MainTex);
float uv_side = TRANSFORM_TEX(i.worldPos.zy,_MainTex);
float uv_top = TRANSFORM_TEX(i.worldPos.xz,_MainTex);
//...
}
获得正确的坐标后,我们读取这些坐标处的纹理,将这三种颜色相加,然后将结果除以3(将三种颜色相加而不除以颜色数将非常明亮)。
//纹理采样
fixed4 col_front = tex2D(_MainTex,uv_front);
fixed4 col_side = tex2D(_MainTex,uv_side);
fixed4 col_top = tex2D(_MainTex,uv_top);
//颜色想加
fixed4 col = (col_front