ONB是在渲染器中看到的几个概念,不过这玩意我还是为了放心在houdini可视化了下。
毕竟这玩意其实跟Houdini中copy的正交基完全一个概念。建立up向量,形成正交矩阵.
ONB其实就是一个简单的正交基,但是只要是正交基就能表示在他作为 基的情况下的向量。 3个不相关向量 可以 唯一的线性表示任何向量.
作用:
(1),制作投射相机的投射光线方向
(2),lens_shader sampler points : 景深采样点的变换,方便得出 透镜与焦平面 光线投射方向
下面主要看如何快速的将一些采样点快速变换到 ONB坐标架下(2):
例如红色球是摄像机的目标点(target_point),蓝色点是眼睛的位置(eye)
蓝色的线可以看成一个向量,但是我们要的方向w是从 <红色点到蓝色的方向> 来建立 ONB坐标架.主要是满足右手坐标架
vector up = set(0,1,0); vector target_pos = point(1,"P",0); vector w = normalize(@P - target_pos); vector u = cross(up,w); vector v = cross(w,u); v@ww = w; v@uu = u; v@vv = v;
现在可以看到ww,uu,vv向量构建的正交基.
利用这个正交基可以快速的将采样点变换到这个ONB框架下.例如在 景深 这章。在单位圆(xy平面)的点要变换到这个坐标下:
vector eye = point(1,"P",0); vector u = point(1,"uu",0); vector v = point(1,"vv",0); @P = eye + u*@P.x + v*@P.y;
PBRT 2.2.5给出了一个从一个vector 构建一个coordinate system:
v1 是x轴向为图中的红色向量,v2是黄色,v3蓝色.
vector v1 = set(1,0,0); v@v1 = normalize(v1); if(abs(v1.x) > abs(v1.y)){ float invLen = 1.f / sqrt(v1.x * v1.x + v1.z*v1.z); v@v2 = set(-v1.z * invLen , 0.f , v1.x*invLen); } else { float invLen = 1.f / sqrt(v1.y * v1.y + v1.z*v1.z); v@v2 = set(0.0f, v1.z * invLen , -v1.y*invLen); } v@v3 = cross(@v1,@v2);