1.几何图形装配(图元装配):将孤立的顶点坐标装配成几何图形。几何图形的类别由gl.drawArrays()函数的第一个参数决定,装配出来的基本图形(点、线、面)被称为图元
2.光栅化:将装配好的几何图形转化为片元。
3.几何图形装配和光栅化过程:光栅化完成后程序逐片调用片元着色器
例如下面程序中着色器的执行过程是:
(1)顶点着色器执行三次,获得三角形的顶点坐标并存放在图形的装配区(有多少顶点就执行多少次)
(2)开始装配图形,使用传入gl_Position的坐标和gl.drawArrays()方法的第一个参数来决定如何装配。
(3)将图形转化为片元。(本例中,片元是像素)
(4)片元着色器开始逐片元操作(图形由多少片元组成就执行多少次)
vec4 gl_fragCoord 该内置变量的第一二个变量分别表示片元在canvas坐标系统(窗口坐标系统)中的坐标值
var SHADER_SOURCE =
'attribute vec4 a_Position;\n'+
'void main(){\n'+
'gl_Position = a_Position;\n'+
'}\n';
var FSHADER_SOURCE =
'precision mediump float;\n'+
'uniform float u_Width;\n' +
'uniform float u_Height;\n'+
'void main(){\n'+
'gl_FragColor = vec4(gl_FragCoord.x/u_Width,0.0,gl_FragCoord.y/u_Height,1.0);\n'+
'}\n';
function main()
{
var canvas = document.getElementById("webgl");
if(!canvas)
{
console.log("获取canvas标签失败");
}
var gl = canvas.getContext("webgl");
if(!gl)
{
console.log("获取上下文失败");
}
if(!initShaders(gl,SHADER_SOURCE,FSHADER_SOURCE))
{
console.log("加载着色器程序失败");
}
var n = initVertexBuffers(gl);
if(n<0)
{
console.log("设置顶点失败");
}
var u_Width = gl.getUniformLocation(gl.program,'u_Width');
var u_Height = gl.getUniformLocation(gl.program,'u_Height');
gl.uniform1f(u_Width,500.0);
gl.uniform1f(u_Height,500.0);
gl.drawArrays(gl.TRIANGLES,0,n);
}
function initVertexBuffers(gl)
{
var vertices = new Float32Array([0.0,0.5,-0.5,-0.5,0.5,-0.5]);
var n = 3; //顶点个数
//创建缓冲区对象
var vertexBuffer = gl.createBuffer();
if(!vertexBuffer)
{
console.log("创建缓冲区失败");
return -1;
}
//将缓冲区对象绑定到目标
gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer);
//向缓冲区对象写入数据
gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);
var a_Position = gl.getAttribLocation(gl.program,'a_Position');
//将缓冲区对象分配给a_Position变量
gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,0,0);
//连接a_Position变量与分配给他的缓冲区对象
gl.enableVertexAttribArray(a_Position);
return n;
}
4.内插:线段两端顶点颜色确定后,线段上所有片元的颜色值都会被恰当地计算出来
下面代码为三角形三个顶点分别指定了三种颜色,而输出结果是一个整体颜色渐变的三角形,因为v_Color变量在传入片元着色器之前,v_Color已经自动进行了内插,片元着色器接受到的是计算完后的每个片元的颜色值。所以我们把这种变量称为"varying"
var SHADER_SOURCE =
'attribute vec4 a_Position;\n'+
'attribute float a_PointSize;\n' +
'attribute vec4 a_Color;\n' +
'varying vec4 v_Color;\n'+
'void main(){\n'+
'gl_Position = a_Position;\n'+
'gl_PointSize = a_PointSize;\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';
function main()
{
var canvas = document.getElementById("webgl");
if(!canvas)
{
console.log("获取canvas标签失败");
}
var gl = canvas.getContext("webgl");
if(!gl)
{
console.log("获取上下文失败");
}
if(!initShaders(gl,SHADER_SOURCE,FSHADER_SOURCE))
{
console.log("加载着色器程序失败");
}
var n = initVertexBuffers(gl);
if(n<0)
{
console.log("设置顶点失败");
}
gl.drawArrays(gl.TRIANGLES,0,n);
}
function initVertexBuffers(gl)
{
var vertices = new Float32Array([
0.0,0.5,10.0,1.0,0.0,0.0,
-0.5,-0.5,20.0,0.0,1.0,0.0,
0.5,-0.5,30.0,0.0,0.0,1.0,
]);
var n = 3; //顶点个数
//创建缓冲区对象
var vertexBuffer = gl.createBuffer();
if(!vertexBuffer)
{
console.log("创建缓冲区失败");
return -1;
}
var FSIZE = vertices.BYTES_PER_ELEMENT;
//将缓冲区对象绑定到目标
gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer);
//向缓冲区对象写入数据
gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);
var a_Position = gl.getAttribLocation(gl.program,'a_Position');
//将缓冲区对象分配给a_Position变量
gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,FSIZE*6,0);
//连接a_Position变量与分配给他的缓冲区对象
gl.enableVertexAttribArray(a_Position);
var sizeBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,sizeBuffer);
gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);
var a_PointSize = gl.getAttribLocation(gl.program,'a_PointSize');
gl.vertexAttribPointer(a_PointSize,1,gl.FLOAT,false,FSIZE*6,FSIZE*2);
gl.enableVertexAttribArray(a_PointSize);
var a_Color = gl.getAttribLocation(gl.program,'a_Color');
var colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);
gl.vertexAttribPointer(a_Color,3,gl.FLOAT,false,FSIZE*6,FSIZE*3);
gl.enableVertexAttribArray(a_Color);
return n;
}