相机如何从剪辑 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
xw
和yw
可以在片段着色器中通过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 的一部分。
我想在没有 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
xw
和yw
可以在片段着色器中通过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 的一部分。