第五章 顏色與紋理
- gl.vertexAttribPointer()的步進和偏移參數
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';
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
]);
var vertexBuffer = gl.createBuffer();
var sizeBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_Position);
gl.bindBuffer(gl.ARRAY_BUFFER, sizeBuffer);
gl.bufferData(gl.ARRAY_BUFFER, sizes, gl.STATIC_DRAW);
var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');
gl.vertexAttribPointer(a_PointSize, 1, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_PointSize);
2.varying變量
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'attribute vec4 a_Color;\n' +
'varying vec4 v_Color;\n' +
'void main() {\n' +
' gl_Position = a_Position;\n' +
' gl_PointSize = 10.0;\n' +
' v_Color = a_Color;\n' +
'}\n';
var FSHADER_SOURCE =
'precision mediump float;\n' +
'varying vec4 v_Color;\n' +
'void main() {\n' +
' gl_FragColor = v_Color;\n' +
'}\n';
var verticesColors = new Float32Array([
// Vertex coordinates and color 頂點坐標和顏色
0.0, 0.5, 1.0, 0.0, 0.0, //一個頂點信息
-0.5, -0.5, 0.0, 1.0, 0.0,
0.5, -0.5, 0.0, 0.0, 1.0,
]);
var vertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexColorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);
var FSIZE = verticesColors.BYTES_PER_ELEMENT;
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
/*
2 :指定了每個頂點的分量個數(x,y),
FSIZE*5 :指定了相鄰兩個頂點之間的字節數
0 :指定了偏移量
*/
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 5, 0);
gl.enableVertexAttribArray(a_Position);
/*
3 :指定了每個頂點的所需顏色的分量數(R,G,B),
FSIZE*5 :指定了相鄰兩個頂點之間的字節數
FSIZE*2 :指定了偏移量,每個頂點信息的前兩個是頂點坐標信息
*/
var a_Color = gl.getAttribLocation(gl.program, 'a_Color');
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 5, FSIZE * 2);
gl.enableVertexAttribArray(a_Color);
/*
GL_ES語句中,頂點著色器中定義了a_color和v_color,并將a_color的值賦值給了v_color,然后在片元著色器中定義了v_color
并將v_color的值賦值給FragColor,由于兩個著色器中的兩個v_color指向了同一個空間,所以在上面的程序中將頂點顏色信息
傳遞給a_color,a_color會將該顏色信息傳遞個v_color,而v_color會將顏色信息傳遞給FragColor,實現了對顏色的修改
*/
3.圖形的繪制
確定頂點坐標
圖形裝配
光柵化
執行片元著色器
4.在矩形表面貼上圖像
var VSHADER_SOURCE=
'attribute vec4 a_Position;\n'+
'attribute vec2 a_TexCoord;\n'+
'varying vec2 v_TexCoord;\n'+
'void main(){\n'+
'gl_Position = a_Position;\n'+
'v_TexCoord=a_TexCoord;\n'+
'}\n';
var FSHADER_SOURCE=
'precision mediump float;\n'+
'uniform sampler2D u_Sampler;\n'+
'varying vec2 v_TexCoord;\n'+
'void main(){\n'+
// u_Sampler中存放著取色器的各種信息:紋理圖像,填充方式
// v_TexCoord中存放著紋理坐標,告訴取色器從哪里選取紋理
'gl_FragColor=texture2D(u_Sampler,v_TexCoord);\n'+
'}\n';
//將頂點坐標和紋理坐標分別賦值給GL_ES語句中的a_Position和a_TexCoord
function initVertexBuffers(gl){
// 頂點和紋理坐標數組
var verticesTexCoords=new Float32Array([
// -0.5,0.5是webgl系統坐標系,0.0,1.0是webgl紋理坐標系系統
-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,
]);
.......
}
function initTextures(gl,n){
// 創建紋理對象
var texture = gl.createTexture();
// 該變量用來接收紋理圖像
var u_Sampler=gl.getUniformLocation(gl.program,'u_Sampler');
var image=new Image();
image.onload = function(){loadTexture(gl,n,texture,u_Sampler,image);};
image.src='sky.JPG';
return true;
}
function loadTexture(gl,n,texture,u_Sampler,image){
// 對紋理圖像進行y軸反轉,讀到的圖像是圖像坐標系,它和webgl紋理坐標系系統的y軸方向相反
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1);
// 開啟0號紋理單元
gl.activeTexture(gl.TEXTURE0);
// 應該是綁定0號紋理單元和紋理對象(每個紋理單元都已經和TEXTURE_2D關聯了)
// 在WebGL中,無法直接操作紋理對象,必須通過將紋理對象綁定到紋理單元,然后通過操作紋理單元來間接操作紋理對象
gl.bindTexture(gl.TEXTURE_2D,texture);
// 配置紋理參數 如何根據紋理坐標來獲取紋素顏色、按哪種方式重復填充紋理
/* 參數2 pname:設置填充方法
gl.TEXTURE_MAG_FILTER 放大填充方法,將紋理圖像映射到更大的空間上
gl.TEXTURE_MIN_FILTER 縮小填充方法,將紋理圖像映射到更小的空間上
gl.TEXTURE_WRAP_S 水平填充方法
gl.TEXTURE_WRAP_T 垂直填充方法
參數3 param:為pname制定的方法指定更具體的填充方法
放大縮小方法可選參數:gl.NEAREST gl.LINEAR
gl.NEAREST:使用原紋理上距離映射后像素(新像素)中心最近(曼哈頓距離)的那個像素的顏色值作為新值
默認值 gl.LINEAR:使用距離新像素中心最近的四個像素的顏色值得加權平均值作為新值
水平填充和垂直填充方法可選參數:gl.REPEAT gl.MIRRORED_REPEAT gl.CLAMP_TO_EDGE
默認值 gl.REPEAT 平鋪式的重復紋理
gl.MIRRORED_REPEAT 鏡像對稱式的重復紋理
gl.CLAMP_TO_EDGE 使用紋理圖像邊緣值
*/
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);
// 將紋理圖像分配給紋理對象,將image指定的圖像分配給綁定到紋理目標上的紋理對象
gl.texImage2D(gl.TEXTURE_2D,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE,image);
//gl.uniform1i的第二個參數為0表示的是紋理單元的編號,
gl.uniform1i(u_Sampler,0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLE_STRIP,0,n);
}