Billboard 的本质是一个参考相机坐标系的物体。
直接坐标系变换
该方法本质是假装物体的本地坐标是在相机坐标系下,将坐标从相机空间转到世界空间就会得到一个紧贴着相机的物体,再根据原始物体与相机的相对位置进行偏移,即可得到 Billboard。
适用于 UE 等难以直接获取矩阵的引擎
flowchart LR
%% 定义主要输入输出节点
LocalPosition["Local Position"]
TransformVector["<span style='white-space: nowrap'>Camera Space → World Space</span>"]
ObjectPosition["Object Position"]
Add["Add"]
%% 定义 Convert 子图(包含内部端口和连线)
subgraph Convert ["Convert"]
direction LR
In_R((X))
In_G((Y))
In_B((Z))
Out_R((X))
Out_G((Y))
Out_B((Z))
%% 内部交叉连接逻辑:R->G, G->R
In_R --> Out_G
In_G --> Out_R
In_B --> Out_B
end
%% 外部主流程连接
LocalPosition o--o Convert
Convert o--o TransformVector
TransformVector o--o Add
ObjectPosition o--o Add
Tips:
- 如果不反转 XY 相机看到的会是背面。
- 一般Billboard是没有厚度的,所以 Z 也可以不参与运算。
手动构建矩阵

即可实现如图所示,原物体 Z 轴/相机空间的 Up 轴 与 世界空间 Z 轴重合。
float3x3 M;
M._m00_m10_m20 = ResolvedView.ViewRight;
M._m01_m11_m21 = float3(0,0,1);
M._m02_m12_m22 = ResolvedView.ViewForward;
return mul(M, x);计算位置等价于:
float3 PositionTransform = Right * LocalPosition.y + Up * LocalPosition.x + Forward * LocalPosition.z;
float3 NewPosition = ObjectPosition + PositionTransform;