這裏就須要用到紋理映射,他就是將一張真實圖片貼到一個幾何圖像表面。html
紋理圖像:映射的這個圖像稱爲紋理圖像;web
紋素:組成紋理圖像的像素稱爲紋素;canvas
紋理座標:是紋理圖像上的座標,經過紋理座標能夠在紋理圖像上獲取紋素顏色;瀏覽器
效果圖:異步
操做步驟:post
1.建立HTML5 canvas動畫
2.獲取畫布 canvas 的 IDwebgl
3.獲取WebGLurl
4.編譯着色器,合併程序spa
5.使用緩衝區對象向頂點傳入多個頂點數據
6.建立紋理,加載紋理圖像,配置屬性,在webgl中使用它;
7.加載紋理圖像,配置屬性,在webgl中使用它;
以上1~3參考:http://www.cnblogs.com/bsman/p/6128447.html
4.編譯着色器
//頂點着色器程序 var VSHADER_SOURCE = "attribute vec4 a_Position;" + "attribute vec2 a_TextCoord;" + // 接受紋理座標 "varying vec2 v_TexCoord;" + // 傳遞紋理座標 "void main() {" + //設置座標 "gl_Position = a_Position; " + // 設置座標 //設置紋素 "v_TexCoord = a_TextCoord; " + // 設置紋理座標 "} "; //片元着色器 var FSHADER_SOURCE = "precision mediump float;" + //須要聲明浮點數精度,不然報錯No precision specified for (float) "uniform sampler2D u_Sampler;" + // 取樣器 "varying vec2 v_TexCoord;" + // 接受紋理座標 "void main() {" + //設置顏色 "gl_FragColor = texture2D(u_Sampler, v_TexCoord);" + // 設置顏色 "}";
解釋:在頂點着色器中爲每一個頂點指定紋理座標,而後在片元着色器中根據每一個片元的紋理座標從紋理圖像中抽取紋素顏色
5.使用緩衝區對象向頂點傳入多個頂點數據
function initBuffers(gl, shaderProgram) { //頂點座標和顏色 var vertices = new Float32Array([ -0.5, 0.5, 0.0, 1.0, -0.5, -0.5, 0.0, 0.0, 0.5, 0.5, 1.0, 1.0, 0.5, -0.5, 1.0, 0.0 ]); var n = 4;//點的個數 //建立緩衝區對象 var vertexBuffer = gl.createBuffer(); //將緩衝區對象綁定到目標 gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer); //向緩衝區寫入數據 gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW); var FSIZE = vertices.BYTES_PER_ELEMENT; //獲取座標點 var a_Position = gl.getAttribLocation(shaderProgram, "a_Position"); //將緩衝區對象分配給a_Position變量 gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE*4, 0); //鏈接a_Position變量與分配給它的緩衝區對象 gl.enableVertexAttribArray(a_Position); //獲取Color座標點 var a_TextCoord = gl.getAttribLocation(shaderProgram, "a_TextCoord"); //將緩衝區對象分配給a_Position變量 gl.vertexAttribPointer(a_TextCoord, 2, gl.FLOAT, false, FSIZE*4, FSIZE*2); //鏈接a_Position變量與分配給它的緩衝區對象 gl.enableVertexAttribArray(a_TextCoord); return n; }
6.初始建立紋理,建立image對象
function initTexture(gl, shaderProgram, n){ //建立紋理對象 var texture = gl.createTexture(); //獲取u_Sampler的存儲位置 var u_Sampler = gl.getUniformLocation(shaderProgram, 'u_Sampler'); //建立image對象 var image = new Image(); //加載紋理 image.onload = function(){ loadTexture(gl, n, texture, u_Sampler, image); }; // 瀏覽器開始加載圖片 注意:必定是2^mx2^n尺寸的圖片 image.src = "../TexturedQuad/shan.jpg"; return true; }
u_Sampler表明從紋理圖像中獲取紋理顏色
gl.createTexture();建立紋理對象以存儲紋理對象;gl.TEXTURE0~gl.TEXTURE7是管理紋理圖像的8個紋理單元
注意:這樣圖片的尺寸必定是2^mx2^n尺寸的圖片,否則會報錯 WebGL: drawArrays: texture bound to texture unit 0 is not renderable.
瀏覽器異步加載圖片
7.加載紋理圖像,配置屬性,在webgl中使用它;
function loadTexture(gl, n, texture, u_Sampler,image){ //1.對紋理圖像進行Y軸反轉 gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1); //2.開啓0號紋理單元 gl.activeTexture(gl.TEXTURE0); //3.向target綁定紋理對象 gl.bindTexture(gl.TEXTURE_2D, texture); //4.配置紋理參數 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); //5.配置紋理圖像 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image); //6.將0號紋理圖像傳遞給着色器 gl.uniform1i(u_Sampler, 0); // 清空 <canvas> gl.clear(gl.COLOR_BUFFER_BIT); //繪製矩形 gl.drawArrays(gl.TRIANGLE_STRIP, 0, n); }
7.1對紋理圖像進行Y軸反轉,由於WebGL紋理座標系統的t軸(分爲t軸和s軸)的方向和圖片的座標系統Y軸方向相反。所以將Y軸進行反轉。
gl.pixelStorei 第一個參數:有兩個,一個UNPACK_FLIP_Y_WEBGL表明對Y軸反轉,默認爲false;一個UNPACK_PREMULTIPLY_ALPHA_WEBGL表明將圖像 RGB顏色值得每個份量乘以A,默認值爲false;
7.2開啓0號紋理單元
WebGL經過紋理單元的機制來同時使用多個紋理,gl.TEXTURE0~gl.TEXTURE7是管理紋理圖像的8個紋理單元
7.3綁定紋理對象
gl.bindTexture兩個參數
第一個參數:有兩個選擇TEXTURE_2D表明二維紋理,TEXTURE_CUBE_MAP 立方體紋理;
第二個參數:表示綁定的紋理單元
7.4配置紋理參數
gl.texParameteri三個參數
第一個參數:有兩個選擇TEXTURE_2D表明二維紋理,TEXTURE_CUBE_MAP 立方體紋理;
第二個參數:有4個紋理參數
1.TEXTURE_MAX_FILTER:放大方法 默認:gl.LINEAR
2.TEXTURE_MIN_FILTER:縮小方法 默認:gl.NEAREST_MIPMAP_LINEAR
3.TEXTURE_WRAP_S: 水平填充方法 默認:gl.REPEAT
4.TEXTURE_WRAP_T: 垂直填充方法 默認:gl.REPEAT
第三個參數:
gl.LINEAR:使用距離新像素中心最近的四個像素的顏色值得加權值平均(圖片質量好,可是開銷大)
gl.NEAREST_MIPMAP_LINEAR:使用原紋理上的距離映射後像素中心最近的那個像素的顏色值做爲新像素的值
gl.REPEAT:平鋪式的重複紋理
gl.REPEAT:鏡像對稱式的重複紋理
gl.REPEAT:使用紋理圖像邊緣值
7.5配置紋理圖像
gl.texImage2D有六個參數
第一個參數:有兩個選擇TEXTURE_2D表明二維紋理,TEXTURE_CUBE_MAP 立方體紋理;
第二個參數:默認爲0,涉及到三維再說
第三個參數:圖像的內部格式
有:gl.RGB(紅綠藍)、gl.RGBA(紅綠藍透明度)、gl.ALPHA(0.0,0.0,0.0,透明度)、gl.LUMINANCE(L、L、L、1L:流明)、
gl.LUMINANCE_ALPHA(L、L、L,透明度)、
流明:表示咱們感知到的物體表面的亮度,等於紅綠藍顏色份量值的加權平均來計算流明
第四個參數:紋理的數據格式,必須與第三個參數相同
第五個參數:紋理數據格式 UNSIGNED_BYTE:表示無符號整形,每個顏色份量佔據1字節
UNSIGNED_SHORT_5_6_5:表示RGB,每個份量分別佔據佔據5,6,5比特
UNSIGNED_SHORT_4_4_4_4:表示RGBA,每個份量分別佔據佔據4,4,4,4比特
UNSIGNED_SHORT_5_5_5_1:表示RGBA,每個份量分別佔據佔據5比特,A份量佔據1比特
第六個參數:紋理圖像的image對象
7.6將0號紋理圖像傳遞給着色器
uniform1i(u_Sampler, 0);這裏和上面的片元着色器"gl_FragColor = texture2D(u_Sampler, v_TexCoord);" + // 設置顏色,有聯繫
其中:sampler2D綁定到gl.TEXTURE_2D上,samplerCube綁定到gl.TEXTURE_CUBE_MAP上