书本源代码 https://download.youkuaiyun.com/download/qfire/10371055
4.1 将非坐标数据传入顶点着色器
点的尺寸
// MultiAttributeSize.js (c) 2012 matsuda
// Vertex shader program
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';
// Fragment shader program
var FSHADER_SOURCE =
'void main() {\n' +
' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +
'}\n';
function main() {
// Retrieve <canvas> element
var canvas = document.getElementById('webgl');
// Get the rendering context for WebGL
var gl = getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
// Initialize shaders
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
console.log('Failed to intialize shaders.');
return;
}
// Set the vertex information
var n = initVertexBuffers(gl);
if (n < 0) {
console.log('Failed to set the positions of the vertices');
return;
}
// Specify the color for clearing <canvas>
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// Clear <canvas>
gl.clear(gl.COLOR_BUFFER_BIT);
// Draw three points
gl.drawArrays(gl.POINTS, 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 sizes = new Float32Array([
10.0, 20.0, 30.0 // Point sizes
]);
// Create a buffer object
var vertexBuffer = gl.createBuffer();
var sizeBuffer = gl.createBuffer();
if (!vertexBuffer || !sizeBuffer) {
console.log('Failed to create the buffer object');
return -1;
}
// Write vertex coordinates to the buffer object and enable it
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if(a_Position < 0) {
console.log('Failed to get the storage location of a_Position');
return -1;
}
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_Position);
// Bind the point size buffer object to target
gl.bindBuffer(gl.ARRAY_BUFFER, sizeBuffer);
gl.bufferData(gl.ARRAY_BUFFER, sizes, gl.STATIC_DRAW);
var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');
if(a_PointSize < 0) {
console.log('Failed to get the storage location of a_PointSize');
return -1;
}
gl.vertexAttribPointer(a_PointSize, 1, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_PointSize);
// Unbind the buffer object
gl.bindBuffer(gl.ARRAY_BUFFER, null);
return n;
}

4.2 gl.vertexAttribPointer()的步进和偏移参数
WebGL允许我们把顶点的坐标和尺寸数据打包到同一个缓冲区对象中,并通过某种机制分别访问缓冲区对象中不同种类的数据。
4.3 彩色三角形
一旦光栅化过程结束后,程序就开始逐片元调用片元着色器。片元着色器每调用一次,就处理一个片元。
光栅化是三维图形学的关键技术之一,它负责将矢量的几何图形转变为栅格化的片元(像素)。图形被转化为片元之后,我们就可以在片元着色器内做更多的事情,如为每个片元指定不同的颜色。颜色可以内插出来,也可以直接编程指定。
不同片元的颜色不同
4.4 在矩形表面贴上图像
纹理映射将一张图像贴到一个几何图形的表面上去。这张图片又可以称为纹理图像。根据纹理图像,为之前光栅化后的每个片元涂上合适的颜色。组成纹理图像的像素又被称为纹素。
四步:
- 准备好映射到几何图形上的纹理图像
- 为几何图形配置纹理映射方式
- 加载纹理图像,对其进行一些配置,以在WebGL中使用它
- 在片元着色器中将相应的纹素从纹理中抽取出来,并将纹素的颜色赋给片元。
纹理坐标是纹理图像上的坐标,通过纹理坐标可以在纹理图像上获取纹素颜色。WebGL系统中的纹理坐标系统是二维的,使用s和t命名纹理坐标。坐标值与图像自身的尺寸无关,不管是128x128还是128x156,其右上角的纹理坐标始终是(1.0, 1.0)
设置纹理坐标(initVertexBuffers())
将纹理坐标传入顶点着色器,与将其他顶点数据相同
配置和加载纹理(initTextures())
激活纹理单元(gl.activeTexture()):WebGL至少支持8个纹理单元。
绑定纹理对象(gl.bindTexture())
配置纹理对象的参数(gl.texParameteri())
将纹理图像分配给纹理对象(gl.texImage2D())
将纹理单元传递给片元着色器(gl.uniform1i())
从顶点着色器向片元着色器传输纹理坐标:根据片元的纹理坐标,从纹理图像上抽取出纹素的颜色
在片元着色器中获取纹理像素颜色(texture2D())
纹理图像不足以覆盖整个矩形
4.5 使用多幅纹理
最终的片元颜色由两个纹理上的纹素颜色共同决定