有时候我们的物体上没有uv坐标休息,或者我们可能希望多个物体上的贴图对齐,或者你希望生成自己的uv坐标信息。在今天教程中,我们展示如果用最简单的方式生成uv坐标信息,平面映射。
本节的shader脚本基于 前面的 Simple textured shader,但是你可以使用任何包含surface shaders的脚本。
Result基础
我们先移除input 结构体中的 uv 坐标相关语句,因为后面我们将生成自己的uv坐标。
struct appdata{
float vertex : POSITION;
};
因为uv坐标可以像之前讲过的,通过差值的方式在顶点间生成,所以我们在vertex shader中来生成。作为简单的开始,我们首先将顶点位置信息的x 、 z设置为uv坐标,这样就可以让贴图在模型上显示出来了。
v2f vert(appdata v){
v2f o;
o.position = UnityObjectToClipPos(v.vertex);
o.uv = v.vertex.xz;
return o;
}
调整 Tiling
上面这样没有将缩放考虑进去,我们可能不希望贴图随随着物体旋转和移动。
通过将TRANSFORM_TEX宏添加到uv坐标信息上,我们可以实现单独控制贴图的偏移和缩放。
v2f vert(appdata v){
v2f o;
o.position = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.vertex.xz, _MainTex);
return o;
}
adjust tiling and offset and watch the material react
贴图坐标信息基于世界坐标
我们可以使用顶点的世界坐标 来使得 贴图 不跟随物体,前面我们使用的是顶点相对于物体的局部坐标。为了获得顶点世界坐标,我们通过 unity_ObjectToWorld 矩阵乘上顶点局部坐标来实现。然后将顶点的世界坐标设置为uv坐标。
v2f vert(appdata v){
v2f o;
//calculate the position in clip space to render the object
o.position = UnityObjectToClipPos(v.vertex);
//calculate world position of vertex
float4 worldPos = mul(unity_ObjectToWorld, v.vertex);
//change UVs based on tiling and offset of texture
o.uv = TRANSFORM_TEX(worldPos.xz, _MainTex);
return o;
}
create a few spheres with the new material and move them around
你可以看到这种技术有一些不足之处,主要包括它只能针对 tile able(无缝贴图) 的贴图,而且在边缘进行了拉伸。这些可以通过别的技术比如 triplanar(三位映射) 进行减轻,后面的教程中我们将讲解。
Shader "Tutorial/008_Planar_Mapping"{
//show values to edit in inspector
Properties{
_Color ("Tint", Color) = (0, 0, 0, 1)
_MainTex ("Texture", 2D) = "white" {}
}
SubShader{
//the material is completely non-transparent and is rendered at the same time as the other opaque geometry
Tags{ "RenderType"="Opaque" "Queue"="Geometry"}
Pass{
CGPROGRAM
#include "UnityCG.cginc"
#pragma vertex vert
#pragma fragment frag
//texture and transforms of the texture
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _Color;
struct appdata{
float4 vertex : POSITION;
};
struct v2f{
float4 position : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert(appdata v){
v2f o;
//calculate the position in clip space to render the object
o.position = UnityObjectToClipPos(v.vertex);
//calculate world position of vertex
float4 worldPos = mul(unity_ObjectToWorld, v.vertex);
//change UVs based on tiling and offset of texture
o.uv = TRANSFORM_TEX(worldPos.xz, _MainTex);
return o;
}
fixed4 frag(v2f i) : SV_TARGET{
//read texture at uv position
fixed4 col = tex2D(_MainTex, i.uv);
//multiply texture color with tint color
col *= _Color;
return col;
}
ENDCG
}
}
FallBack "Standard" //fallback adds a shadow pass so we get shadows on other objects
}
网友评论