3d基礎 - 從模型座標到螢幕座標

新房客發表於2023-04-03

在 3D 引擎中,場景通常被描述為三維空間中的模型或物件,每個模型物件由許多三維頂點組成。最終,這些模型物件將在平面螢幕上呈現和顯示。
渲染場景始終相對於攝像機,因此,還必須相對於攝像機的檢視定義場景的頂點。瞭解一下這個轉換過程是相當有必要的。

上圖中,point為正方體的一個頂點point.

一般要經過4步變化。

  • 模型座標 -> 世界座標
  • 世界座標-> 相機座標
  • 相機座標 -> NDC
  • NDC > 螢幕座標

NDC是Normalized Device Coordinates 的縮寫,所謂Normalized Device就是指xyz三個軸向都是-1到1的空間

從程式碼角度看轉換的過程

/*
  立方體:
  - 大小 10x10x10
  - 世界座標 (0, 5, 0) 

  桔色小球的座標,在立方體的左上角,(-5, 5, 5)
*/

// cube.position.y = 5
// cube.add(sphere)
// sphere.position.set(-5, 5, 5)

const point = sphere.position.clone(); // (-5, 5, 5) aka relative to cube
console.log("point=", point);

//
// A: Model -> World
//

const M = cube.matrixWorld;
console.log("Model (World) Matrix", M);
point.applyMatrix4(M);
console.log("world-space point=", point);

//
// B: World -> Camera (aka View)
//

const V = camera.matrixWorldInverse;
console.log("View Matrix", V);
point.applyMatrix4(V);
console.log("view-space point=", point);

//
// C: Camera -> NDC
//

const P = camera.projectionMatrix;
console.log("Projection Matrix", P);
point.applyMatrix4(P);
console.log("clip coordinates", point);

//
// D: NDC -> Screen
//

const W = new THREE.Matrix4();
const { x: WW, y: WH } = renderer.getSize(new THREE.Vector2());
W.set(
  WW / 2, 0, 0, WW / 2,
  0, -WH / 2, 0, WH / 2,
  0, 0, 0.5, 0.5,
  0, 0, 0, 1
);
console.log("Window Matrix", W);
point.applyMatrix4(W);
console.log("window coordinates", point);

用一張圖更容易看懂這個過程:

相關的文章

https://webgl2fundamentals.org/webgl/lessons/zh_cn/webgl-matrix-naming.html
https://jsantell.com/model-view-projection/

相關文章