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

时间:2019-09-14 18:04:22

标签: javascript webgl

我想在没有webgl的情况下将一堆3d点渲染到2d画布中。 我以为剪辑空间和屏幕空间是同一回事,并且使用摄像头将3d世界空间转换为2d屏幕空间, 但显然不是。

因此在webgl上,设置gl_Position时,它位于剪辑空间中, 之后,此位置将通过webgl转换为屏幕空间,并设置gl_FragCoord。 该计算如何完成以及在何处进行?

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

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

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中提到的摄像机将剪辑空间转换为屏幕空间,如果这样,就不应该将其命名为摄像机吗?

1 个答案:

答案 0 :(得分:0)

首先根据裁剪空间坐标(gl_Position)裁剪几何。剪辑空间坐标为Homogeneous coordinates。齐次坐标位于剪辑空间中的条件是:

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

剪辑空间坐标通过Cartesian coordinate转换为规范化设备空间中的Perspective divide

ndc_position = gl_Position.xyz / gl_Position.w

归一化的设备空间是一个立方体,其左下角前部为(-1,-1,-1),右上角后部为(1,1,1)。

标准化设备空间坐标的x和y分量线性映射到视口,该视口由gl.viewport设置(请参见WebGL Viewport)。视口是一个具有原点(xy)和widthheight的矩形:

xw = (ndc_position.x + 1) * (width / 2) + x
yw = (ndc_position.y + 1) * (height / 2 ) + y 
片段着色器中的xw可以访问

ywgl_FragCoord.xy

归一化设备空间坐标的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

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

所有这些操作都是在渲染管道中自动完成的,并且是“顶点后处理”的一部分。