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 到世界座標的轉換.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章