WebGL程式設計指南(4)顏色與紋理

CopperDong發表於2018-04-24

書本原始碼 https://download.csdn.net/download/qfire/10371055

4.1 將非座標資料傳入頂點著色器

   點的尺寸

// MultiAttributeSize.js (c) 2012 matsuda
// Vertex shader program
var VSHADER_SOURCE =
  'attribute vec4 a_Position;\n' +
  'attribute float a_PointSize;\n' +
  'void main() {\n' +
  '  gl_Position = a_Position;\n' +
  '  gl_PointSize = a_PointSize;\n' +
  '}\n';

// Fragment shader program
var FSHADER_SOURCE =
  'void main() {\n' +
  '  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +
  '}\n';

function main() {
  // Retrieve <canvas> element
  var canvas = document.getElementById('webgl');
  // Get the rendering context for WebGL
  var gl = getWebGLContext(canvas);
  if (!gl) {
    console.log('Failed to get the rendering context for WebGL');
    return;
  }
  // Initialize shaders
  if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
    console.log('Failed to intialize shaders.');
    return;
  }
  // Set the vertex information
  var n = initVertexBuffers(gl);
  if (n < 0) {
    console.log('Failed to set the positions of the vertices');
    return;
  }
  // Specify the color for clearing <canvas>
  gl.clearColor(0.0, 0.0, 0.0, 1.0);
  // Clear <canvas>
  gl.clear(gl.COLOR_BUFFER_BIT);
  // Draw three points
  gl.drawArrays(gl.POINTS, 0, n);
}

function initVertexBuffers(gl) {
  var vertices = new Float32Array([
    0.0, 0.5,   -0.5, -0.5,   0.5, -0.5
  ]);
  var n = 3;
  var sizes = new Float32Array([
    10.0, 20.0, 30.0  // Point sizes
  ]);
  // Create a buffer object
  var vertexBuffer = gl.createBuffer();  
  var sizeBuffer = gl.createBuffer();
  if (!vertexBuffer || !sizeBuffer) {
    console.log('Failed to create the buffer object');
    return -1;
  }
  // Write vertex coordinates to the buffer object and enable it
  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;
  }
  gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
  gl.enableVertexAttribArray(a_Position);
  // Bind the point size buffer object to target
  gl.bindBuffer(gl.ARRAY_BUFFER, sizeBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, sizes, gl.STATIC_DRAW);
  var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');
  if(a_PointSize < 0) {
    console.log('Failed to get the storage location of a_PointSize');
    return -1;
  }
  gl.vertexAttribPointer(a_PointSize, 1, gl.FLOAT, false, 0, 0);
  gl.enableVertexAttribArray(a_PointSize);
  // Unbind the buffer object
  gl.bindBuffer(gl.ARRAY_BUFFER, null);
  return n;
}

4.2 gl.vertexAttribPointer()的步進和偏移引數

   WebGL允許我們把頂點的座標和尺寸資料打包到同一個緩衝區物件中,並通過某種機制分別訪問緩衝區物件中不同種類的資料。


4.3 彩色三角形


一旦光柵化過程結束後,程式就開始逐片元呼叫片元著色器。片元著色器每呼叫一次,就處理一個片元。

光柵化是三維圖形學的關鍵技術之一,它負責將向量的幾何圖形轉變為柵格化的片元(畫素)。圖形被轉化為片元之後,我們就可以在片元著色器內做更多的事情,如為每個片元指定不同的顏色。顏色可以內插出來,也可以直接程式設計指定。

不同片元的顏色不同


4.4 在矩形表面貼上影像

   紋理對映將一張影像貼到一個幾何圖形的表面上去。這張圖片又可以稱為紋理影像。根據紋理影像,為之前光柵化後的每個片元塗上合適的顏色。組成紋理影像的畫素又被稱為紋素。

四步

  1. 準備好對映到幾何圖形上的紋理影像
  2. 為幾何圖形配置紋理對映方式
  3. 載入紋理影像,對其進行一些配置,以在WebGL中使用它
  4. 在片元著色器中將相應的紋素從紋理中抽取出來,並將紋素的顏色賦給片元。

紋理座標是紋理影像上的座標,通過紋理座標可以在紋理影像上獲取紋素顏色。WebGL系統中的紋理座標系統是二維的,使用s和t命名紋理座標。座標值與影像自身的尺寸無關,不管是128x128還是128x156,其右上角的紋理座標始終是(1.0, 1.0)


設定紋理座標(initVertexBuffers())

    將紋理座標傳入頂點著色器,與將其他頂點資料相同

配置和載入紋理(initTextures())

啟用紋理單元(gl.activeTexture()):WebGL至少支援8個紋理單元。



繫結紋理物件(gl.bindTexture())

配置紋理物件的引數(gl.texParameteri())


將紋理影像分配給紋理物件(gl.texImage2D())


將紋理單元傳遞給片元著色器(gl.uniform1i())

從頂點著色器向片元著色器傳輸紋理座標:根據片元的紋理座標,從紋理影像上抽取出紋素的顏色

在片元著色器中獲取紋理畫素顏色(texture2D())


紋理影像不足以覆蓋整個矩形

4.5 使用多幅紋理

    最終的片元顏色由兩個紋理上的紋素顏色共同決定



相關文章