# 2. 示例：绘制三角形

// 顶点着色器程序
'attribute vec4 a_Position;\n' + // attribute variable
'attribute vec4 a_Color;\n' +
'varying vec4 v_Color;\n' +
'void main() {\n' +
'  gl_Position = a_Position;\n' + // Set the vertex coordinates of the point
'  v_Color = a_Color;\n' +
'}\n';

// 片元着色器程序
'precision mediump float;\n' +
'varying vec4 v_Color;\n' +
'void main() {\n' +
'  gl_FragColor = v_Color;\n' +
'}\n';

function main() {
// 获取 <canvas> 元素
var canvas = document.getElementById('webgl');

// 获取WebGL渲染上下文
var gl = getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}

// 初始化着色器
return;
}

// 设置顶点位置
var n = initVertexBuffers(gl);
if (n < 0) {
console.log('Failed to set the positions of the vertices');
return;
}

// 指定清空<canvas>的颜色
gl.clearColor(0.0, 0.0, 0.0, 1.0);

// 清空<canvas>
gl.clear(gl.COLOR_BUFFER_BIT);

// 绘制三角形
gl.drawArrays(gl.TRIANGLES, 0, n);
}

function initVertexBuffers(gl) {
// 顶点坐标和颜色
var verticesColors = new Float32Array([
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 n = 3; // 点的个数
var FSIZE = verticesColors.BYTES_PER_ELEMENT;   //数组中每个元素的字节数

// 创建缓冲区对象
var vertexBuffer = gl.createBuffer();
if (!vertexBuffer) {
console.log('Failed to create the buffer object');
return -1;
}

// 将缓冲区对象绑定到目标
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
// 向缓冲区对象写入数据
gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);

//获取着色器中attribute变量a_Position的地址
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;
}
// 将缓冲区对象分配给a_Position变量
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 5*FSIZE, 0);

// 连接a_Position变量与分配给它的缓冲区对象
gl.enableVertexAttribArray(a_Position);

//获取着色器中attribute变量a_Color的地址
var a_Color = gl.getAttribLocation(gl.program, 'a_Color');
if(a_Color < 0) {
console.log('Failed to get the storage location of a_Color');
return -1;
}
// 将缓冲区对象分配给a_Color变量
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 5, FSIZE * 2);
// 连接a_Color变量与分配给它的缓冲区对象
gl.enableVertexAttribArray(a_Color);

// 解除绑定
gl.bindBuffer(gl.ARRAY_BUFFER, null);

return n;
}


## 1) 数据的组织

// 顶点着色器程序
'attribute vec4 a_Position;\n' + // attribute variable
'attribute vec4 a_Color;\n' +
…
'}\n';


  // 创建缓冲区对象
var vertexBuffer = gl.createBuffer();
if (!vertexBuffer) {
console.log('Failed to create the buffer object');
return -1;
}

// 将缓冲区对象绑定到目标
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
// 向缓冲区对象写入数据
gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);

//获取着色器中attribute变量a_Position的地址
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;
}
// 将缓冲区对象分配给a_Position变量
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 5*FSIZE, 0);

// 连接a_Position变量与分配给它的缓冲区对象
gl.enableVertexAttribArray(a_Position);

//获取着色器中attribute变量a_Color的地址
var a_Color = gl.getAttribLocation(gl.program, 'a_Color');
if(a_Color < 0) {
console.log('Failed to get the storage location of a_Color');
return -1;
}
// 将缓冲区对象分配给a_Color变量
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 5, FSIZE * 2);
// 连接a_Color变量与分配给它的缓冲区对象
gl.enableVertexAttribArray(a_Color);


## 2) varying变量

// 顶点着色器程序
…
'varying vec4 v_Color;\n' +
'void main() {\n' +
…
'  v_Color = a_Color;\n' +
'}\n';

// 片元着色器程序
…
'varying vec4 v_Color;\n' +
'void main() {\n' +
'  gl_FragColor = v_Color;\n' +
'}\n';


varying变量表达的正是一种可变的变量，它的作用就是从顶点着色器向片元着色器传输数据。在顶点着色器的main函数中，将从缓冲区对象中获取的attribute变量a_Color赋值给预先定义的varying变量v_Color；同时在片元着色器中又定义了一个同类型同名的varying变量v_Color，那么顶点着色器中该变量的值就会自动传入到片元着色器中。最后在片元着色器的main函数中将该值传入到gl_FragColor中，就得到最终的结果了。其示意图如下：

# 5. 参考

posted @ 2019-09-14 17:46  charlee44  阅读(1013)  评论(0编辑  收藏