第五章 颜色与纹理
- 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);
}