WebGL 2D 圖像轉換

2018-10-03 11:21 更新

WebGL 2D 圖像轉換

在學習 3D 相關知識之前,請首先看看 2D 的知識。請保持耐心。這篇文章某些人看起來可能非常簡單,但是我們將要講解的知識是建立在前幾篇的文章的基礎之上。如果你沒有閱讀過,我建議你至少閱讀第一章之后再回到這里繼續(xù)學習。

Translation 指的是一些奇特的數(shù)學名稱,它的基本意思是“移動”某物。它同樣適用于將一個句子從英文“移動”成為日語這一說法,但是此處我們談論的是幾何中的移動。通過使用以 the first post 結尾的代碼,你可以僅僅通過修改 setRectangle 距離右邊的的值來使矩形移動。如下是一個基于我們初始示例的代碼:

  // First lets make some variables 
  // to hold the translation of the rectangle
  var translation = [0, 0];

  // then let's make a function to
  // re-draw everything. We can call this
  // function after we update the translation.

  // Draw a the scene.
  function drawScene() {
    // Clear the canvas.
    gl.clear(gl.COLOR_BUFFER_BIT);

    // Setup a rectangle
    setRectangle(gl, translation[0], translation[1], width, height);

    // Draw the rectangle.
    gl.drawArrays(gl.TRIANGLES, 0, 6);
  }

在上面的例子中,我在界面中放置了兩個可滑動欄,你可以通過滑動按鈕來修改 translation[0] 和 translation[1] 的值,而且在這個兩個值發(fā)生修改時調用 drawScene 函數(shù)對界面進行更新。拖動滑動條對矩陣進行移動。

到此處你已經覺得很不錯。然而,現(xiàn)在假設我們想要利用相同的操作,但是處理更復雜的圖形,那么該如何實現(xiàn)了。

假設我們想要畫一個包含 6 個三角形的 'F' 形狀,如下所示:

F

如下是我們將要使用的改變 setRectangle 值的代碼:

// Fill the buffer with the values that define a letter 'F'.
function setGeometry(gl, x, y) {
  var width = 100;
  var height = 150;
  var thickness = 30;
  gl.bufferData(
      gl.ARRAY_BUFFER,
      new Float32Array([
          // left column
          x, y,
          x + thickness, y,
          x, y + height,
          x, y + height,
          x + thickness, y,
          x + thickness, y + height,

          // top rung
          x + thickness, y,
          x + width, y,
          x + thickness, y + thickness,
          x + thickness, y + thickness,
          x + width, y,
          x + width, y + thickness,

          // middle rung
          x + thickness, y + thickness * 2,
          x + width * 2 / 3, y + thickness * 2,
          x + thickness, y + thickness * 3,
          x + thickness, y + thickness * 3,
          x + width * 2 / 3, y + thickness * 2,
          x + width * 2 / 3, y + thickness * 3]),
      gl.STATIC_DRAW);
}

你會發(fā)現(xiàn)畫出來的圖形伸縮比例不是很好。如果你想畫出有幾百或者幾千條線組成的幾何圖形,我們就需要編寫一些相當復雜的代碼。在上面的代碼中,每次用 JavaScript 就需要更新所有的點。

有一種更簡單的方式。僅僅只需要更新幾何圖形,接著修改渲染器部分。

如下是渲染器部分:

<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec2 a_position;

uniform vec2 u_resolution;
uniform vec2 u_translation;

void main() {
   // Add in the translation.
   vec2 position = a_position + u_translation;

   // convert the rectangle from pixels to 0.0 to 1.0
   vec2 zeroToOne = position / u_resolution;
   ...

接著我們將會稍微重構下代碼。我們僅僅需要設置幾何圖形一次。

// Fill the buffer with the values that define a letter 'F'.
function setGeometry(gl) {
  gl.bufferData(
      gl.ARRAY_BUFFER,
      new Float32Array([
          // left column
          0, 0,
          30, 0,
          0, 150,
          0, 150,
          30, 0,
          30, 150,

          // top rung
          30, 0,
          100, 0,
          30, 30,
          30, 30,
          100, 0,
          100, 30,

          // middle rung
          30, 60,
          67, 60,
          30, 90,
          30, 90,
          67, 60,
          67, 90]),
      gl.STATIC_DRAW);
}

在實現(xiàn)我們想要的移動之前需要更新下 u_translation 變量的值。

  ...
  var translationLocation = gl.getUniformLocation(
             program, "u_translation");
  ...
  // Set Geometry.
  setGeometry(gl);
  ..
  // Draw scene.
  function drawScene() {
    // Clear the canvas.
    gl.clear(gl.COLOR_BUFFER_BIT);

    // Set the translation.
    gl.uniform2fv(translationLocation, translation);

    // Draw the rectangle.
    gl.drawArrays(gl.TRIANGLES, 0, 18);
  }

注意 setGeometry 只是被調用一次。在 drawScene 中不需要。

如下是一個示例。同樣,你可以通過拖動滑動條來更新圖形的位置。

現(xiàn)在,當我們繪制 WebGL 圖像就包括要實現(xiàn)上面所有的事。我們所作的所有事指的是設置移動變量接著調用函數(shù)進行繪制。即使我們的幾何圖形包含成千上萬的點,main 代碼仍然是相同的。

以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號