永远的主视图
Unity中,X、Y、Z坐标轴分别对应左、上、前,摄像机人视觉的方向在Z轴上。所以,当我们从Z轴看物体看的是正反面,Y轴看的是上下面,X看的是左右面。
一个面片Quad只有四个顶点、两个三角形,我们从Z上看是矩形,但是从其他的两个方向上看我们是看不见的。而场景中烟花的粒子,一个正在旋转的黑洞等大都是一个面片,我们希望从任意角度看这个物体时它都和从正面看到的一样,怎么办呢?简单的想想有两种方法:
1,让面片永远的LookAt 摄像机(个人觉得有点Low)
2,使用Shader重绘顶点
3,没想…
现在说说关于2的实现。
如下面第一张图是我们正常的视觉,把物体的中心点设置为坐标的元点,从正前方看。当我们改变视线,从Z1向物体看去,把原来的坐标轴按照新的视线进行对应得到图2。现在我们的目的转换成求转换后坐标轴即可,把点转换成我们新构建的坐标空间。
得到Z1是新的视觉方向,那么先预计一个大概的Y方向。如果新的Z1靠近原Y,那么我们估计他的新Y为(0,0,1),否则还当作(0,1,0), 只要这两个向量是在同一个水平面上就行。然后通过向量的叉乘求得X1:
X1 = 预估Y1 x Z1;
再去求得准确的Y1:
Y1 = Z1 x X1;
得到改变后的坐标向量(X1,Y1,Z1),把模型上的坐标点距离我们选定的中心点的向量转换到新的坐标系中就可。
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
Shader "Custom/MainView" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
}
SubShader{
Tags{"Queue"="Transparent" "RenderType"="Transparent" "IgnoreProject"="True" "DisableBatching"="True"}
Pass{
Tags{"LightMode"="ForwardBase"}
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Cull Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
fixed4 _Color;
sampler2D _MainTex;
struct a2v {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
};
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert(a2v v) {
v2f o;
float3 center = float3(0,0,0);
float3 viewerPos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1));
float3 z1 = normalize(viewerPos - center);//视觉向量,新的Z1
//上方,模型的向上方向向量,和视觉方向垂直,当视觉方向接近垂直时设为世界坐标的水平方向
float3 y1 = abs(z1.y) > 0.999 ? float3(0,0,1) : float3(0,1,0);
float3 x1 = normalize(cross(y1, z1));//叉乘得垂直
y1 = normalize(cross(z1, x1));//获取准确的向上分量
float3 curVector = v.vertex.xyz - center;//当前坐标向量
//向量在三个方向上的分量为最终坐标,相当于重构坐标轴
float3 newPos = center + x1 * curVector.x + y1 * curVector.y + z1 * curVector.z;//转化到新坐标系
o.pos = mul(UNITY_MATRIX_MVP, float4(newPos, 1));
o.uv = v.texcoord.xy;
return o;
}
fixed4 frag(v2f i) : SV_Target {
return tex2D(_MainTex, i.uv) * _Color;
}
ENDCG
}
}
FallBack Off
}
DisableBatching的作用说过了,其他的都是满满的线性代数0.0
可以看到当我们旋转从不同角度看时看到的基本上都是一样的。