圖形學之紋理後續/WebGL多紋理處理

wlove發表於2021-10-14

背景

本篇收錄於《資料視覺化和圖形學》專欄

之前介紹紋理相關的理論及簡單使用 有需要可以參考上文 , 在上文基礎進行多紋理實踐(更多是幫助群內小夥伴提前脫坑!!!!)

本篇大綱

  1. 多紋理渲染實現思路
  2. 多紋理渲染coding(幾種場景)

1. 多紋理渲染實現思路

多紋理渲染更多是指 gl_FragColor採取混合紋理 texture2D * texture2D的關係。本篇初衷為了幫助群裡小夥伴的進階坎坷路~會提到多vertex(紋理)渲染 然後座標重疊的需求。
  1. 定義vertexArray(本文示例為2point)
  2. 定義textureArray
  3. 建立緩衝區(此處注意多渲染節點公用緩衝區情況)
  4. 按部就班依此註冊shader.繫結資料,渲染。

多紋理渲染coding(幾種場景)

第一種 gl_FragColor採取混合紋理 texture2D * texture2D
image.png

shader部分沒什麼難度...

// vertex
attribute vec2 a_position; //座標
attribute vec2 a_texCoord; //紋理

uniform vec2 u_resolution;

varying vec2 v_texCoord;

void main() {
   //  座標轉換畫素->1.0,0.0...
   vec2 zeroToOne = a_position / u_resolution;

   vec2 zeroToTwo = zeroToOne * 2.0;

   vec2 clipSpace = zeroToTwo - 1.0;
    
   gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
   // 紋理 給fragment使用 
   v_texCoord = a_texCoord;
}

// fragment
uniform sampler2D u_image0;  // 紋理
uniform sampler2D u_image1;

// 來自vertex shader
varying vec2 v_texCoord;

void main() {
   vec4 color0 = texture2D(u_image0, v_texCoord);
   vec4 color1 = texture2D(u_image1, v_texCoord);
   gl_FragColor = color0 * color1;  // 可以理解為混合紋理
}

JavaScript 也很簡單 建立節點座標/紋理/shader&資料連線/渲染 搞定!

// 此處示意程式碼 完整程式碼上傳github
 var texcoordBuffer = gl.createBuffer();  //紋理
 gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
 // bufferData 
 ...
 for(...images length){
     // 迴圈遍歷
     gl.bindTexture(gl.TEXTURE_2D, texture);
 }

 var positionBuffer = gl.createBuffer(); //節點座標  此處繪製TRIANGLES 三角形
 gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
 // bufferData
 
 // 緩衝區分配給attribute變數
 gl.vertexAttribPointer(
  texcoordLocation, size, type, normalize, stride, offset);
 gl.vertexAttribPointer(
  positionLocation, size, type, normalize, stride, offset);
 // 開啟attribute變數
 gl.enableVertexAttribArray(positionLocation);
 gl.enableVertexAttribArray(texcoordLocation);
 
 // 紋理!!!!啟用紋理單元
 gl.activeTexture(gl.TEXTURE0);
 //給定的紋理繫結到目標(vertex)
 gl.bindTexture(gl.TEXTURE_2D, textures[0]);
 
 // 繪製!!! 大功告成
 gl.drawArrays(gl.TRIANGLES, 0, 6);

第二種 多個節點紋理(其實就是座標重疊 後者覆蓋前者...)
image.png

shader部分也沒什麼難度(沒什麼改變)...

// vertex
attribute vec2 a_position;
attribute vec2 a_texCoord;
attribute lowp float textureIndex;

uniform vec2 u_resolution;
varying vec2 v_texCoord;
varying lowp float indexPicker;

void main() {
   vec2 zeroToOne = a_position / u_resolution;
   vec2 zeroToTwo = zeroToOne * 2.0;
   vec2 clipSpace = zeroToTwo - 1.0;
   
   gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
   v_texCoord = a_texCoord;
   indexPicker = textureIndex; // 控制fragment shader選哪一個紋理
}

// fragment
precision mediump float;

// 紋理
uniform sampler2D u_image[2];

// the texCoords passed in from the vertex shader.
varying vec2 v_texCoord;
varying lowp float indexPicker;

void main() {
   if (indexPicker < 0.5) {
       gl_FragColor = texture2D(u_image[0], v_texCoord);
   } else {
       gl_FragColor = texture2D(u_image[1], v_texCoord);
   }
}

JavaScript 也很簡單 建立節點座標/紋理/shader&資料連線/渲染 搞定!

// 此處示意程式碼 完整程式碼上傳github
 var texcoordBuffer = gl.createBuffer();  //紋理
 gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
 // bufferData 
 ...
 for(...images length){
     // 迴圈遍歷
     gl.bindTexture(gl.TEXTURE_2D, texture);
 }
 
 
 // 注意vertex!!!!! 此處與上文不同 
 var positionBuffer = gl.createBuffer(); //節點座標  此處繪製TRIANGLES 三角形
 gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
 // bufferData
 
 // 緩衝區分配給attribute變數
 gl.vertexAttribPointer(
  texcoordLocation, size, type, normalize, stride, offset);
 gl.vertexAttribPointer(
  positionLocation, size, type, normalize, stride, offset);
 // 開啟attribute變數
 gl.enableVertexAttribArray(positionLocation);
 gl.enableVertexAttribArray(texcoordLocation);
 
 // 紋理!!!!啟用紋理單元
 gl.activeTexture(gl.TEXTURE0);
 //給定的紋理繫結到目標(vertex)
 gl.bindTexture(gl.TEXTURE_2D, textures[0]);
 
 // 繪製!!! 大功告成
 gl.drawArrays(gl.TRIANGLES, 0, vertextArray.length/2); // 繪製多個(三角形組合)正方形

!!!!注意 群裡小夥伴留意程式碼中註釋 (解決你的疑惑)

image.png

1.webgl-utils.js webgl相關函式封裝工具庫

完整程式碼示例 [請點選git倉庫檢視程式碼示例]
texture.html

texture1.html

2D渲染方面你可能需要了解的有

  1. 紋理快取
  2. 紋理壓縮
  3. 2D/2D紋理優化
  4. 渲染優化...

最後

最後強烈希望大家學習相關理論知識;理論可能日常用到的地方很少,但是它能決定你走多遠。(有的人問難怎麼辦,勤於練習吧) 寫作速度我感覺我又行了,哈哈哈... 最近會持續更新(因為在自研自己的渲染引擎。唉 一言難盡。。。抱歉啦)

相關文章