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>
相关推荐
康康的幸福生活15 小时前
webgl2 方法解析: shaderSource()
webgl
魂断蓝桥6661 天前
如何基于three.js(webgl)引擎架构,实现3D医院、3D园区导航,3D科室路径导航
webgl·数字孪生·threejs·3d定位、三维室内定位、3d建筑·three.js路径规划、三维a*算法、javascript三维导航,·3d医院·3d导航·园区导航
康康的幸福生活11 天前
webgl2 方法解析: SCISSOR_TEST
javascript·webgl
魂断蓝桥66612 天前
如何基于three.js(webgl)引擎架构,实现3D机房园区,数据中心消防系统
webgl·数字孪生·three.js·物联网3d·3d机房·、3d工厂、3d工业园区、智慧制造、智慧工业、智慧工厂·bim管理系·3d消防·消防演习模拟
康康的幸福生活14 天前
webgl2 方法解析: colorMask()
webgl
Mapmost14 天前
全新升级!3DTiles加载速度Mapmost完胜Cesium
性能优化·webgl·cesium
康康的幸福生活15 天前
webgl2 方法解析: texImage2D()
webgl
点量云实时渲染-小芹16 天前
UE/Unity/Webgl云渲染推流网址,如何与外部网页嵌套和交互?
unity·webgl·webgl云渲染网页交互·点量云流
小old弟18 天前
🚀🚀🚀WebGL 加载 glTF 模型
前端·webgl
放逐者-保持本心,方可放逐21 天前
webgl(three.js 与 cesium 等实例应用)之浏览器渲染应用及内存释放的关联与应用
开发语言·javascript·webgl·顶点着色器·three.js 释放·cesium 释放·片元着色器