自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

WebGL初探

開發(fā) 前端
目前,我們有很多方案可以快速的接觸到 WebGL 并繪制復(fù)雜的圖形,但最后發(fā)現(xiàn)我們忽視了很多細(xì)節(jié)性的東西。當(dāng)然,這對(duì)初學(xué) WebGL 是有必要的,它能迅速提起我們對(duì) WebGL 的學(xué)習(xí)興趣。當(dāng)學(xué)習(xí)到更加深入的階段時(shí),我們更想了解 WebGL 的工作機(jī)制,這也將對(duì)我們編程有極大的幫助。

目前,我們有很多方案可以快速的接觸到 WebGL 并繪制復(fù)雜的圖形,但***發(fā)現(xiàn)我們忽視了很多細(xì)節(jié)性的東西。當(dāng)然,這對(duì)初學(xué) WebGL 是有必要的,它能迅速提起我們對(duì) WebGL 的學(xué)習(xí)興趣。當(dāng)學(xué)習(xí)到更加深入的階段時(shí),我們更想了解 WebGL 的工作機(jī)制,這也將對(duì)我們編程有極大的幫助。以上也是我想寫這樣一個(gè)系列的原因。

簡介

用更專業(yè)的描述講,WebGL (Web Graphics Library) 是一個(gè)用以渲染交互式 3D 和 2D 圖形的無需插件且兼容下一代瀏覽器的 JavaScript API,通過 HTML5 中 <canvas> 元素實(shí)現(xiàn)功能。WebGL 是由 Khronos Group 集團(tuán)制定,而非 W3C 組織。目前,我們可以使用的是 WebGL ***個(gè)版本,它繼承自 OpenGL ES 2.0 。而 OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL 三維圖形 API 的子集,針對(duì)手機(jī)、PDA 和游戲主機(jī)等嵌入式設(shè)備而設(shè)計(jì)。以下是各版本之間的關(guān)系圖:

Hello World

首先,我們將通過實(shí)現(xiàn)一個(gè)簡單的 WebGL 程序(清空繪圖區(qū))叩開 WebGL 的大門。下面將實(shí)現(xiàn)一個(gè)最簡單的 WebGL 功能:

 

創(chuàng)建 canvas 元素

WebGL 采用 HTML5 中的 <canvas> 元素。為了使用 WebGL 進(jìn)行 3D 渲染,你首先需要一個(gè) canvas 元素。這里創(chuàng)建了一個(gè) canvas 元素,并使用 onload 事件創(chuàng)建來初始化 WebGL 上下文。

  1. <body onload="start()"
  2.   <canvas id="glcanvas" width="640" height="480"
  3.     Your browser doesn't appear to support the HTML5 <code>&lt;canvas&gt;</code> element. 
  4.   </canvas> 
  5. </body> 

獲取 WebGL 上下文

目前,各瀏覽器基本都實(shí)現(xiàn)了對(duì) WebGL 的支持,但 IE11 及 Edge 瀏覽器稍微有些不同。以下是對(duì)初始化 WebGL 的基本封裝:

  1. function initWebGL(canvas) { 
  2.   // 創(chuàng)建全局變量 
  3.   window.gl = null
  4.    
  5.   try { 
  6.     // 嘗試獲取標(biāo)準(zhǔn)上下文,如果失敗,回退到試驗(yàn)性上下文 
  7.     gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); 
  8.   } 
  9.   catch(e) { 
  10.     throw '創(chuàng)建失敗。'
  11.   } 
  12.    
  13.   // 如果沒有GL上下文,馬上放棄 
  14.   if (!gl) { 
  15.     alert("WebGL初始化失敗,可能是因?yàn)槟臑g覽器不支持。"); 
  16.     gl = null
  17.   } 
  18.   return gl; 
  19. }     

這里通過采用 canvas 的 getContext(contextType, contextAttributes) 方法判斷瀏覽器是否支持 WebGL,并創(chuàng)建其上下文。當(dāng)返回值是 canvas 的上下文時(shí),瀏覽器可支持 WebGL,為 null 時(shí),則創(chuàng)建失敗。注意,在 IE11 及 Edge 瀏覽器下,需要使用 "experimental-webgl" 創(chuàng)建 WebGL,此處做了兼容處理。

清空繪圖區(qū)

下面將背景顏色設(shè)置為黑色,并清空緩存區(qū)。

  1. var gl; // WebGL的全局變量 
  2.  
  3. function start() { 
  4.   var canvas = document.getElementById("glcanvas"); 
  5.  
  6.   // 初始化 WebGL 上下文 
  7.   gl = initWebGL(canvas);    
  8.    
  9.   // 只有在 WebGL 可用的時(shí)候才繼續(xù) 
  10.    
  11.   if (gl) { 
  12.     // 設(shè)置清除顏色為黑色,不透明 
  13.     gl.clearColor(0.0, 0.0, 0.0, 1.0);      
  14.     // 清除顏色和深度緩存 
  15.     gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);      
  16.   } 
  17.  

這樣,我們可以在瀏覽器中看到一塊黑色區(qū)域。你可能已經(jīng)注意到,WebGL 遵循的是傳統(tǒng) OpenGL 顏色分量的取值范圍,從 0.0 到 1.0。RGB 的值越高,顏色越亮。注意,clear() 方法在這里清除顏色和深度緩存,而不是繪制區(qū)域的 <canvas>,該方法繼承自 OpenGL(基于多緩存模型)。實(shí)際還有模版緩存,但實(shí)際很少會(huì)被用到。

更進(jìn)一步

上面我們完成了***個(gè) WebGL 程序,但是我們還未接觸到 WebGL 的核心:可編程著色器。接下來,我們將使用可編程著色器在屏幕上繪制點(diǎn)。可編程著色器是一個(gè)較為復(fù)雜的概念,也有自己的編程語言 GLSL,后面將會(huì)又專門的文章具體講解可編程著色器。這里我們只需要簡單了解繪制的流程:

編寫著色器程序

  1. // 頂點(diǎn)著色器程序 
  2. var VSHADER_SOURCE =  
  3.   'void main() {\n' + 
  4.   '  gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n' + // 設(shè)置頂點(diǎn)位置 
  5.   '  gl_PointSize = 10.0;\n' +                    // 設(shè)置點(diǎn)的大小 
  6.   '}\n'
  7.  
  8. // 片元著色器程序 
  9. var FSHADER_SOURCE = 
  10.   'void main() {\n' + 
  11.   '  gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n' + // 設(shè)置點(diǎn)的顏色,此處為白色 
  12.   '}\n' 

上面程序是不是有中似曾相識(shí)的感覺?沒錯(cuò),GLSL 語言和 C 語言很類似。著色器程序中包含一個(gè)主函數(shù),且返回值為空。其中vec4() 構(gòu)造函數(shù)用于生成一個(gè)四維向量(x,y,z,w)。

編譯著色器

首先,需要用 createShader( type ) 方法生成相應(yīng)類型的 WebGLShader。接著,使用 shaderSource( shader, sourceCode ) 作為 GLSL 源碼的鉤子函數(shù)。***使用 compileShader( shader ) 完成對(duì)著色器的編譯。程序中我們做了編譯后的校驗(yàn),當(dāng)著色器編譯失敗時(shí),會(huì)報(bào)出失敗并刪除著色器。

  1. function createShader (gl, type, sourceCode) { 
  2.   // 編譯著色器類型:頂點(diǎn)著色器及片元著色器。 
  3.   var shader = gl.createShader( type ); 
  4.   gl.shaderSource( shader, sourceCode ); 
  5.   gl.compileShader( shader ); 
  6.  
  7.   if ( !gl.getShaderParameter(shader, gl.COMPILE_STATUS) ) { 
  8.     var info = gl.getShaderInfoLog( shader ); 
  9.     console.log( "無法編譯 WebGL 程序。 \n\n" + info); 
  10.     gl.deleteShader(shader); 
  11.     return null
  12.   } 
  13.  
  14.   return shader; 
  15.  

連接到可用程序

此時(shí),著色器仍是不可用的,需要將其賦值到 WebGLProgram 上。這里主要進(jìn)行了三步操作,首先,需要使用 createProgram() 方法創(chuàng)建和初始化一個(gè) WebGLProgram 對(duì)象。接著,使用 gl.attachShader(program, shader) 將該對(duì)象結(jié)合兩個(gè)已經(jīng)編譯的著色器。***,使用 linkProgram(program) 將 WebGLProgram 和著色器連接。

  1. function createProgram(gl, vshader, fshader) { 
  2.   // 創(chuàng)建著色器對(duì)象 
  3.   var vertexShader = createShader(gl, gl.VERTEX_SHADER, vshader); 
  4.   var fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fshader); 
  5.   if (!vertexShader || !fragmentShader) { 
  6.     return null
  7.   } 
  8.  
  9.   // 創(chuàng)建編程對(duì)象 
  10.   var program = gl.createProgram(); 
  11.   if (!program) { 
  12.     return null
  13.   } 
  14.  
  15.   // 賦值已創(chuàng)建的著色器對(duì)象 
  16.   gl.attachShader(program, vertexShader); 
  17.   gl.attachShader(program, fragmentShader); 
  18.  
  19.   // 連接編程對(duì)象 
  20.   gl.linkProgram(program); 
  21.  
  22.   // 檢查鏈接結(jié)果 
  23.   var linked = gl.getProgramParameter(program, gl.LINK_STATUS); 
  24.   if (!linked) { 
  25.     var error = gl.getProgramInfoLog(program); 
  26.     console.log('鏈接程序失?。? + error); 
  27.     gl.deleteProgram(program); 
  28.     gl.deleteShader(fragmentShader); 
  29.     gl.deleteShader(vertexShader); 
  30.     return null
  31.   } 
  32.   return program; 
  33.  

使用可用著色器程序

這一步主要使用 useProgram(program) 方法告訴 GPU 使用程序。

  1. function initShaders(gl, vshader, fshader) { 
  2.   var program = createProgram(gl, vshader, fshader); 
  3.   if (!program) { 
  4.     console.log('創(chuàng)建程序失敗。'); 
  5.     return false
  6.   } 
  7.  
  8.   gl.useProgram(program); 
  9.   gl.program = program; 
  10.  
  11.   return true
  12.  

繪制一個(gè)點(diǎn)

***,使用 drawArrays(mode, first, count) 繪制一個(gè)點(diǎn),該函數(shù)是一個(gè)非常強(qiáng)大的渲染函數(shù),后續(xù)文章會(huì)有詳細(xì)介紹。此處只需要知道傳入 "POINTS" 繪制了一個(gè)點(diǎn)。

  1. // 繪制一個(gè)點(diǎn) 
  2. gl.drawArrays(gl.POINTS, 0, 1);    

至此,我們已經(jīng)完成了繪制一個(gè)點(diǎn)的全部程序。當(dāng)運(yùn)行以上程序時(shí),我們會(huì)在瀏覽器中看到一個(gè)白色的點(diǎn)。

結(jié)束語

到現(xiàn)在,我們雖然還沒有使用 WebGL 繪制三維圖形,但我們已經(jīng)進(jìn)入了 WebGL 世界。我們已經(jīng)使用 WebGL 繪制了簡單的圖形。但是這只是 WebGL 的繪制的冰山一角,我們使用 WebGL 當(dāng)然不是為了繪制這樣一個(gè)簡單的圖形。為了繪制更復(fù)雜的圖形,我們還有很多的細(xì)節(jié)需要去了解。但是無論如何,我們都已經(jīng)開啟了 WebGL 的***步,其實(shí)問題也并沒有我們想象的那么難。

責(zé)任編輯:龐桂玉 來源: segmentfault
相關(guān)推薦

2010-06-03 12:57:06

Hadoop

2009-06-24 13:22:27

Glassfish

2017-04-06 15:10:08

WebGLJavascriptWeb

2011-05-17 14:11:06

Dijkstra

2011-04-18 09:53:08

Ruby

2015-01-21 16:35:49

Apple WatchWatchKit

2014-11-20 15:44:40

Apple Watch

2012-02-29 15:03:30

2017-12-26 17:42:12

前端WebGLThree.js

2023-03-16 14:33:23

WebGL初始化繪制

2012-07-09 10:22:28

Mono for An

2011-08-24 09:30:29

JavaJVM

2021-04-14 09:33:58

Kubernetes通信網(wǎng)絡(luò)模型

2013-04-10 11:23:27

2012-04-05 13:50:38

Java

2010-09-08 17:26:46

JavaScript

2011-06-16 10:25:29

AndroidAIR

2017-05-29 08:18:11

Serverless架構(gòu)軟件系統(tǒng)

2013-09-09 09:41:34

2011-09-14 14:15:25

IBMAIX 7操作系統(tǒng)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)