<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      WebGL簡易教程(三):繪制一個三角形(緩沖區對象)

      1. 概述

      在上一篇教程《WebGL簡易教程(二):向著色器傳輸數據》中,通過向著色器(shader)傳輸數據,改變了繪制點的大小和顏色。之前的例子只能繪制一個點,如果需要繪制如三角形、矩形或者立方體等稍微復雜的圖形,需要怎么做呢?這個時候就需要一種很方便的機制——緩沖區對象(buffer object)。

      我們知道,OpenGL/WebGL進行圖形工作,需要訪問顯存的數據。而像C或者JS這樣的編程語言去申請數據,總是保存在內存中——也就是說,需要把內存中的數據傳輸到顯存,OpenGL/WebGL才能進行繪制。數據的申請、傳輸、釋放是一種IO操作,對IO操作而言,分段的、多次的讀寫操作的效率總是比不上一次總體的讀寫操作。緩沖區對象正是用來解決這兩個問題的:我們可以一次性向緩沖區對象填充大量的頂點數據,供頂點著色器使用。

      這里就通過繪制一個三角形的實例,來講解緩沖區對象的使用。一般來說,任何三維模型的基本單位就是三角形,會繪制三角形就能繪制任意復雜的圖形。

      2. 示例:繪制三角形

      同之前的例子一樣,繪制三角形的實例包含HTML和JavaScript兩個部分。

      1) HelloTriangle.html

      <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="utf-8" />
          <title>Hello Triangle</title>
        </head>
      
        <body onload="main()">
          <canvas id="webgl" width="400" height="400">
          Please use a browser that supports "canvas"
          </canvas>
      
          <script src="../lib/webgl-utils.js"></script>
          <script src="../lib/webgl-debug.js"></script>
          <script src="../lib/cuon-utils.js"></script>
          <script src="HelloTriangle.js"></script>
        </body>
      </html>
      

      這段HTML代碼與之前的例子相比幾乎沒有改動,引入了需要webgl組件和主要的繪制代碼HelloTriangle.js。沒有特別改動的話,以后的html代碼就不再介紹。

      2) HelloTriangle.js

      // 頂點著色器程序
      var VSHADER_SOURCE =
        'attribute vec4 a_Position;\n' + // attribute variable
        'void main() {\n' +
        '  gl_Position = a_Position;\n' + // Set the vertex coordinates of the point
        '}\n';
      
      // 片元著色器程序
      var FSHADER_SOURCE =
        'precision mediump float;\n' +
        'uniform vec4 u_FragColor;\n' +  // uniform変數
        'void main() {\n' +
        '  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +
        '}\n';
      
      function main() {
        // 獲取 <canvas> 元素
        var canvas = document.getElementById('webgl');
      
        // 獲取WebGL渲染上下文
        var gl = getWebGLContext(canvas);
        if (!gl) {
          console.log('Failed to get the rendering context for WebGL');
          return;
        }
      
        // 初始化著色器
        if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
          console.log('Failed to intialize shaders.');
          return;
        }
      
        // 設置頂點位置
        var n = initVertexBuffers(gl);
        if (n < 0) {
          console.log('Failed to set the positions of the vertices');
          return;
        } 
      
        // 指定清空<canvas>的顏色
        gl.clearColor(0.0, 0.0, 0.0, 1.0);
      
        // 清空<canvas>
        gl.clear(gl.COLOR_BUFFER_BIT);
      
        // 繪制三角形
        gl.drawArrays(gl.TRIANGLES, 0, 3);
      }
      
      function initVertexBuffers(gl) {
        var vertices = new Float32Array([
          0, 0.5,   -0.5, -0.5,   0.5, -0.5
        ]);
        var n = 3; // 點的個數
      
        // 創建緩沖區對象
        var vertexBuffer = gl.createBuffer();
        if (!vertexBuffer) {
          console.log('Failed to create the buffer object');
          return -1;
        }
      
        // 將緩沖區對象綁定到目標
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
        // 向緩沖區對象寫入數據
        gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
      
        var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
        if (a_Position < 0) {
          console.log('Failed to get the storage location of a_Position');
          return -1;
        }
        // 將緩沖區對象分配給a_Position變量
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
      
        // 連接a_Position變量與分配給它的緩沖區對象
        gl.enableVertexAttribArray(a_Position);
      
        return n;
      }
      

      與之前的繪制JS代碼相比,著色器等大部分內容都沒有變化,最主要的變化是不再通過 gl.vertexAttrib3f()函數向著色器傳遞數據,取而代之的是自定義了一個初始化頂點位置函數initVertexBuffers()。在這個函數中,正是通過緩沖區對象向著色器傳遞數據的。

      3) 緩沖區對象

      在函數initVertexBuffers()中,可以看到首先初始化了一個JavaScript數組(Float32Array是WebGL引入的特殊的類型化數組,能夠保存大量同一種類型的元素),它就是緩沖區需要寫入的數據:

      var vertices = new Float32Array([
          0, 0.5,   -0.5, -0.5,   0.5, -0.5
        ]);
      

      這個數據通過緩沖區對象傳入頂點著色器,需要如下五個步驟:

      (1) 創建緩沖區對象(gl.createBuffer())

        // 創建緩沖區對象
        var vertexBuffer = gl.createBuffer();
        if (!vertexBuffer) {
          console.log('Failed to create the buffer object');
          return -1;
        }
      

      WebGL通過gl.createBuffer()來創建緩沖區對象,它告訴WebGL系統,開辟顯存空間接受內存傳輸過來的數據。其函數的具體說明如下:
      1.創建緩沖區對象

      (2) 綁定緩沖區對象(gl.bindBuffer())

        // 將緩沖區對象綁定到目標
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
      

      由于緩沖區對象可能有多種用途,創建緩沖區之后還需要將其綁定到不同目標上,參數gl.ARRAY_BUFFER表示緩沖區對象存儲的是關于頂點的數據。其綁定函數gl.bindBuffer()的具體說明如下:
      2.綁定緩沖區對象

      (3) 將數據寫入緩沖區對象(gl.bufferData())

        // 向緩沖區對象寫入數據
        gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
      

      這段代碼的意思是將數組vertices中的數據傳輸到目標gl.ARRAY_BUFFER上的緩沖區對象。其函數的具體說明如下:
      3.將數據寫入緩沖區對象

      (4) 將緩沖區對象分配給attribute變量(gl.vertexAttribPointer())

        var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
        if (a_Position < 0) {
          console.log('Failed to get the storage location of a_Position');
          return -1;
        }
        // 將緩沖區對象分配給a_Position變量
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
      

      正如《WebGL簡易教程(二):向著色器傳輸數據》介紹的,通過函數getAttribLocation()獲取頂點著色器的attribute變量a_Position的地址。不同的是,這里用過函數gl.vertexAttribPointer(),將整個緩沖區對象,也就是頂點數據,一次性分配給attribute變量a_Position。其函數的具體說明如下:
      4.將緩沖區對象分配給attribute變量

      (5) 開啟attribute變量(gl.enableVertexAttribArray())

        // 連接a_Position變量與分配給它的緩沖區對象
        gl.enableVertexAttribArray(a_Position);
      

      最后一步就非常簡單了,開啟attribute變量,建立緩沖區與attribute變量的連接。其函數說明如下:
      5.開啟attribute變量

      通過以上五個步驟,著色器就可以根據緩沖區對象的數據進行正確的繪制了。其示意圖如下:
      6.使用緩沖區對象傳輸頂點

      4) 基本圖形繪制

      與前兩篇教程中繪制點不同,這里繪制的是一個三角形:

        // 繪制三角形
        gl.drawArrays(gl.TRIANGLES, 0, 3);
      

      可以看到這里同樣是用的函數gl.drawArrays()進行繪制的,其具體的函數說明如下:
      7.drawArrays()
      第二個參數和第三個參數非常簡單,表示從哪個頂點數據繪制到哪個頂點數據。例如這里繪制三角形表示從第1個點繪制到第3個點。
      第一個參數則非常強大,表示可以繪制的7種基本圖形:
      8
      9
      基本示意圖如下:

      3. 結果

      用瀏覽器打開HelloTriangle.html,可以看到繪制了一個紅色的三角形,顯示效果如下所示:

      4. 參考

      本來部分代碼和插圖來自《WebGL編程指南》。

      代碼和數據地址

      上一篇
      目錄
      下一篇

      posted @ 2019-09-04 11:09  charlee44  閱讀(2851)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 欧洲美熟女乱又伦AV影片| 亚洲全网成人资源在线观看| 丁香五月亚洲综合在线国内自拍 | 极品少妇无套内射视频| 亚洲中文字幕人妻系列| 亚洲人成网站在线观看播放不卡| 国产果冻豆传媒麻婆精东| 久久综合老鸭窝色综合久久| 国产成人一区二区三区在线| 北岛玲中文字幕人妻系列| 国产一区二区精品偷系列| 九九re线精品视频在线观看视频| 99在线精品国自产拍中文字幕| 免费人成年激情视频在线观看| 加勒比精品一区二区三区| 国产亚洲精品AA片在线爽| 农村肥熟女一区二区三区| 大地资源中文在线观看西瓜| 国产99在线 | 免费| 国产台湾黄色av一区二区| 狠狠色综合久久丁香婷婷| 久久av无码精品人妻出轨| 国产激情福利短视频在线| 国产女人和拘做受视频免费| 在线综合亚洲欧洲综合网站| 和艳妇在厨房好爽在线观看| 亚洲国产精品无码av| 国内自产少妇自拍区免费| 国产国产午夜福利视频| 92成人午夜福利一区二区| 99精品久久毛片a片| 97欧美精品系列一区二区| 中文字幕国产精品资源| 最近中文字幕完整版hd| 国产萌白酱喷水视频在线观看 | 久久成人影院精品777| 国产成人精品亚洲精品密奴| 4hu44四虎www在线影院麻豆| 色婷婷综合久久久久中文一区二区 | 2019国产精品青青草原| 湖州市|