最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • WebGL基本图形三角形的绘制

    正文概述 掘金(慕斯不想说话)   2021-06-15   636

    三角形的绘制比点的绘制多对多一个步骤。那就是三角形需要创建缓冲区。有以下几种绘制三角形的方法。 三种绘制方式的代码几乎是一样的。只是在进行渲染时drawArrays(type,start,count)中的type不一样。

    以下例子主要用到以下GLSL知识。

    gl.createBuffer:创建buffer。
    gl.bindBuffer:绑定某个缓冲区对象为当前缓冲区。
    gl.bufferData:往缓冲区中复制数据。
    gl.enableVertexAttribArray:启用顶点属性。
    gl.vertexAttribPointer:设置顶点属性从缓冲区中读取数据的方式。
    
    • 顶点着色器代码
    <script id="vertexShader" type="x-shader/x-vertex">
      //attribute声明vec4类型变量apos
      attribute vec4 apos;
      void main() {
        //顶点坐标apos赋值给内置变量gl_Position
        //逐顶点处理数据
        gl_Position = apos;
      }
    </script>
    
    • 片元着色器代码
    <script id="fragmentShader" type="x-shader/x-fragment">
      void main() {
        // 逐片元处理数据,所有片元(像素)设置为红色
        gl_FragColor = vec4(1.0,0.0,0.0,1.0);
      }
    </script>
    
    • javascript代码,主要由以下4部分代码构成
      • 获取WebGL上下文
      //通过getElementById()方法获取canvas画布
      const canvas = document.getElementById('webgl');
      //通过方法getContext()获取WebGL上下文
      const gl = canvas.getContext('webgl');
      //初始化着色器
      const program = initShader(gl);
      //初始化缓存区
      const count = initBuffer(gl);
      render(gl, program, count);
      
      • 声明初始化着色器函数
      //声明初始化着色器函数
      function initShader(gl) {
          //顶点着色器源码
          const vertexShaderSource = document.getElementById('vertexShader').innerText;
          //片元着色器源码
          const fragmentShaderSource = document.getElementById('fragmentShader').innerText;
          const vertexShader = gl.createShader(gl.VERTEX_SHADER);
          const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
          gl.shaderSource(vertexShader, vertexShaderSource);
          gl.shaderSource(fragmentShader, fragmentShaderSource);
          gl.compileShader(vertexShader);
          gl.compileShader(fragmentShader);
          const program = gl.createProgram();
          gl.attachShader(program, vertexShader);
          gl.attachShader(program, fragmentShader);
          gl.linkProgram(program);
          gl.useProgram(program);
          return program;
      }
      
      • 初始化缓冲数据
      //初始化缓冲数据
      function initBuffer(gl) {
          //类型数组构造函数Float32Array创建顶点数组
          const data = new Float32Array([
          -0.5, 0.5,
          -0.5, -0.5,
          0.5, 0.5,
          ]);
      
          //创建缓冲区对象
          var buffer = gl.createBuffer();
          //绑定缓冲区对象,激活buffer
          gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
          //顶点数组data数据传入缓冲区
          gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
          return data.length;
      }
      
      • 渲染
      function render(gl, program, count) {
          //获取顶点着色器的位置变量apos,即aposLocation指向apos变量。
          const aposLocation = gl.getAttribLocation(program, 'apos');
      
          //缓冲区中的数据按照一定的规律传递给位置变量apos
          gl.vertexAttribPointer(aposLocation, 2, gl.FLOAT, false, 0, 0);
          //允许数据传递
          gl.enableVertexAttribArray(aposLocation);
          //设置清屏颜色为黑色。
          gl.clearColor(0, 0, 0, 1.0);
          //清屏
          gl.clear(gl.COLOR_BUFFER_BIT);
          //开始绘制图形
          gl.drawArrays(gl.TRIANGLES, 0, count);
      }
      

    1、常规方式

    gl.drawArrays(gl.TRIANGLES, 0, 3);
    

    2、三角形带

    WebGL基本图形三角形的绘制

    绘制三角形的数量 = 顶点数 - 2

     gl.drawArrays(gl.TRIANGLE_STRIP, 0, 3);
    

    3、三角形扇

    WebGL基本图形三角形的绘制

    绘制三角形的数量 = 顶点数 - 2

     gl.drawArrays(gl.TRIANGLE_FAN, 0, 3);
    

    4、动态绘制三角形

    着色器中的代码跟动态绘制点的代码几乎是一样的。只是多了一个颜色插值的处理。

    • 顶点着色器代码
    <script type="shader-source" id="vertexShader">
        //浮点数设置为中等精度
        precision mediump float;
        //接收 JavaScript 传递过来的点的坐标(X, Y)
        attribute vec2 a_Position;
        attribute vec4 a_Color;
        varying vec4 v_Color;
        void main(){
            // 最终的顶点坐标。
            gl_Position = vec4(a_Position, 0.0, 1.0);
            //进行颜色插值计算
            v_Color = a_Color;
        }
    </script>
    
    • 片元着色器代码
    <script type="shader-source" id="fragmentShader">
        //浮点数设置为中等精度
        precision mediump float;
        // 用来接收顶点着色器插值后的颜色。
        varying vec4 v_Color;
        void main(){
            // 点的最终颜色。
            gl_FragColor =  v_Color;
        }
    </script>
    
    • javascript代码
      • WebGL上下文的获取
      //通过getElementById()方法获取canvas画布
      const canvas = document.getElementById('webgl');
      //设置canvas尺寸为满屏
      //注意设置canvas的尺寸必须在获取WebGL上下文之前调用
      resizeCanvas(canvas);
      //通过方法getContext()获取WebGL上下文
      const gl = canvas.getContext('webgl');
      
      • canvas的尺寸动态设置
      //设置canvas的大小
      function resizeCanvas(canvas, width, height) {
          if (canvas.width !== width) {
              canvas.width = width ? width : window.innerWidth;
          }
          if (canvas.height !== height) {
              canvas.height = height ? height : window.innerHeight;
          }
      }
      
      • 着色器中的变量赋值处理
      function assignValue(gl,program){
          let a_Position = gl.getAttribLocation(program, 'a_Position');
          let a_Color = gl.getAttribLocation(program, 'a_Color');
          gl.enableVertexAttribArray(a_Position);
          gl.enableVertexAttribArray(a_Color);
          let buffer = gl.createBuffer();
          gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
          //将缓冲区中的数据按照一定规律传递给a_Position,表示从缓存区中获取两个浮点型数据(浮点型数据,4个字节),缓存区一行为4*6个字节,偏移量为0
          gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 4*6, 0);
          gl.vertexAttribPointer(a_Color, 4, gl.FLOAT, false,4*6, 8);
      }
      
      • 点击事件监听
      const positions = [];
      function initClick() {  
          canvas.addEventListener("click", e => {
              const color = randomColor();
              const position = coordTransform(e.pageX, e.pageY)
              positions.push(...position, ...Object.values(color));
              // 顶点信息为 18 的整数倍即3个顶点时执行绘制操作,因为三角形由三个顶点组成,每个顶点由六个元素组成。
              if (positions.length % 18 == 0) {
                  // gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
                  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
                  render(gl);
              }
          })
      }
      //颜色值的随机生成
      const random = Math.random;
      function randomColor() {
          return {
              r: random(),
              g: random(),
              b: random(),
              a: random()
          };
      }
      
      • 声明初始化着色器函数
      //声明初始化着色器函数
      function initShader(gl) {
          //顶点着色器源码
          const vertexShaderSource = document.getElementById('vertexShader').innerText;
          //片元着色器源码
          const fragmentShaderSource = document.getElementById('fragmentShader').innerText;
          const vertexShader = gl.createShader(gl.VERTEX_SHADER);
          const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
          gl.shaderSource(vertexShader, vertexShaderSource);
          gl.shaderSource(fragmentShader, fragmentShaderSource);
          gl.compileShader(vertexShader);
          gl.compileShader(fragmentShader);
          const program = gl.createProgram();
          gl.attachShader(program, vertexShader);
          gl.attachShader(program, fragmentShader);
          gl.linkProgram(program);
          gl.useProgram(program);
          return program;
      }
      
      • 屏幕坐标换算成裁剪坐标系(顶点着色器)的坐标
      //屏幕坐标换算成裁剪坐标系的坐标(在着色器中的坐标)
      const { width, height } = canvas;
      function coordTransform(x, y) {
          // 将 canvas 的坐标值 转换为 [-1.0, 1.0]的范围。
          const posisionX = 2 * x / width - 1;
          // canvas的 Y 轴坐标方向和 裁剪坐标系的相反。
          const positionY = -(2 * y / height - 1);
          return [posisionX, positionY];
      }
      
      • WebGL渲染
      function render(gl) {
          //设置清屏颜色为黑色。
          gl.clearColor(0, 0, 0, 1);
          gl.clear(gl.COLOR_BUFFER_BIT);
          if (positions.length > 0) {
              gl.drawArrays(gl.TRIANGLES, 0, positions.length / 6);
          }
      }
      //创建着色器程序
      const program = initShader(gl);
      constassignValue(gl,program)
      initClick();
      render(gl);
      

    参考

    WebGL零基础入门教程(郭隆邦);
    WebGL 入门与实践
    WebGL官方文档


    起源地下载网 » WebGL基本图形三角形的绘制

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元