关于前端:WebGL-系列-12-WebGL-视口

3次阅读

共计 2860 个字符,预计需要花费 8 分钟才能阅读完成。

  • 原文地址:Day 12. Highdpi displays and webgl viewport
  • 原文作者:Andrei Lesnitsky

这是 WebGL 系列的第 12 天教程,每天都有新文章公布。

订阅或者退出邮件列表以便及时获取更新内容。

源代码在这里

嘿 ???? 欢送回到 WebGL 系列教程。

以前的所有教程都是在默认尺寸画布上实现的,当初让咱们应用更大的图片尺寸!

咱们先要对 CSS 进行一些调整,以便填满整个页面。

???? index.html

      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <meta http-equiv="X-UA-Compatible" content="ie=edge" />
      <title>WebGL Month</title>
+ 
+     <style>
+     html, body {
+       height: 100%;
+     }
+ 
+     body {
+       margin: 0;
+     }
+     </style>
    </head>
    <body>
      <canvas></canvas>

当初咱们能够读取页面尺寸:

???? src/texture.js

  const canvas = document.querySelector('canvas');
  const gl = canvas.getContext('webgl');
  
+ const width = document.body.offsetWidth;
+ const height = document.body.offsetHeight;
+ 
  const vShader = gl.createShader(gl.VERTEX_SHADER);
  const fShader = gl.createShader(gl.FRAGMENT_SHADER);
  

并设置画布尺寸:

???? src/texture.js

  const width = document.body.offsetWidth;
  const height = document.body.offsetHeight;
  
+ canvas.width = width;
+ canvas.height = height;
+ 
  const vShader = gl.createShader(gl.VERTEX_SHADER);
  const fShader = gl.createShader(gl.FRAGMENT_SHADER);
  

好的,已更改画布大小,然而咱们的图片并没有全屏显示,为什么?

事实证明,扭转画布大小是不够的,咱们还须要指定一个视口 viewport。将视口设置为矩形,它将用作绘图区域,并将其插值到 [-1...1] 剪贴空间。

???? src/texture.js

  
      gl.uniform2fv(programInfo.uniformLocations.resolution, [canvas.width, canvas.height]);
  
+     gl.viewport(0, 0, canvas.width, canvas.height);
+ 
      gl.drawElements(gl.TRIANGLES, indexBuffer.data.length, gl.UNSIGNED_BYTE, 0);
  });

当初咱们的图片填满了整个文档,然而有点含糊。起因不言而喻的 – 咱们的纹理不够大,为此应该拉伸它并革除品质。然而,还有另一个起因。

古代显示器在物理像素大小(苹果称其为视网膜)中能够包容更多的理论像素,有一个全局变量 devicePixelRatio 能够帮忙咱们。

???? src/texture.js

  const width = document.body.offsetWidth;
  const height = document.body.offsetHeight;
  
- canvas.width = width;
- canvas.height = height;
+ canvas.width = width * devicePixelRatio;
+ canvas.height = height * devicePixelRatio;
  
  const vShader = gl.createShader(gl.VERTEX_SHADER);
  const fShader = gl.createShader(gl.FRAGMENT_SHADER);

好的,当初咱们的画布具备适合的尺寸,然而它比视网膜显示屏上的主体大。咱们该如何解决?

咱们能够应用 CSS 的 widthheight 属性将画布放大到理论尺寸。

???? src/texture.js

  canvas.width = width * devicePixelRatio;
  canvas.height = height * devicePixelRatio;
  
+ canvas.style.width = `${width}px`;
+ canvas.style.height = `${height}px`;
+ 
  const vShader = gl.createShader(gl.VERTEX_SHADER);
  const fShader = gl.createShader(gl.FRAGMENT_SHADER);
  

总而言之,画布的 widthheight 属性指定像素理论大小,但为了使画面显示锐利的 highdpi,咱们须要应用 devicePixelRatio 乘以 widthheight,并用 CSS 放大画布背景的规模。

当初咱们能够让画布从新调整大小。

???? src/texture.js

  
      gl.drawElements(gl.TRIANGLES, indexBuffer.data.length, gl.UNSIGNED_BYTE, 0);
  });
+ 
+ 
+ window.addEventListener('resize', () => {
+     const width = document.body.offsetWidth;
+     const height = document.body.offsetHeight;
+ 
+     canvas.width = width * devicePixelRatio;
+     canvas.height = height * devicePixelRatio;
+ 
+     canvas.style.width = `${width}px`;
+     canvas.style.height = `${height}px`;
+ 
+     gl.viewport(0, 0, canvas.width, canvas.height);
+ });

然而,调整大小后会革除画布内容。原来,对 widthheight 属性的批改,会迫使浏览器革除画布(2d 上下文也是如此),因而咱们须要再次收回绘图调用。

???? src/texture.js

      canvas.style.height = `${height}px`;
  
      gl.viewport(0, 0, canvas.width, canvas.height);
+ 
+     gl.drawElements(gl.TRIANGLES, indexBuffer.data.length, gl.UNSIGNED_BYTE, 0);
  });

明天就这样,今天见????

正文完
 0