初涉WebGL

以前一直在搗鼓Vue和React棧,對組件化架構項目有了些理解和體會。今天嚐嚐WebGL,固然,並不打算如今深刻,只是略做了解,我知道這個坑很深。css

js的圖形庫、3d庫也有好幾款比較流行的,如遊戲開發方面的three.js、數據可視化的圖表庫echarts.js、GIS方面的百度地圖、google地圖等,最近打算學習下。html

言歸正傳,之前學canvas的時候,只是簡單地學習2d context的一些api寫寫畫畫,webGL顯然更高級些,在MDN文檔的介紹中:web

WebGL enables web content to use an API based on OpenGL ES 2.0 to perform 3D rendering in an HTML <canvas> in browsers that support it without the use of plug-ins. WebGL programs consist of control code written in JavaScript and special effects code(shader code) that is executed on a computer's Graphics Processing Unit (GPU). WebGL elements can be mixed with other HTML elements and composited with other parts of the page or page background.編程

提到了WebGL可讓網頁內容中的canvas元素實現3d渲染,其編程由兩部分組成,一部分是由js寫的控制代碼,一部分是在用戶設備gpu上執行的實現特定效果的代碼(GLSL,注意,GLSL是一門針對GPU的編程語言)。不過WebGL只兼容IE11+canvas

教程假設咱們會一些基本的3d圖像的概念。Learn WebGL for 2D and 3D graphics這篇入門教程指出,須要咱們會一點html和css知識,以及較深的js功底,能理解閉包、原型鏈、構造函數等概念。api

 

 

第一步,檢測設備是否支持WebGL:閉包

  function detectWebGLContext () {
    // Create canvas element. The canvas is not added to the
    // document itself, so it is never displayed in the
    // browser window.
    var canvas = document.createElement("canvas");
    // Get WebGLRenderingContext from canvas element.
    var gl = canvas.getContext("webgl")
      || canvas.getContext("experimental-webgl");
    // Report the result.
    if (gl && gl instanceof WebGLRenderingContext) {
      paragraph.innerHTML =
        "Congratulations! Your browser supports WebGL.";
    } else {
      paragraph.innerHTML = "Failed to get WebGL context. "
        + "Your browser or device may not support WebGL.";
    }
  }
View Code

跟通常的功能檢測同樣,其實就是判斷  gl = canvas.getContext("webgl")|| canvas.getContext("experimental-webgl")  是否是 WebGLRenderingContext 的一個實例。一旦咱們的canvas元素有這個rendering context,咱們就可使用它的api進行渲染。架構

 

第二步,開始簡單的exampleecharts

 

-----填充WebGLContextdom

1.獲取(set up)rendering context ,就是上一步的gl。

2.而後drawing buffer(如今先理解爲畫布)填充顏色。這個過程分兩步:

  //肯定渲染的範圍
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
  //設定WebGL的內部狀態--設定顏色
  // Set the clear color to darkish green.
  gl.clearColor(0.0, 0.5, 0.0, 1.0);
  //輸出其狀態--填充顏色
  // Clear the context with the newly set color. This is
  // the function call that actually does the drawing.
  gl.clear(gl.COLOR_BUFFER_BIT);
View Code

 gl.viewport()中前兩個參數是相對於左下角的距離。後兩個是寬,高。

在定義了drawing buffer的 範圍後,咱們執行了兩個動做,先是設定WebGL的內部狀態(顏色爲綠色),而後執行語句讓drawing buffer 變成WebGL內部狀態所設定的樣子。因此,WebGL其實是一個狀態機。咱們能夠回想下,在getContext(「2d」)的時候,要畫一個矩形,咱們也是遵循一樣的操做步驟:

//定義樣式(即內部狀態)
cxt.fillStyle="#FF0000";
//輸出圖形(將樣式狀態輸出到畫布中)
cxt.fillRect(0,0,150,75);

最後,WebGL中顏色定義都是使用RGBA格式的。

 

-----開始將WebGL和用戶交互結合

Clearing by clicking一例由上面的簡單例子延伸而來,對canvas和button綁定了click事件,觸發switchColor函數。

該函數先判斷是否支持WebGL,再肯定畫布的範圍,以後再執行三行代碼:

    //產生隨機顏色
    // Get a random color value using a helper function.
    var color = getRandomColor();
    //設置WebGL內部狀態的顏色新值
    // Set the clear color to the random color.
    gl.clearColor(color[0], color[1], color[2], 1.0);
    //將新值輸出到畫布
    // Clear the context with the newly set color. This is
    // the function call that actually does the drawing.
    gl.clear(gl.COLOR_BUFFER_BIT);
View Code

----裁剪:

  //開啓裁剪功能
  // Enable scissoring operation and define the position and
  // size of the scissoring area.
  gl.enable(gl.SCISSOR_TEST);
  //設定可更新的區域
  gl.scissor(60, 60, 60, 130);

  // Clear the drawing buffer solid yellow.
  gl.clearColor(1.0, 0.6, 0.0, .1);
  gl.clear(gl.COLOR_BUFFER_BIT);
View Code

getContext("2d")中也有類似的api。只有在指定的區域中畫布纔會被更新(顯示)。

----不設置高寬會致使不符合預期的渲染結果

咱們知道設置css能夠改變元素的視覺高寬,canvas也同樣。但若是咱們只是單純設置了css樣式,不對其dom節點設置高寬,將致使詭異的渲染效果。

其實不止「webgl」的RenderingConext,「2d」的context也會有這種狀況。

之前研究過canvas這個問題,由於css只是改變canvas元素呈如今頁面上的視覺大小,可是其邏輯像素默認是300*150.

當咱們調用api時,往api中傳入表示高寬或x、y軸位置的參數時,一旦超出y軸方向的150和x軸方向的300,就會超出畫布。

因此必要的時候,咱們得獲取canvas節點,而後js設定其邏輯高寬。canvas.height=xx;canvas.width=xx;

 

----封裝WebGL 方法

function getRenderingContext() {
  var canvas = document.querySelector("canvas");
  canvas.width = canvas.clientWidth;
  canvas.height = canvas.clientHeight;
  var gl = canvas.getContext("webgl")
    || canvas.getContext("experimental-webgl");
  if (!gl) {
    var paragraph = document.querySelector("p");
    paragraph.innerHTML = "Failed to get WebGL context."
      + "Your browser or device may not support WebGL.";
    return null;
  }
  gl.viewport(0, 0,
    gl.drawingBufferWidth, gl.drawingBufferHeight);
  gl.clearColor(0.0, 0.0, 0.0, 1.0);
  gl.clear(gl.COLOR_BUFFER_BIT);
  return gl;
}
View Code

這一節沒什麼新內容,只是把幾個基本的語句進行封裝。函數作了兩件事情,判斷是否支持webgl,而後將畫布填充成黑色並返回RenderingContext這個接口。

 //往後補充

相關文章
相關標籤/搜索