欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

webgl 常用的坐标系相互转换

程序员文章站 2022-03-10 16:57:38
...

webgl 常用的坐标系相互转换

纹理贴到canvas上,然后通过点击canvas上的点找纹理对应的位置然后反算世界坐标系
注意:cesium相机实时渲染纹理 默认会进行y轴翻转
1.拿到的fbo 经过readPixels后,会有一堆Uint8Array 数据 需要给转换成rgba;

    let r = pixels[i];
    let g = pixels[i + 1];
    let b = pixels[i + 2];
    let a = pixels[i + 3];

2.拿到这些值后需要根据canvas的宽度计算出对应的x,y值,简称canvas下的屏幕坐标.,

    let x = (i / 4) % width;
    let y = Math.floor(i / (4 * width));

3.由深度图和当前uv坐标得到当前像素的NDC坐标,

    let ndc = new Cesium.Cartesian4(); //等价于 Cesium.Cartesian4.UNIT_W
    ndc.x = (x / width) * 2.0 - 1.0;
    ndc.y = (y / height) * 2.0 - 1.0;
    ndc.z = 2;//宽度值
    ndc.w = 1.0;

4.然后只要采用View-Projection(视图-裁剪)的逆矩阵就可以将NDC坐标变换到世界坐标
注意:矩阵乘积的逆等于矩阵的逆的相反顺序的乘积
模型视图投影矩阵=投影矩阵×视图矩阵×模型矩阵
视图投影矩阵的逆矩阵 = 视图矩阵的逆矩阵 * 投影矩阵的逆矩阵

  let inverseViewProjection = Cesium.Matrix4.multiply(
      this.customCamera.inverseViewMatrix,//应该是生成纹理的当时的矩阵,不是scene 下的矩阵
      uniformState.inverseProjection,
      new Cesium.Matrix4()
    );
    let worldCoords = Cesium.Matrix4.multiplyByVector(
      inverseViewProjection,
      ndc,
      new Cesium.Cartesian4()
    );
    let w = 1.0 / worldCoords.w; //投影坐标的转ndc 需要除以w 分量
    Cesium.Cartesian3.multiplyByScalar(worldCoords, w, worldCoords);
    worldPositions.push(worldCoords);

到此为止世界坐标计算出来了,开始下一步.从canvas上拾取点然后换世界坐标
5.canvas 的坐标系和webgl的坐标系 不同,还有由于我的canvas 并不是全屏的

            let rect = canvas.getBoundingClientRect();
            let x = event.clientX - rect.left * (canvas.width / rect.width);
            let y = event.clientY - rect.top * (canvas.height / rect.height);

这样把x,y 值传入计算世界坐标的时候就能换算出点击canvas对应的世界坐标.其中坐标的转换包括canvas到webgl的坐标转换,屏幕坐标到ndc坐标转换,ndc 到世界坐标的转换.

相关标签: webgl