相机如何从剪辑 space 转换为屏幕 space?

How Does a camera convert from clip space into screen space?

我想在没有 webgl 的情况下将一堆 3d 点渲染成 2d canvas。 我以为clipspace和screenspace是一回事,camera是用来把3d worldspace转成2d screenspace的, 但显然他们不是。

所以在webgl上,设置gl_Position的时候,是在剪辑space, 后来这个位置被webgl转换为screen space,并且设置了gl_FragCoord。 这个计算是如何完成的,在哪里完成的?

并且相机矩阵和视图投影矩阵与将剪辑 space 转换为屏幕 space 无关。 我可以拥有适合剪辑 space 的 3d 世界 space,而且我不需要使用相机,对吗?

如果我的所有假设都是正确的,我需要学习如何将剪辑 space 转换为屏幕 space。 这是我的代码:

const uMatrix = mvpMatrix(modelMatrix(transform));

 // transform each vertex into 2d screen space
vertices = vertices.map(vertex => {
  let res = mat4.multiplyVector(uMatrix, [...vertex, 1.0]);
  // res is vec4 element, in clip space,
  // how to transform this into screen space?
  return [res[0], res[1]];
});


// viewProjectionMatrix calculation
const mvpMatrix = modelMatrix => {
  const { pos: camPos, target, up } = camera;
  const { fov, aspect, near, far } = camera;

  let camMatrix = mat4.lookAt(camPos, target, up);
  let viewMatrix = mat4.inverse(camMatrix);

  let projectionMatrix = mat4.perspective(fov, aspect, near, far);

  let viewProjectionMatrix = mat4.multiply(projectionMatrix, viewMatrix);

  return mat4.multiply(viewProjectionMatrix, modelMatrix);
};

this article 中提到的摄像头将剪辑 space 转换为屏幕 space,如果是这样,它不应该被命名为摄像头吗?

首先根据剪辑space 坐标(gl_Position) 剪辑几何体。剪辑 space 坐标是 Homogeneous coordinates。齐次坐标在剪辑space中的条件是:

-w <=  x, y, z  <= w.

剪辑 space 坐标转换为 Cartesian coordinate in normalized device space, by Perspective divide:

ndc_position = gl_Position.xyz / gl_Position.w

归一化设备space是一个立方体,左下前方为(-1, -1, -1),右上后方为(1, 1, 1)。

标准化设备 space 坐标的 x 和 y 分量线性映射到视口,由 gl.viewport 设置(参见 WebGL Viewport)。视口是一个矩形,原点 (x, y) 和 width 以及 height:

xw = (ndc_position.x + 1) * (width / 2) + x
yw = (ndc_position.y + 1) * (height / 2 ) + y 

xwyw可以在片段着色器中通过gl_FragCoord.xy访问。

标准化设备space坐标的z分量线性映射到深度范围,默认为[0.0, 1.0],但可以通过gl.depthRange设置。参见 Viewport Depth Range。深度范围由 near 值和 far 值组成。 far 必须大于 near 并且两个值都必须在 [0.0, 1.0]:

范围内
depth = (ndc_position.z + 1) * (far-near) / 2 + near

片段着色器中gl_FragCoord.z可以访问depth

所有这些操作都是在渲染管道中自动完成的,并且是顶点 Post-Processing 的一部分。