我想在没有 webgl 的情况下将一堆 3d 点渲染到 2d 画布中。我认为剪辑空间和屏幕空间是同一件事,相机用于从 3d 世界空间转换为 2d 屏幕空间,但显然它们不是。
所以在webgl上,设置时gl_Position,它是在剪辑空间中,后来这个位置被webgl转换为屏幕空间,并被gl_FragCoord设置。这个计算是如何进行的以及在哪里进行?
相机矩阵和视图投影矩阵与将剪辑空间转换为屏幕空间无关。我可以拥有一个适合剪辑空间的 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);
};
Run Code Online (Sandbox Code Playgroud)
本文提到的相机将剪辑空间转换为屏幕空间,如果是这样的话,它不应该被命名为相机,对吗?
首先,根据裁剪空间坐标 ( gl_Position) 裁剪几何体。剪辑空间坐标是齐次坐标。齐次坐标位于裁剪空间的条件是:
-w <= x, y, z <= w.
Run Code Online (Sandbox Code Playgroud)
通过Perspective div将剪辑空间坐标转换为标准化设备空间中的笛卡尔坐标:
ndc_position = gl_Position.xyz / gl_Position.w
Run Code Online (Sandbox Code Playgroud)
标准化设备空间是一个立方体,左下前部为(-1,-1,-1),右上后部为(1,1,1)。
标准化设备空间坐标的 x 和 y 分量线性映射到视口,其设置为gl.viewport(请参阅WebGL Viewport)。视口是一个具有原点 ( x, y) 以及 awidth和 a 的矩形height:
ndc_position = gl_Position.xyz / gl_Position.w
Run Code Online (Sandbox Code Playgroud)
xw并可以在片段着色器中yw访问。gl_FragCoord.xy
标准化设备空间坐标的 z 分量线性映射到深度范围,默认为 [0.0, 1.0],但可以通过 设置gl.depthRange。请参阅视口深度范围。深度范围由一个near值和一个far值组成。far必须大于near并且两个值都必须在 [0.0, 1.0] 范围内:
xw = (ndc_position.x + 1) * (width / 2) + x
yw = (ndc_position.y + 1) * (height / 2 ) + y
Run Code Online (Sandbox Code Playgroud)
可以在片段着色器中depth访问。gl_FragCoord.z
所有这些操作都是在渲染管道中自动完成的,并且是顶点后处理的一部分。
| 归档时间: |
|
| 查看次数: |
4968 次 |
| 最近记录: |