由于从本篇开始,代码量会逐渐增多。每行代码都尽量做到中文注释。
如有疑问可以在下方留言。本示例基于typescript语言开发,是前几篇的连载。
本篇代码主要学习利用WebGL在Canvas上画一个三角形。成果如下图所示:
创建一个 HelloTriangles.ts 然后在 Main.ts 中调用它,全部代码如下:
namespace
sunnyboxs {
//namespace命名空间
export
class
HelloTriangles {
//类名
constructor()
//构造函数
{
//通过元素id来获取对象
var
canvas:
HTMLCanvasElement = <
HTMLCanvasElement>
document.
getElementById(
'my-canvas');
if (!
canvas) {
console.
log(
"错误:无法获取到 Canvas 元素!");
return;
}
//获取一个3d绘图上下文,表明我们将使用webgl相关的api
var
gl:
WebGLRenderingContext =
this.
create3DContext(
canvas);
if (
gl ==
null) {
console.
log(
"错误:无法获取到 WebGL 上下文!");
return;
}
//设置WebGL渲染区域尺寸
gl.
viewport(
0,
0,
canvas.
clientWidth,
canvas.
clientHeight);
//顶点着色器
var
vertexShaderSource:
string =
`
attribute vec4 a_Position;
void main()
{
gl_Position = vec4(a_Position.x, a_Position.y, a_Position.z, 1.0);
}
`;
//片段着色器
var
fragmentShaderSource:
string =
`
precision mediump float;
void main()
{
gl_FragColor = vec4(1.0, 0.5, 0.2, 1.0);
}
`;
// 生成并编译顶点着色器和片段着色器
// =========================================================================
// 首先是创建和编译顶点着色器
var
vertexShader:
WebGLShader |
null =
gl.
createShader(
gl.
VERTEX_SHADER);
gl.
shaderSource(
vertexShader,
vertexShaderSource);
gl.
compileShader(
vertexShader);
//编译
// 检查着色器代码是否发生编译错误
if (!
gl.
getShaderParameter(
vertexShader,
gl.
COMPILE_STATUS)) {
var
log:
string |
null =
gl.
getShaderInfoLog(
vertexShader);
gl.
deleteShader(
vertexShader);
console.
log(
"错误:编译vertex顶点着色器发生错误:" +
log);
return;
}
// 片段着色器
var
fragmentShader:
WebGLShader |
null =
gl.
createShader(
gl.
FRAGMENT_SHADER);
gl.
shaderSource(
fragmentShader,
fragmentShaderSource);
gl.
compileShader(
fragmentShader);
//编译
// 检查着色器代码是否发生编译错误
if (!
gl.
getShaderParameter(
fragmentShader,
gl.
COMPILE_STATUS)) {
var
log:
string |
null =
gl.
getShaderInfoLog(
fragmentShader);
gl.
deleteShader(
fragmentShader);
console.
log(
"错误:编译fragment片段着色器发生错误:" +
log);
return;
}
// 链接到着色器
var
shaderProgram:
WebGLProgram |
null =
gl.
createProgram();
gl.
attachShader(
shaderProgram,
vertexShader);
//导入顶点着色器
gl.
attachShader(
shaderProgram,
fragmentShader);
//导入片断着色器
gl.
linkProgram(
shaderProgram);
//链接到着色器
// 检查链接时,是否发生错误
if (!
gl.
getProgramParameter(
shaderProgram,
gl.
LINK_STATUS)) {
var
log:
string |
null =
gl.
getProgramInfoLog(
shaderProgram);
console.
log(
"错误:链接到着色器时发生错误:" +
log);
return;
}
//链接完成后可以释放源
gl.
deleteShader(
vertexShader);
gl.
deleteShader(
fragmentShader);
// 创建一个三角形的顶点数据
// =========================================================================
var
vertices:
number[] = [
-
0.5, -
0.5,
0.0,
// left
0.5, -
0.5,
0.0,
// right
0.0,
0.5,
0.0
// top
];
// 创建并绑定一个VBO对象
var
VBO:
WebGLBuffer |
null =
gl.
createBuffer();
//创建一个VBO顶点Buffer
gl.
bindBuffer(
gl.
ARRAY_BUFFER,
VBO);
//绑定
gl.
bufferData(
gl.
ARRAY_BUFFER,
new
Float32Array(
vertices),
gl.
STATIC_DRAW);
//填充数据
//给指定的着色器变量a_Position赋值
var
a_Position =
gl.
getAttribLocation(
shaderProgram,
'a_Position');
//获取地址
//参数:着色器中的位置,顶点大小,数据类型,是否标准化,步长,偏移量
gl.
vertexAttribPointer(
a_Position,
3,
gl.
FLOAT,
false,
0,
0);
gl.
enableVertexAttribArray(
a_Position);
//激活
//开始渲染
// =========================================================================
//清空指定<canvas>的颜色
gl.
clearColor(
0.2,
0.3,
0.3,
1.0);
//清空<canvas>
gl.
clear(
gl.
COLOR_BUFFER_BIT);
// 画出三角形
gl.
useProgram(
shaderProgram);
gl.
bindBuffer(
gl.
ARRAY_BUFFER,
VBO);
gl.
drawArrays(
gl.
TRIANGLES,
0,
3);
//渲染结束
}
//获取一个兼容的webgl上下文
private
create3DContext(
canvas:
HTMLCanvasElement):
WebGLRenderingContext |
any {
var
names:
string[] = [
"webgl",
"experimental-webgl",
"webkit-3d",
"moz-webgl"];
for (
var
i =
0;
i <
names.
length;
i++) {
try {
var
context:
WebGLRenderingContext = <
WebGLRenderingContext>
canvas.
getContext(
names[
i]);
if (
context) {
return
context;
}
}
catch (
e) { }
}
return
null;
}
}
}
另外,Main.ts 修改为调用 HelloTriangles.ts 编译就可以了。Main.ts 代码如下:
import
HelloCanvas =
sunnyboxs.
HelloCanvas;
import
HelloTriangles =
sunnyboxs.
HelloTriangles;
//new HelloCanvas();
new
HelloTriangles();
整个工程目录结构如下,请参见前几篇的教程:
如有错误之处欢迎指正。
下一节,我们继续一步一步学习WebGL!
欢迎关注~~
结尾:推荐一个写glsl的vscode插件,写着色器会有代码提示和代码着色:
Shader languages support for VS Code