標籤:
前幾章對圖形圖形內部多是 以純色填充,但是現實中已經有許多好的圖片了我們沒必要一點點畫,這一章第五章就是將圖片以紋理的形式載入到片元中,主要過程如下,首先是定義點的座標的attribute變數用於在javascript中 賦值,接下來定義varying 的vec2的變數用於將紋理座標從頂點著色器傳給片元著色器 在片元著色器中定義取樣器左右儲存紋理映像和相關參數,接下來就是為各個變數賦值,賦值方法與前面一直,先是建立緩衝區,綁定矩陣,寫入資料,擷取變數儲存地址,再就是寫入緩衝區資料,最後啟用變數,這樣就為頂點座標和紋理座標賦值了,最後是對取樣器賦值 取樣器是uniform的 先建立紋理對象,擷取取樣器地址,擷取映像對象,設定映像Y軸反轉,因為無法對紋理對象直接操作所以指定紋理單員,啟用單元,將紋理對象和紋理單元綁定,配置紋理參數,配置紋理映像,最後取樣器賦值,然後畫圖形。
上代碼:
<!DOCTYPE html>
<html>
<head>
<title>TexturedQuad.html</title>
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<!--<link rel="stylesheet" type="text/css" href="./styles.css">-->
<script src="js/cuon-matrix.js"></script>
<script src="js/cuon-utils.js"></script>
<script src="js/webgl-debug.js"></script>
<script src="js/webgl-utils.js"></script>
<script type="text/javascript">
var VSHADER_SOURCE=//定點著色器
‘attribute vec4 a_Position;\n‘+//定義vec4的變數 並且聲明該變數是attribute型的
‘attribute float a_PointSize;\n‘+
‘attribute vec2 a_TextCoord;\n‘+
‘varying vec2 v_TextCoord;\n‘+
‘void main(){\n‘+
‘gl_Position=a_Position;\n‘+//將attribute的變數賦值給內部
‘gl_PointSize=a_PointSize;\n‘+
‘v_TextCoord=a_TextCoord;\n‘+//將資料傳給片元著色器
‘}\n‘;
var FSHADER_SOURCE=//片元著色器
‘precision mediump float;\n‘ +
‘uniform sampler2D u_Sampler;\n‘+
‘varying vec2 v_TextCoord;\n‘+
‘void main(){\n‘+
‘gl_FragColor=texture2D(u_Sampler,v_TextCoord);\n‘+//
‘}\n‘;
function main(){
var canvas=document.getElementById("webgl");
var gl=getWebGLContext(canvas);
if(!gl){
console.log("gl load fail!");
return;
}
if(!initShaders(gl,VSHADER_SOURCE,FSHADER_SOURCE)){//初始化著色器
console.log("fail init shader()!");
return ;
}
var n=initVertexBuffers(gl);//將頂點座標和紋理座標賦值
if(n<0){
console.log("failed to set the positions of the vertices");
return;
}
gl.clearColor(0.0, 0.0, 1.0, 1.0);
initTextures(gl,n);
}
function initVertexBuffers(gl){
var verticesTextCoords=new Float32Array([
-0.5,0.5,2,-0.3,1.7,
-0.5,-0.5,2,-0.3,-0.2,
0.5,0.5,2,1.7,1.7,
0.5,-0.5,2,1.7,-0.2,
]);//類型化數組
var n=4;//點的個數
var vertexTexcoordBuffer=gl.createBuffer();//在webGL中建立緩衝區
if(!vertexTexcoordBuffer){
console.log("failed to create the buffer object!");
return -1;
}
gl.bindBuffer(gl.ARRAY_BUFFER,vertexTexcoordBuffer);//將緩衝區與ARRAY_BUFFER綁定就是指定了緩衝區的用途
gl.bufferData(gl.ARRAY_BUFFER,verticesTextCoords,gl.STATIC_DRAW);//往緩衝區寫資料 STATIC_DRAW對緩衝區最佳化 將頂點座標和紋理座標放進緩衝區
var FSize=verticesTextCoords.BYTES_PER_ELEMENT;//數組中每個元素的位元組大小
//alert(FSize);
//設定頂點座標 從緩衝區取出座標
var a_Position=gl.getAttribLocation(gl.program,‘a_Position‘);
gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,5*FSize,0);//將緩衝區的資料傳入分配給attribute對象 2是定點的分量個數 3*FSize表示相鄰兩個頂點間相距的位元組數也可以理解為每隔3*FSize位元組取倆值 是這些 0表示它的其實 位移量就是從哪開始的
gl.enableVertexAttribArray(a_Position);//開啟attribute變數
//將紋理座標分配給webgl
var a_TextCoord=gl.getAttribLocation(gl.program,‘a_TextCoord‘);
gl.vertexAttribPointer(a_TextCoord,2,gl.FLOAT,false,5*FSize,3*FSize);
gl.enableVertexAttribArray(a_TextCoord);
//設定點的大小
var a_PointSize=gl.getAttribLocation(gl.program,‘a_PointSize‘);
gl.vertexAttribPointer(a_PointSize,1,gl.FLOAT,false,5*FSize,2*FSize);
gl.enableVertexAttribArray(a_PointSize);
return n;
}
function initTextures(gl,n){
//alert(n);
var texture=gl.createTexture();//建立紋理對象 用來管理紋理
if(!texture){
console.log("failed to texture");
return false;
}
//u_Sampler是用來儲存紋理的
var u_Sampler=gl.getUniformLocation(gl.program,‘u_Sampler‘);
if(!u_Sampler){
console.log("failed to u_Sampler");
return false;
}
//載入圖片建立圖片對象非同步載入圖片載入完後調用loadTexture函數 未完成前也繼續執行下面的代碼
var image=new Image();
image.onload=function(){
loadTexture(gl,n,texture,u_Sampler,image);//將紋理單元的映像以及參數傳給取樣器
};
image.src="image/sky.jpg";
return true;
}
function loadTexture(gl,n,texture,u_Sampler,image){
//alert(image.height);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1);//對映像進行Y軸反轉
gl.activeTexture(gl.TEXTURE0);//開啟0號單元
//console.log(gl.activeTexture(gl.TEXTURE0));
gl.bindTexture(gl.TEXTURE_2D,texture);//將紋理對象綁定到紋理單元中 因為沒法直接操作紋理對象但是可以操作紋理單元
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);//配置紋理的參數
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);//在X軸上不足會自動填滿
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.MIRRORED_REPEAT);//在y軸上不足的灰自動tian
gl.texImage2D(gl.TEXTURE_2D,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE,image);//配置紋理映像
gl.uniform1i(u_Sampler,0);//將0單元的紋理傳給紋理取樣器
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLE_STRIP,0,n);
}
</script>
</head>
<body onload="main()">
<canvas id="webgl" width="600" height="400"></canvas>
</body>
</html>
WebGL學習筆記四點二