WebGL系列 - 裁剪空间矩阵优化

该系列仅为记录自己的学习相关知识。

以 2d 的顶点着色器为例

  <script  id="vertex-shader-2d" type="notjs">

  // an attribute will receive data from a buffer
  attribute vec4 a_position;

  // all shaders have a main function
  void main() {

    // gl_Position is a special variable a vertex shader
    // is responsible for setting
    gl_Position = a_position;
  }

</script>

我们知道,定义一个定点着色器,我们为了能够让我们定义的数据能够渲染到屏幕上,我们需要将屏幕中的点转化到裁剪空间中,以下是对应关系。

 裁剪空间            屏幕空间
   0, 0       ->   200, 150
   0, 0.5     ->   200, 225
 0.7, 0       ->   340, 150

会渲染出以下的图形

image-20211009005125727

我们会发现这个三角形是从中间开始,并且是朝向右上方的,是因为裁剪空间的x坐标范围是 -1 到 +1,而 (0,0) 在中心。

对于二维空间中的物体,我们更希望得到的是屏幕像素坐标而不是裁剪空间坐标。

<script id="vertex-shader-2d" type="x-shader/x-vertex">
        attribute vec2 a_position;
        
        uniform vec2 u_resolution;
        uniform mat3 u_matrix;
        
        void main() {
        
          // 从像素坐标转换到 0.0 到 1.0
          vec2 zeroToOne = position / u_resolution;
        
          // 再把 0->1 转换 0->2
          vec2 zeroToTwo = zeroToOne * 2.0;
        
          // 把 0->2 转换到 -1->+1 (裁剪空间)
          vec2 clipSpace = zeroToTwo - 1.0;
        
          gl_Position = vec4(clipSpace, 0, 1);
        }
</script>

因此对于输入的坐标点 (200, 150)( 200, 225)( 340, 150),我们可以渲染成

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PnvdtZU3-1633759639041)(/Users/huayifeng/Downloads/image-20211009010603385.png)]

而WebGL默认为左下角为 (0,0)想要像传统 API 一样右上角为 (0,0),我们只需要将 Y 轴反转gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);

<script id="vertex-shader-2d" type="notjs">

      // an attribute will receive data from a buffer
      attribute vec2 a_position;
 
      uniform vec2 u_resolution;
    
      // all shaders have a main function
      void main() {
        // 从像素坐标转换到 0.0 到 1.0
        vec2 zeroToOne = a_position / u_resolution;
     
        // 再把 0->1 转换 0->2
        vec2 zeroToTwo = zeroToOne * 2.0;
     
        // 把 0->2 转换到 -1->+1 (裁剪空间)
        vec2 clipSpace = zeroToTwo - 1.0;
     
        gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
      }
</script>

1633713038492

扫描二维码关注公众号,回复: 14652048 查看本文章

而为了能够更加简洁地描述,我们可以使用矩阵来进行描述

<script id="vertex-shader-2d" type="x-shader/x-vertex">
        attribute vec2 a_position;
         
        uniform mat3 u_matrix;
         
        void main() {
          // 使位置和矩阵相乘
          gl_Position = vec4((u_matrix * vec3(a_position, 1)).xy, 0, 1);
        }
</script>
var matrixLocation = gl.getUniformLocation(program, "u_matrix");

var m3 = {
    
    
  projection: function (width, height) {
    
    
    return [
      2 / width, 0, 0,
      0, -2 / height, 0,
      -1, 1, 1
    ];
  },
}

var matrix = m3.projection(gl.canvas.clientWidth, gl.canvas.clientHeight);

gl.uniformMatrix3fv(matrixLocation, false, matrix);

下面谈谈,关于以下式子的推导:
在这里插入图片描述

等价于以下式子,由于矩阵变化为从右到左。依次为

1.缩放到 [-1, 1]范围

2.放大2倍

3.x,y平移 -1

4.y轴反转
在这里插入图片描述

参考资料:GAMES101-现代计算机图形学入门-闫令琪

猜你喜欢

转载自blog.csdn.net/blueblueskyhua/article/details/120669891