背景
本篇收錄於《資料視覺化和圖形學》專欄
之前介紹紋理相關的理論及簡單使用 有需要可以參考上文 , 在上文基礎進行多紋理實踐(更多是幫助群內小夥伴提前脫坑!!!!)
本篇大綱
- 多紋理渲染實現思路
- 多紋理渲染coding(幾種場景)
1. 多紋理渲染實現思路
多紋理渲染更多是指 gl_FragColor採取混合紋理 texture2D * texture2D的關係。本篇初衷為了幫助群裡小夥伴的進階坎坷路~會提到多vertex(紋理)渲染 然後座標重疊的需求。
- 定義vertexArray(本文示例為2point)
- 定義textureArray
- 建立緩衝區(此處注意多渲染節點公用緩衝區情況)
- 按部就班依此註冊shader.繫結資料,渲染。
多紋理渲染coding(幾種場景)
第一種 gl_FragColor採取混合紋理 texture2D * texture2D
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);
第二種 多個節點紋理(其實就是座標重疊 後者覆蓋前者...)
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); // 繪製多個(三角形組合)正方形
!!!!注意 群裡小夥伴留意程式碼中註釋 (解決你的疑惑)
1.
webgl-utils.js
webgl相關函式封裝工具庫完整程式碼示例 [請點選git倉庫檢視程式碼示例]
texture.html
2D渲染方面你可能需要了解的有
- 紋理快取
- 紋理壓縮
- 2D/2D紋理優化
- 渲染優化...
最後
最後強烈希望大家學習相關理論知識;理論可能日常用到的地方很少,但是它能決定你走多遠。(有的人問難怎麼辦,勤於練習吧) 寫作速度我感覺我又行了,哈哈哈... 最近會持續更新(因為在自研自己的渲染引擎。唉 一言難盡。。。抱歉啦)