顶点动画之让一个物体时刻面向你



让一个物体始终面朝向你摄像机的位置




unity开发游戏app对接抖音广告 unity3d广告_顶点着色器


顶点着色器部分:

       

v2f vert (appdata v)
            {
                v2f o;
//选择将原型空间的原点作为全程位置都不会改变的锚点,物体会                                                         围绕这锚点旋转,为什么这样做,后面方便计算
                float3 view_pos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1));
                //dir
//记住这里是中心指向摄像机的方向作                                                                         为法线方向的,也暗示了两坐标系原点的重合
                normal_dir.y = normal_dir.y * _FaceDirCtr;
  float3 up_dir = abs(normal_dir.y) > 0.999 ? float3(0, 0, 1) : float3(0, 1, 0);//为了防止法                                                                                 线和向上的方向平行,这里不做解释,脑补一下
                float3 right_dir = normalize(cross(up_dir, normal_dir));
                up_dir = normalize(cross(normal_dir, right_dir));
   float3 offset = v.vertex - center; 
 float3 localPos = center + right_dir * offset.x + up_dir * offset.y + normal_dir * offset.z;//详细讲一下这个地方
                o.pos = UnityObjectToClipPos(float4(localPos,1));
                o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                return o;
            }

详细讲一下这个地方


float3 offset = v.vertex - center;

float3 localPos = center + right_dir * offset.x + up_dir * offset.y + normal_dir * offset.z;


这个问题其实本质上就是两个坐标空间之间的转换  所以先复习一下这个


unity开发游戏app对接抖音广告 unity3d广告_顶点着色器_02


当我们拥有条件:

1.子坐标系中各个轴在父坐标空间下的表达方式

 2.子坐标系原点在父坐标系下的位置的时候

我们就可以将一个点转换到另一个坐标空间下,可以用下面的公式:


unity开发游戏app对接抖音广告 unity3d广告_顶点着色器_03


来进行子空间里的物体向父空间的变换


而我们现在处理的这个问题,其实就是两个坐标系之间的顶点转换,我们现在有什么?子坐标系各个轴在父坐标系下的表示有了 ,子坐标系原点在父坐标系下的位置怎么获得,我们之前为什么把模型空间的原点设置成锚点?现在就起作用了,锚点是永远不会变的,而模型是围绕锚点转的,所以就导致了子坐标系的原点和父坐标系的原点重合,所以原点就是之前的center  (补充一下:不管你模型怎么转,你始终是围绕着那个锚点转的,锚点即是你的旋转中心,所以那个锚点位置就是第二个坐标空间的原点,而我们一开始就把锚点位置设置成了第一个坐标空间的原点位置,这就可以让两个坐标空间的原点重合,就免去了多余的计算)

现在所有条件都具备了,将条件代入公式得到变换后的点的位置:

 float3 localPos = center + right_dir * v.vertex.x + up_dir * v.vertex.y + normal_dir * v.vertex.z;

到这里所有功能就已经完成了,那为什么原来的公式却是这样的?

 float3 offset = v.vertex - center;

float3 localPos = center + right_dir * offset.x + up_dir * offset.y + normal_dir * offset.z;


两者是相等的

float3 offset = v.vertex - center; //从原点指向顶点的一个向量

float3 localPos = center + right_dir * offset.x + up_dir * offset.y + normal_dir * offset.z;//轴也是一个向量,向量和向量相乘是一个点,而我们要计算的最终结果其实是一个点的位置,所以这里做到了100分,而我们之前按公式做的那个是点和向量相乘,得到的是个向量,虽然不影响最终结果,但是只能拿90分.