最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 手摸手带你用webgl原生绘制一个矩形

    正文概述 掘金(哦嗬)   2021-04-14   525

    webgl和threejs

    WebGL是一种3D绘图标准,这种绘图技术标准允许把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的一个JavaScript绑定,WebGL可以为HTML5 Canvas提供硬件3D加速渲染,这样Web开发人员就可以借助系统显卡来在浏览器里更流畅地展示3D场景和模型了,还能创建复杂的导航和数据视觉化。

    Three.js是一款开源的主流3D绘图JS引擎(名字Three就是3D的含义), threejs对webgl进行了封装 , 让我们更容易的创建3D应用 . 框架内置了很多现成工具 , 比如模型加载器 , 支持obj , fbx , 等通用模型格式 . 还提供了鼠标控制如缩放 , 放大等等 .

    使用threejs虽然能快速创建3D应用 , 但是对理解底层的webgl代码没有了解 . 更别谈webgl的爸爸OpenGL了 .

    下面我将用webgl绘制一个矩形

    最终效果

    手摸手带你用webgl原生绘制一个矩形

    创建一个canvas

    <canvas id="box" width=300 height=300></canvas>
    
    
    // 获取canvas的dom对象
    const canvas = document.getElementById('box')
    
    // 获取绘制webgl的上下文, 之后我们就可以使用webgl这个对象来创建3d应用
    const webgl = canvas.getContext('webgl')
    
    准备要绘制的矩形的坐标
    //  v1--------v0
    //  |         |
    //  |         | 
    //  |         |
    //  v2--------v3
    // 改正方形由4个点组成
    let jsArrayData = new Float32Array([
      // x   y    z         
      -0.5, +0.5, 0.0,  // v1
      +0.5, +0.5, 0.0,  // v0
      +0.5, -0.5, 0.0,  // v3
      -0.5, -0.5, 0.0,  // v2
    ])
    
    // 通过绘制两个三角形来组成一个正方形, 下面的数组里的数字表示jsArrayData里的索引,
    // 如: 0表示-0.5, 2表示0.0
    // 0, 1, 2表示用这三个点绘制一个三角形    
    let indexDatas = [      
        0, 1, 2,      
        0, 2, 3    
    ]
    

    将正方形的顶点和三角形的顶点索引绑定到webgl中

    // 创建顶点缓冲区
    triangleBuffer = webgl.createBuffer()
    // 指明缓冲区的类型
    // webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer)
    // // 分配内存
    // webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayData), webgl.STATIC_DRAW)
    webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer)
    // 分配内存
    webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayData), webgl.STATIC_DRAW)
    
    // 创建索引缓冲区
    indexBuffer = webgl.createBuffer()
    // 指明缓冲区的类型
    webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER, indexBuffer)
    // 分配内存
    webgl.bufferData(webgl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexDatas), webgl.STATIC_DRAW)
    // 使用缓冲区, 指定绘制所用的顶点数据, 从该缓冲区中获取
    webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER, indexBuffer)
    
    

    将顶点数据传到shader中

    // 将v3PositionIndex变量绑定到顶点shader里的v3Position    
    webgl.bindAttribLocation(programObject, v3PositionIndex, 'v3Position')
        
    // 启用v3PositionIndex
    webgl.enableVertexAttribArray(v3PositionIndex)    
    //  3表示每个顶点有三个数据(x, y, z)
    // 4 * 3 表示所有顶点在内存中占用的字节数, 4表示一个顶点占用的字节数, 3表示一个顶点有3个数据
    // 0 表示取数据的时候从第0个元素开始    
    webgl.vertexAttribPointer(v3PositionIndex, 3, webgl.FLOAT, false, 4 * 3, 0)
    
    

    绑定顶点着色器和片元着色器

    // 创建shader
    vertexShaderObject = webgl.createShader(webgl.VERTEX_SHADER)
    fragmentShaderObject = webgl.createShader(webgl.FRAGMENT_SHADER)
    
    webgl.shaderSource(vertexShaderObject, `
      attribute vec3 v3Position;
      void main(void)
      {
        gl_Position = vec4(v3Position, 1.0);
      }
    `)
    
    webgl.shaderSource(fragmentShaderObject, `
      precision  lowp  float;
      void main(void)
      {
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
      }
    `)
    
    // 编译shader
    webgl.compileShader(vertexShaderObject)
    webgl.compileShader(fragmentShaderObject) 
    

    绑定着色器和顶点数据到webgl

    // 创建一段空程序    
    programObject = webgl.createProgram()    
    // 绑定顶点着色器和片元着色器    
    webgl.attachShader(programObject, vertexShaderObject)    
    webgl.attachShader(programObject, fragmentShaderObject)    
    // 将v3PositionIndex变量绑定到顶点shader里的v3Position    
    webgl.bindAttribLocation(programObject, v3PositionIndex, 'v3Position')    
    // 执行连接, 此段程序不再是空    
    webgl.linkProgram(programObject)    
    // 使用这段程序    
    webgl.useProgram(programObject)
    

    执行绘制

    // 设置重绘背景的颜色    
    webgl.clearColor(0.0, 0.0, 0.0, 1.0)
    // 清空背景    
    webgl.clear(webgl.COLOR_BUFFER_BIT)    
    // 两个面的索引总共有6个数据    
    webgl.drawElements(webgl.TRIANGLES, 6, webgl.UNSIGNED_SHORT, 0)
    

    总代码

    
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>WebGL</title>
    </head>
    
    <body>
    
      <canvas id="box" style="border: 1px solid black;" width=300 height=300></canvas>
    
      <script>
        let vertexShaderObject = null
        let fragmentShaderObject = null
        let programObject = null
        let indexBuffer = null
        let v3PositionIndex = 0
        let uniformColor
    
        // 1 创建上下文
        const canvas = document.getElementById('box')
        const webgl = canvas.getContext('webgl')
    
        webgl.viewport(0, 0, canvas.clientWidth, canvas.clientHeight)
    
        // 2 创建shader
        vertexShaderObject = webgl.createShader(webgl.VERTEX_SHADER)
        fragmentShaderObject = webgl.createShader(webgl.FRAGMENT_SHADER)
    
        webgl.shaderSource(vertexShaderObject, `
          attribute vec3 v3Position;
          void main(void)
          {
            gl_Position = vec4(v3Position, 1.0);
          }
        `)
    
        webgl.shaderSource(fragmentShaderObject, `
          precision  lowp  float;
          void main(void)
          {
            gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
          }
        `)
    
        // 3 编译shader
        webgl.compileShader(vertexShaderObject)
        webgl.compileShader(fragmentShaderObject)
    
        if (!webgl.getShaderParameter(vertexShaderObject, webgl.COMPILE_STATUS)) {
          console.log('err---vertexShaderObject', webgl.getShaderInfoLog(vertexShaderObject))
        }
    
        if (!webgl.getShaderParameter(fragmentShaderObject, webgl.COMPILE_STATUS)) {
          console.log('err---fragmentShaderObject', webgl.getShaderInfoLog(fragmentShaderObject))
        }
    
    
        // 创建一段空程序
        programObject = webgl.createProgram()
    
        // 绑定顶点着色器和片元着色器
        webgl.attachShader(programObject, vertexShaderObject)
        webgl.attachShader(programObject, fragmentShaderObject)
    
        // 将v3PositionIndex变量绑定到顶点shader里的v3Position
        webgl.bindAttribLocation(programObject, v3PositionIndex, 'v3Position')
    
        // 执行连接, 此段程序不再是空
        webgl.linkProgram(programObject)
    
        // 使用这段程序
        webgl.useProgram(programObject)
    
    
        //  v1--------v0
        //  |         |
        //  |         | 
        //  |         |
        //  v2--------v3
    
        let jsArrayData = new Float32Array([
          // x   y    z         
          -0.5, +0.5, 0.0,  // v1
          +0.5, +0.5, 0.0,  // v0
          +0.5, -0.5, 0.0,  // v3
          -0.5, -0.5, 0.0,  // v2
        ])
    
        let indexDatas = [
          0, 1, 2,
          0, 2, 3
        ]
    
        // 创建顶点缓冲区
    
        triangleBuffer = webgl.createBuffer()
        // 指明缓冲区的类型
        // webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer)
        // // 分配内存
        // webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayData), webgl.STATIC_DRAW)
        webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer)
        // 分配内存
        webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayData), webgl.STATIC_DRAW)
    
    
    
        // 创建索引缓冲区
        indexBuffer = webgl.createBuffer()
        // 指明缓冲区的类型
        webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER, indexBuffer)
        // 分配内存
        webgl.bufferData(webgl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexDatas), webgl.STATIC_DRAW)
        // 使用缓冲区, 指定绘制所用的顶点数据, 从该缓冲区中获取
        webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER, indexBuffer)
    
    
    
        webgl.enableVertexAttribArray(v3PositionIndex)
    
        // 指定绘制顶点的数据
        // v3PositionIndex 绑定shader里的v3Position
        // 3 每个顶点有3个数据组成, 每取一个顶点都会往后偏移3个
        // 4*3  4是一个float占的字节数, 6是指每个顶点有6个数据, 表示每隔24个字节到下一个顶点
        // 0 从缓冲区的第0个开始往后取
        webgl.vertexAttribPointer(v3PositionIndex, 3, webgl.FLOAT, false, 4 * 3, 0)
    
        // 设置重绘背景的颜色
        webgl.clearColor(0.0, 0.0, 0.0, 1.0)
        // 执行绘制
        webgl.clear(webgl.COLOR_BUFFER_BIT)
    
        // 两个面的索引总共有6个数据
        webgl.drawElements(webgl.TRIANGLES, 6, webgl.UNSIGNED_SHORT, 0)
    
      </script>
    
    </body>
    
    </html>
    
    

    分享我私藏的TS教程,从0到高阶全系列,点击链接,0元获取 www.yidengxuetang.com/pub-page/in…


    起源地下载网 » 手摸手带你用webgl原生绘制一个矩形

    常见问题FAQ

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

    发表评论

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

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

    联系作者

    请选择支付方式

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