zoukankan      html  css  js  c++  java
  • WebGL学习笔记二——绘制基本图元

    webGL的基本图元点、线、三角形

    gl.drawArrays(mode, first,count)

      first,代表从第几个点开始绘制即顶点的起始位置

      count,代表绘制的点的数量。

      mode,代表图元类型。

        (1)gl.POINTS——点

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
        <head>
            <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
            <title>WebGL</title>
        </head>
        <body style="background: #000">
            <canvas id="canvas"></canvas>
        </body>
        <!-- 顶点着色器源码 -->
        <script type="shader-source" id="vertexShader">
            //接收顶点坐标 (x, y)
            attribute vec2 a_Position;
            void main(){
                   gl_Position = vec4(a_Position, 0, 1);
                   gl_PointSize = 10.0;
            }
        </script>
    
        <!-- 片元着色器源码 -->
        <script type="shader-source" id="fragmentShader">
            void main(){
                   gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
            }
        </script>
        <script type="text/javascript" src="helper.js"></script>
        <script type="text/javascript">
    
            var canvas = getCanvas('#canvas');
            resizeCanvas(canvas);
            var gl = getContext(canvas);
            //创建顶点着色器
            var vertexShader = createShaderFromScript(gl, gl.VERTEX_SHADER,'vertexShader');
            //创建片元着色器
            var fragmentShader = createShaderFromScript(gl, gl.FRAGMENT_SHADER,'fragmentShader');
            //创建着色器程序
            var program = createSimpleProgram(gl ,vertexShader, fragmentShader);
            // 使用刚创建好的着色器程序。
            gl.useProgram(program);
    
            //创建缓冲区
            var positions= new Float32Array([
                0.0,0.5,
                0.5,0.0,
                0.5,0.5,
                0.0,0.9,
                -0.5,0.5,
                -0.5,0.0,
                ]);
            var a_Position = gl.getAttribLocation(program, 'a_Position')
            var buffer = gl.createBuffer();
            gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
            gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
    
            //每次取两个数据
            var size = 2;
            //每个数据的类型是32位浮点型
            var type = gl.FLOAT;
            //不需要归一化数据
            var normalize = false;
            // 每次迭代运行需要移动数据数 * 每个数据所占内存 到下一个数据开始点。
            var stride = 0;
            // 从缓冲起始位置开始读取
            var offset = 0;
            // 将 a_Position 变量获取数据的缓冲区指向当前绑定的 buffer。
            gl.vertexAttribPointer(a_Position, size, type, normalize, stride, offset);
            gl.enableVertexAttribArray(a_Position);
          
            var primitiveType = gl.POINTS;
            var offset = 0;
            var count = 6;
            gl.drawArrays(primitiveType, offset, count);
    
        </script>
    </html>

        gl.LINES——线段

          一系列单独的线段

        将上面代码的primitiveType赋值部分改为:  primitiveType = gl.LINES;

     

        gl.LINE_STRIP——线条

          一系列连接的线段

        将上面代码的primitiveType赋值部分改为: primitiveType = gl.LINE_STRIP;

        gl.LINE_LOOP——回路线条

          一系列连接的线段,最后一个点会与开始的点相连接(vn,v0),线段会闭合

         将上面代码的primitiveType赋值部分改为:primitiveType = gl.LINE_LOOP;

        gl.TRIANGLES——基本三角形

          是一个个独立的三角形

        将上面代码的primitiveType赋值部分改为: primitiveType = gl.TRIANGLES;

        gl.TRIANGLE_STRIP——三角带

          一些列条带状的三角形,前三个点构成第一个三角形,从第二个点开始的三个点构成第二个三角形

        将上面代码的primitiveType赋值部分改为: primitiveType = gl.TRIANGLE_STRIP;

        gl.TRIANGLE_FAN——三角扇 

          以第一个顶点作为所有三角形的顶点进行绘制的

        将上面代码的primitiveType赋值部分改为: primitiveType = gl.TRIANGLE_FAN;

    helper.js

    var random = Math.random;
    function randomColor() {
      return {
        r: random() * 255,
        g: random() * 255,
        b: random() * 255,
        a: random() * 1
      };
    }
    function $$(str) {
      if (!str) return null;
      if (str.startsWith('#')) {
        return document.querySelector(str);
      }
      let result = document.querySelectorAll(str);
      if (result.length == 1) {
        return result[0];
      }
      return result;
    }
    function getCanvas(id) {
      return $$(id);
    }
    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 getContext(canvas) {
      return canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
    }
    function createSimpleProgram(gl, vertexShader, fragmentShader) {
      if (!vertexShader || !fragmentShader) {
        console.warn('着色器不能为空');
        return;
      }
      let program = gl.createProgram();
      gl.attachShader(program, vertexShader);
      gl.attachShader(program, fragmentShader);
      gl.linkProgram(program);
      let success = gl.getProgramParameter(program, gl.LINK_STATUS);
      if (success) {
        return program;
      }
      console.error(gl.getProgramInfoLog(program));
      gl.deleteProgram(program);
    }
    
    function createShader(gl, type, source) {
      let shader = gl.createShader(type);
      gl.shaderSource(shader, source);
      gl.compileShader(shader);
      //检测是否编译正常。
      let success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
      if (success) {
        return shader;
      }
      console.error(gl.getShaderInfoLog(shader));
      gl.deleteShader(shader);
    }
    function createShaderFromScript(gl, type, scriptId) {
      let sourceScript = $$('#' + scriptId);
      if (!sourceScript) {
        return null;
      }
      return createShader(gl, type, sourceScript.innerHTML);
    }
    View Code

    说明:

     使用缓冲区对象的流程:

    a.创建缓冲区对象(gl.createBuffer());
    b.把缓冲区对象(gl.bindBuffer())绑定到目标对象上(gl.ARRAY_BUFFER);
    c.将数据写入缓冲区对象(gl.bufferData());
    d.将缓冲区对象分配给attribute变量(gl.vertexAttribPointer());
    e.开启attribute变量(gl.enableVertexAttribrray());

     gl.bindBuffer(parms1,parms2);

        parms1:

          gl.ARRAY_BUFFER ——包含顶点属性的缓冲区

          gl.ELEMENT_ARRAY_BUFFER——用于元素索引的缓冲区

        parms2:需要绑定的缓冲区对象

     gl.bufferData(parms1,parms2,parms3);

        params1:

          gl.ARRAY_BUFFER或gl.ELEMENT_ARRAY_BUFFER

        parms2:顶点数据

        parms3:绘制方式

          gl.STATIC_DRAW:内容应由应用程序指定一次,并多次用作WebGL绘图和图像规范命令的源。

          gl.STREAM_DRAW:内容应由应用程序指定一次,并且最多使用几次作为WebGL绘图和图像规范命令的源。

          gl.DYNAMIC_DRAW:内容旨在由应用程序重复指定,并多次用作WebGL绘图和图像规范命令的源。

     gl.vertexAttribPointer(parms1,parms2,parms3,parms4,parms5,parms6);

        params1:指定要修改的顶点属性的索引

        params2:指定每个顶点属性的组件数。必须是1,2,3或4

        params3:指定数组中每个组件的数据类型

      • gl.BYTE:带符号的8位整数,其值为[-128,127]
      • gl.SHORT:带符号的16位整数,其值为[-32768,32767]
      • gl.UNSIGNED_BYTE:无符号8位整数,值为[0,255]
      • gl.UNSIGNED_SHORT:无符号16位整数,值为[0,65535]
      • gl.FLOAT:32位IEEE浮点数

        params4:指定整数数据值是否应被归一化到一定的范围内被转换为一个浮点数时

        params5:指定连续顶点属性开头之间的偏移量

        params6:指定顶点属性数组中第一个组件的偏移量

    相关文章

    WebGL学习笔记一

  • 相关阅读:
    如何用SendInput模拟键盘的组合键使用?
    Js获取当前日期时间及其它操作
    如何动态修改窗口的Style
    js时间加减
    遍历子窗口
    使用SampleGrabber过滤器扑获图像
    js 字符串日期 yyyyMMdd 转化为 date
    ModifyStyle函数的用法
    有谁用过sendinput摸拟一个鼠标击键?
    在VC中如何才能得到当前屏幕的分辨率
  • 原文地址:https://www.cnblogs.com/baby123/p/11322978.html
Copyright © 2011-2022 走看看