WebGL笔记:图形缩放的原理和实现

缩放

1 )原理

  • 缩放可以理解为对向量长度的改变,或者对向量坐标分量的同步缩放
    • 如下图,比如
    • 让向量OA 收缩到点B的位置,也就是从OA变成OB,缩放了一半

2 )公式

  • 已知

    • 点A的位置是(ax,ay,az)
    • 点A基于原点內缩了一半
    • 点A內缩了一半后的bx、by、bz位置B
  • js 复制代码
    bx = ax * 0.5
    by = ay * 0.5
    bz = az * 0.5

在着色器中缩放

1 )核心代码

  • 可以对gl_Position 的x、y、z依次缩放

    html 复制代码
    <script id="vertexShader" type="x-shader/x-vertex">
      attribute vec4 a_Position;
      float scale = 1.2; // 注意这里声明了浮点型,一点要用浮点数,否则会导致 UseProgram: program not valid 的警告
      void main() {
        gl_Position.x = a_Position.x * scale;
        gl_Position.y = a_Position.y * scale;
        gl_Position.z = a_Position.z * scale;
        gl_Position.w = 1.0; // 注意 w 的值,默认1.0
      }
    </script>
  • 也可以从a_Position中抽离出由x、y、z组成的三维向量,对其进行一次性缩放

    html 复制代码
    <script id="vertexShader" type="x-shader/x-vertex">
      attribute vec4 a_Position;
      float scale = 1.2;
      void main() {
        gl_Position = vec4(vec3(a_Position) * scale, 1.0);
      }
    </script>

2 )完整代码

html 复制代码
<canvas id="canvas"></canvas>
<script id="vertexShader" type="x-shader/x-vertex">
  attribute vec4 a_Position;
  float scale = 1.0;
  void main() {
      gl_Position = vec4(vec3(a_Position) * scale, 1.0);
  }
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
  void main(){
      gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
  }
</script>
<script type="module">
  import { initShaders } from './utils.js';

  const canvas = document.getElementById('canvas');
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
  const gl = canvas.getContext('webgl');
  const vsSource = document.getElementById('vertexShader').innerText;
  const fsSource = document.getElementById('fragmentShader').innerText;
  initShaders(gl, vsSource, fsSource);

  const vertices = new Float32Array([
    0.0, 0.1,
    -0.1, -0.1,
    0.1, -0.1
  ])

  const vertexBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
  const a_Position = gl.getAttribLocation(gl.program, 'a_Position');
  gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
  gl.enableVertexAttribArray(a_Position);
  gl.clearColor(0.0, 0.0, 0.0, 1.0);
  gl.clear(gl.COLOR_BUFFER_BIT);
  gl.drawArrays(gl.TRIANGLES, 0, 3);
</script>

用js缩放图形

1 )核心代码

  • 同样的我们也可以把缩放系数暴露给js,通过js 缩放图形
    • 建立uniform变量

      html 复制代码
      <script id="vertexShader" type="x-shader/x-vertex">
          attribute vec4 a_Position;
          uniform float u_Scale;
          void main() {
              gl_Position = vec4(vec3(a_Position) * u_Scale, 1.0);
          }
      </script>
    • 使用js获取并修改uniform 变量

      js 复制代码
      const u_Scale = gl.getUniformLocation(gl.program, 'u_Scale')
      gl.uniform1f(u_Scale, 1.0)
    • 添加动画让其动起来

      js 复制代码
      let angle = 0
      !(function animate() {
          angle += 0.05;
          const scale = Math.sin(n) + 1; // 借助三角函数正弦进行缩放 (-1, 1) + 1 => (0, 2)
          gl.uniform1f(u_Scale, scale);
          gl.clear(gl.COLOR_BUFFER_BIT);
          gl.drawArrays(gl.TRIANGLES, 0, 3);
          requestAnimationFrame(animate)
      })()

2 )完整代码

html 复制代码
<canvas id="canvas"></canvas>
<script id="vertexShader" type="x-shader/x-vertex">
  attribute vec4 a_Position;
  uniform float u_Scale;
  void main() {
      gl_Position = vec4(vec3(a_Position) * u_Scale, 1.0);
  }
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
  void main() {
      gl_FragColor = vec4(1.0,1.0,0.0,1.0);
  }
</script>
<script type="module">
  import { initShaders } from './utils.js';

  const canvas = document.getElementById('canvas');
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
  const gl = canvas.getContext('webgl');

  const vsSource = document.getElementById('vertexShader').innerText;
  const fsSource = document.getElementById('fragmentShader').innerText;
  initShaders(gl, vsSource, fsSource);
  
  const vertices = new Float32Array([
    0.0, 0.1,
    -0.1, -0.1,
    0.1, -0.1
  ])

  const vertexBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
  const a_Position = gl.getAttribLocation(gl.program, 'a_Position');
  gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
  gl.enableVertexAttribArray(a_Position);

  const u_Scale = gl.getUniformLocation(gl.program, 'u_Scale')
  gl.uniform1f(u_Scale, 1);

  gl.clearColor(0.0, 0.0, 0.0, 1.0);
  gl.clear(gl.COLOR_BUFFER_BIT);
  gl.drawArrays(gl.TRIANGLES, 0, 3);

  let angle = 0;
  !(function animate() {
    angle += 0.05;
    const scale = Math.sin(angle) + 1;
    gl.uniform1f(u_Scale, scale);
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.TRIANGLES, 0, 3);
    requestAnimationFrame(animate);
  })()
</script>
相关推荐
ThreePointsHeat4 天前
Unity WebGL打包后启动方法,部署本地服务器
unity·游戏引擎·webgl
林枫依依5 天前
电脑配置流程(WebGL项目)
webgl
冥界摄政王7 天前
CesiumJS学习第四章 替换指定3D建筑模型
3d·vue·html·webgl·js·cesium
温宇飞9 天前
高效的线性采样高斯模糊
javascript·webgl
冥界摄政王10 天前
Cesium学习第一章 安装下载 基于vue3引入Cesium项目开发
vue·vue3·html5·webgl·cesium
光影少年12 天前
三维前端需要会哪些东西
前端·webgl
nnsix13 天前
Unity WebGL jslib 通信时,传入字符串,变成数值 问题
webgl
二狗哈13 天前
Cesium快速入门34:3dTile高级样式设置
前端·javascript·算法·3d·webgl·cesium·地图可视化
AlanHou13 天前
Three.js:Web 最重要的 3D 渲染引擎的技术综述
前端·webgl·three.js
二狗哈14 天前
Cesium快速入门33:tile3d设置样式
3d·状态模式·webgl·cesium·地图可视化