尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

WebGIS开发进阶教程①:WebGL坐标系

WebGIS开发进阶教程①:WebGL坐标系 坐标系的分类WebGL 是如何把 3D 世界中的模型物体渲染到屏幕上的呢 这其中的最大难点就是坐标系的变换。在坐标系转换过程中都涉及“哪些坐标系”、“他们存在的意义是什么”、“其中的计算逻辑又是什么”等问题本文将详细的总结webgl当中的坐标系。WebGL 坐标系分为如下几类模型坐标系 -- 世界坐标系 -- 观察坐标系又称相机坐标系、视图坐标系 -- 裁剪坐标系**font stylecolor:rgb(255, 80, 44);background-color:rgb(255, 245, 245);gl_Position/font**接收的值 -- NDC 坐标系 -- 屏幕坐标系。其中裁剪坐标系之前的这几个坐标系我们都可以使用 JavaScript 控制。从裁剪坐标系到 NDC 坐标系这一个步骤是 顶点着色器的最后自动完成的我们无法干预。CPU 中将模型坐标转换成裁剪坐标顶点在模型坐标系中的坐标经过模型变换转换到世界坐标系中。然后通过摄像机观察这个世界将物体从世界坐标系中转换到观察坐标系。之后进行投影变换将物体从观察坐标系中转换到裁剪坐标系。具体代码实现我们一般会计算一个几何体的顶点这个顶点就是模型坐标然后这个顶点经过mvp变换然后赋值给gl_Position这个gl_Position所对应的坐标我们称之为裁剪坐标。gl_Positionu_ProjMatrix*u_ViewMatrix*u_ModelMatrix*vec4(a_Position,1.0);模型坐标系这个概念最好理解假如我们有一个箱子它的长宽高为10那么我们能够很轻松的计算出以这个箱子中心为原点的箱子顶点的坐标比如箱子左上角的模型坐标就是5,5,5,一般来说这种模型坐标系遵循右手坐标系。世界坐标系我们创建好的模型需要放在世界中的位置比如我在地球上的坐标是650000,500000,500000以地球为原点建立的坐标系对我来说就是一个世界坐标世界坐标系也是遵循右手坐标系X 轴水平向右Y 轴垂直向上Z 轴指向屏幕外面。具体到代码实现中就是vec4 positionmodelMatrix*a_Position;观察坐标系观察坐标系是将世界空间坐标转化为用户视野前方的坐标而产生的结果。**人眼或者摄像机**看到的世界中的物体**相对于他自身的位置所参照的坐标系就叫观察坐标系**。在我们日常生活中精准描述一个街道我们一般用经纬度来表示但是如果有人问你某某街道在什么位置如果我们告诉他世界坐标某某街道在东经 M 度北纬 N 度我想他会打你。一般我们都会用这样易于理解的描述在font stylecolor:rgb(255, 80, 44);background-color:rgb(255, 245, 245);前面多远往左或右走多远/font。这种坐标就称为观察坐标也叫相机坐标他是以人眼/摄像机为原点而建立的坐标系。具体到代码实现vec4 positionviewMatrix*modelMatrix*a_Position;裁剪坐标系裁剪坐标系遵循左手坐标系。相机坐标系观察的空间是整个 3D 世界而裁剪坐标系是希望所有的坐标都落在一个特定的范围内超出这个范围的顶点坐标都将被裁剪掉被裁剪掉的坐标就不会显示这就是裁剪坐标系的由来。具体到代码实现vec4 positionprojMatrix*viewMatrix*modelMatrix*a_Position;细心的同学可能会发现之前我们讲过投影矩阵它们分别是正交投影与透视投影它们是如何让物体变换到上图中的立方体空间中的呢正交投影变换首先看一下正交投影假设我们的点在左图中的长方体中第一步这个长方体会平移到世界坐标原点translate所以正交投影会有一个平移分量scale所以正交投影的缩放分量推导为为什么是**(f-n)****? **按照正常传参的情况, f的值比n的值大. 比如: f10, n1f表示的是远面和相机的距离n表示的是近面和相机的距离正交投影矩阵 缩放矩阵 x 位移矩阵由于上面的矩阵是在左手坐标系下计算的, 要映射到裁剪空间需要把z反转, 最终的正交投影矩阵如下透视投影变换透视投影也需要把物体变换到世界原点也需要缩放为一个立方体所以正交投影其实是透视投影的一个分量透视投影在正交投影的基础上还需要把金字塔的棱锥变为长方体即我们需要一个远面压缩矩阵这需要用来我们坐标的第四个分量齐次坐标。齐次坐标的作用假如有一条无限长的列车轨道虽然我们知道在物理上两条轨道是平行线是不会相交的但是在我们的眼睛里两条轨道在无穷远的位置会相交在一起这就是透视空间。那么如何用数学的方法来表示透视空间下轨道上的点呢。这是齐次坐标的第一个作用可以表示无穷远的点。在透视投影下齐次坐标可以用来处理透视投影矩阵的远面压缩矩阵当应用投影矩阵后顶点的坐标会被转换为齐次坐标然后通过透视除法除以w得到NDC裁剪坐标。代码示例远处的物体w更大 → x/y分量被压缩更明显 → 产生近大远小效果gl_Position.xyz / gl_Position.w另外一个作用是齐次坐标可以用来处理更复杂的变换比如将缩放和平移结合起来。透视投影矩阵推导深入研究-透视投影中深度与距离的对应关系在后续内容中会详细介绍。我让ai推导了这个对应关系我们只需要关注结果即可让n1,f100将公式用graphToy进行观测我们可以看到zView的值在-1到-∞之间时深度值在前期会变化的很快但是后期会变化的很慢以此得到结论所以我们在使用透视投影相机的时候尽量让near/far的比例合适这样可以避免一些遮挡问题因为webgl中是通过深度检测来判断物体的前后顺序的。比较合适的比例我们还可以在shader中调试深度值// 片段着色器 gl_FragColor vec4(vec3(gl_FragCoord.z), 1.0);纯白表示far平面纯黑表示near平面出现明显色阶断裂说明精度不足NDC坐标系Normalized device coordinates归一化设备坐标系上面的裁剪坐标已经是我们能通过编程得到的最细一层次的坐标了一个物体的模型坐标经过模型视图投影变换之后得到一个四阶的裁剪坐标 vec4(x,y,z,w)接着gpu会接受到这个四阶坐标并对x,y,z分别除以w分量这一步叫做透视除法经过这一步转换而来的坐标将会被归一化到一个立方体范围内如下图所示NDC 坐标系遵循font stylecolor:rgb(255, 80, 44);background-color:rgb(255, 245, 245);左手坐标系/fontZ 轴朝向屏幕里面Z轴值越小越靠近我们的眼睛我们之前的例子验证过webgl的深度检测这一点。屏幕坐标系有了 NDC 坐标之后GPU 会执行最后一步变换操作视口变换这个过程会将所有在【-1, 1】之间的坐标映射到屏幕空间中并被变换成片段。这一步主要由我们的viewPort来完成具体到代码实现gl.viewport(0,0,canvas.width,canvas.height)其中的转换公式为具体的步骤就是将x轴的 [-1,1] 转换为[startX,startX viewWidth]将y轴的[-1,1]转换为[startY,startY viewHeight]更多WebGIS开发干货教程请持续关注我们
返回列表