文章目录
- 前言
- 一、实现思路
- 1、 我们要实现模型面片一直跟着摄像机旋转,那么就需要用到旋转矩阵
- 2、确定 原坐标系 和 目标坐标系
- 3、确定旋转后坐标系基向量
- 二、确定旋转后 坐标系基向量 在 原坐标系 下的值
- 1、Z轴基向量
- 2、假设Y轴基向量 和 世界空间下 的Y轴方向一致竖直向上
- 3、X轴基向量
- 4、Y轴基向量
- 三、最终整合
前言
在之前的文章中,我们实现了Shader的序列帧动画。
- Unity中Shader序列帧动画(总结篇)
但是,我们会发现,我们的面片不会一直面向摄像机,当摄像机移动时,人物或特效就会出现穿帮的效果。所以,我们接下来就来实现让我们的面片面向摄像机。
类似的功能,还可能用于:特效、公告牌、八方旅人风格效果、饥荒风格效果。
一、实现思路
1、 我们要实现模型面片一直跟着摄像机旋转,那么就需要用到旋转矩阵
- Unity中Shader旋转矩阵(二维旋转矩阵)
- Unity中Shader旋转矩阵(四维旋转矩阵)
2、确定 原坐标系 和 目标坐标系
- 原坐标系 就是模型的本地坐标
- 目标坐标系
因为我们的面片需要一直朝向摄像机。
所以,可以确定旋转后的坐标系Z轴方向 需要 和 原模型本地空间坐标系原点 指向 摄像机 方向一致。
3、确定旋转后坐标系基向量
二、确定旋转后 坐标系基向量 在 原坐标系 下的值
1、Z轴基向量
- 求 摄像机坐标 在模型本地空间下的坐标值,在 归一化后 就是 Z轴基向量
float3 viewDir = normalize(mul(GetWorldToObjectMatrix(),_WorldSpaceCameraPos));
2、假设Y轴基向量 和 世界空间下 的Y轴方向一致竖直向上
float3 upDir = float3(0,1,0);
3、X轴基向量
-
X轴基向量 = Z轴基向量 × Y轴基向量
-
叉积 的顺序取决于 坐标系类型 (逆时针叉积)
-
模型本地空间坐标系为左手坐标系
-
左手坐标系中,X轴 = 食指 × 拇指 = Z × Y
float3 rightDir = cross(viewDir,upDir);
4、Y轴基向量
- Y轴基向量 = X轴基向量 × Z轴基向量
- 叉积 的顺序取决于 坐标系类型 (逆时针叉积)
- 模型本地空间坐标系为左手坐标系
- 左手坐标系中,Y轴 = 中指 × 食指 = X × Z
upDir = cross(rightDir,viewDir);
三、最终整合
- 在顶点着色器中,该操作需要在转化到齐次裁剪空间前完成。
//Z轴基向量
float3 viewDir = normalize(mul(GetWorldToObjectMatrix(),_WorldSpaceCameraPos));
//假设Y轴基向量
float3 upDir = float3(0,1,0);
//X轴基向量(左手坐标系、逆时针叉乘)
float3 rightDir = cross(viewDir,upDir);
//Y轴基向量(左手坐标系、逆时针叉乘)
upDir = cross(rightDir,viewDir);