鍍金池/ 教程/ HTML/ WebGL 2D 圖像轉(zhuǎn)換
WebGL 文本 HTML
WebGL 文本 Canvas 2D
WebGL 2D 圖像旋轉(zhuǎn)
WebGL 圖像處理(續(xù))
WebGL 2D 矩陣
WebGL 繪制多個(gè)東西
WebGL 圖像處理
WebGL 2D 圖像轉(zhuǎn)換
WebGL 3D 透視
WebGL 是如何工作的
WebGL 文本 紋理
WebGL 2D 圖像伸縮
WebGL 場景圖
WebGL 3D 攝像機(jī)
WebGL 文本 使用字符紋理
WebGL 正交 3D
WebGL 基本原理
WebGL - 更少的代碼,更多的樂趣
WebGL 著色器和 GLSL

WebGL 2D 圖像轉(zhuǎn)換

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

Translation 指的是一些奇特的數(shù)學(xué)名稱,它的基本意思是“移動(dòng)”某物。它同樣適用于將一個(gè)句子從英文“移動(dòng)”成為日語這一說法,但是此處我們談?wù)摰氖菐缀沃械囊苿?dòng)。通過使用以 the first post 結(jié)尾的代碼,你可以僅僅通過修改 setRectangle 距離右邊的的值來使矩形移動(dòng)。如下是一個(gè)基于我們初始示例的代碼:

  // 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);
  }

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

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

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

http://wiki.jikexueyuan.com/project/webgl/images/webgl-2d-translation-F.png" alt="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);
}

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

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

如下是渲染器部分:

<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;
   ...

接著我們將會(huì)稍微重構(gòu)下代碼。我們僅僅需要設(shè)置幾何圖形一次。

// 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);
}

在實(shí)現(xiàn)我們想要的移動(dòng)之前需要更新下 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 只是被調(diào)用一次。在 drawScene 中不需要。

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

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