html - WebGL: Canvas 坐标到 3d 坐标

标签 html webgl

我试图找到我的 WebGL 视口(viewport)的“左”边框,因为我想在那里绘制一些调试信息。 (像大多数建模程序一样的轴迷你 map ) 我当然可以获得包含 WebGL 视口(viewport)的 Canvas 的宽度和高度。

我真的很想知道如何将 2d Canvas 坐标计算为 3d 坐标?在 3d 视口(viewport)中找到左边框的最佳方法是什么?


任何研究这个的人都应该阅读 http://webglfactory.blogspot.com/2011/05/how-to-convert-world-to-screen.html或者看看 GluProject() 和 GluUnproject()

最佳答案

为了澄清 datenwolf 的回答,3D 空间和 2D Canvas 之间的坐标映射正是您想要的。您可以使用 gl.viewport 和传递给着色器的矩阵来控制它。

gl.viewport 只是在 Canvas 上绘制一个像素矩形。大多数情况下,这与 Canvas 的尺寸完全匹配,但在某些情况下,您只想绘制其中的一部分。 (例如,分屏游戏。)从这里开始,您正在绘制的 Canvas 区域将被称为视口(viewport)。如果愿意,您可以假设它与“ Canvas ”的含义相同。

最简单的是,视口(viewport)在 X 轴和 Y 轴上始终具有从 -1 到 1 的隐式坐标系。这是您的顶点着色器输出的 gl_Position 运行的空间。如果您在 (-1, -1) 处输出一个顶点,它将位于视口(viewport)的左下角。 (1, 1) 处的顶点将位于右上角。 (是的,我现在忽略了深度)使用它,您可以构建旨在映射到该空间的几何体并绘制它而根本不需要任何矩阵变换,但这可能有点尴尬。

为了让生活更轻松,我们使用投影矩阵。投影矩阵只是将几何体从任意 3D 空间转换为视口(viewport)所需的 -1 到 1 空间的矩阵。最常见的是透视矩阵。根据您使用的库,创建它的方式看起来会有所不同,但通常是这样的:

var fov = 45;
var aspectRatio = canvas.width/canvas.height;
var near = 1.0;
var far = 1024.0;
var projectionMat = mat4.perspective(fov, aspect, near, far);

我不打算深入探讨所有这些值的含义,但您可以清楚地看到我们正在使用 Canvas 宽度和高度来帮助设置此投影。这使得它不会根据 Canvas 大小看起来被拉伸(stretch)或压扁。然而,这一切归结为,将空间中的任何 3D 点与该矩阵相乘将产生一个映射到该 -1 到 1 空间的点,同时考虑到与“相机”和其他一切的距离。 (它实际上可能落在该范围之外,但这仅仅意味着它在镜头外。)这就是让我们的 3D 场景看起来像 3D 的原因。

不过,也可以创建专门用于绘制 2D 几何图形的投影矩阵。这称为正交矩阵,设置通常如下所示:

var left = 0;
var top = 0;
var right = canvas.width;
var bottom = canvas.height;
var near = 1.0;
var far = 1024.0;
var projectionMat = mat4.ortho(left, right, bottom, top, near, far);

此矩阵与透视矩阵的不同之处在于它完全忽略了您位置的 z 分量。相反,此矩阵将平面坐标(如像素)转换为 -1 到 1 的范围。因此,您的场景看起来不是 3D,但更容易精确控制屏幕上出现的位置。因此,使用上面的矩阵,如果我们在 (16, 16, 0) 处给它一个顶点,它将出现在我们 Canvas 上的 (16, 16) 处(假设视口(viewport)与 Canvas 的尺寸相同)。因此,当您想绘制平面 UI 元素之类的东西时,这就是您想要的矩阵类型!

好的部分是,因为这些只是您传递给着色器的值,所以您可以在一次绘制调用和下一次绘制调用中使用完全不同的矩阵。通常,您将使用透视矩阵绘制所有 3D 几何图形,然后使用正交矩阵绘制所有 UI。

如果有点乱,请见谅。我从来都不擅长解释所有这些数学方面的东西。

关于html - WebGL: Canvas 坐标到 3d 坐标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8985588/

相关文章:

glsl - 从顶点着色器更新信息

javascript - HTML 获取 URL、单选按钮组、javascript 解析、设置按钮值

javascript - 如何修复引用错误: firebase is not defined when all SDKs are in the HTML file

webgl - 如果我的显卡默认不支持 WebGL,我为什么要使用它?

javascript - 有没有办法让 WebGL 在屏幕外渲染,而无需将 webgl Canvas 附加到 DOM?

three.js - 轮廓对象(正常比例+模板掩模)三.js

javascript - onclick 事件以不同的方式执行相同的功能

html - 托管转换后不显示 CSS 背景图片

javascript - <div> 标签在选择其他时向上移动

webgl - 矩阵乘法与 glsl 中的向量