WebGL:画布坐标为3d坐标

Tom*_*Tom 4 html5 webgl

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

我真的想知道如何计算2d画布坐标到3d坐标?在3d视口中找到左边框的最佳方法是什么?


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

Toj*_*oji 7

为了阐明datenwolf的答案,3D空间和2D画布之间的坐标映射正是您想要的.您可以使用gl.viewport和传递到着色器的矩阵来控制它.

gl.viewport只是阻止你要绘制的画布上的像素矩形.大多数情况下,这与画布的尺寸完全匹配,但在某些情况下,您只想绘制其中的一部分.(例如,分屏游戏.)您要绘制的画布区域将从此处开始称为视口.如果你愿意,你可以认为它与"画布"的意思相同.

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

为了让生活更轻松,我们使用投影矩阵.投影矩阵只是将几何体从某个任意3D空间转换为视口所需的-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);
Run Code Online (Sandbox Code Playgroud)

我不会深入了解所有这些值的含义,但您可以清楚地看到我们使用画布宽度和高度来帮助设置此投影.这使得它看起来不会拉伸或压扁,具体取决于画布大小.然而,归结起来的是,在空间中取任何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);
Run Code Online (Sandbox Code Playgroud)

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

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

抱歉,如果那有点散漫.我从未非常擅长解释所有数学的东西.