WebGL
重要通知
。
webGL基本概况
WebGL(Web 图形库)是一个 JavaScript API,可在任何兼容的 Web 浏览器中渲染高性能的交互式 3D 和 2D 图形,而无需使用插件。
const canvas = document.createElement('canvas');
const width = document.body.clientWidth;
const height = document.body.clientHeight;
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
document.body.append(canvas);
const gl = canvas.getContext("webgl");
webGL实现原理
着色器 shader
着色器是一个绘制东西到屏幕上的函数。
- 顶点着色器
用来描述顶点特性(位置、颜色等)的程序。
const VSHADER_SOURCE = ``;
- 片元着色器
进行逐片元处理的程序,其中,片元指图像的单元。
const FSHADER_SOURCE = ``;
- 初始化着色器
Eshen.initShaderProgram = function(vsSource, fsSource) {
const vertexShader = Eshen.loadShader(gl.VERTEX_SHADER, vsSource);
const fragmentShader = Eshen.loadShader(gl.FRAGMENT_SHADER, fsSource);
if (!vertexShader || !fragmentShader) {
throw new Error(`vertexShader or fragmentShader is null or undefined.`);
}
// 创建着色器程序
const program = gl.createProgram();
if (!program || !gl.isProgram(program)) {
gl.deleteProgram(program);
return null;
}
// 添加预先存在的着色器
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.validateProgram(program);
// 是否编译成功
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.log('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));
gl.deleteProgram(program);
gl.deleteShader(fragmentShader);
gl.deleteShader(vertexShader);
return null;
}
return program;
}
- 加载着色器程序
Eshen.loadShader = function(type, source) {
// 创建一个新的着色器
const shader = gl.createShader(type);
if (!shader || !gl.isShader(shader)) {
return null;
}
gl.shaderSource(shader, source); // 将源代码发送到着色器
gl.compileShader(shader); // 编译一个GLSL着色器,使其成为为二进制数据
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
// 异常时删除着色器代码,释放连接着色器程序的内存
var error = gl.getShaderInfoLog(shader);
console.log('Failed to compile shader: ' + error);
gl.deleteShader(shader);
return null;
}
return shader;
}
- 初始化Buffer缓冲区
Eshen.initBuffer = function(vertices = new Float32Array([]), n, program) {
const vertexBuffer = gl.createBuffer();
if (!vertexBuffer) {
console.log('Failed to create the buffer object');
return false;
}
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); // 绑定缓冲区对象
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); // 将数据写入缓冲区对象
// attribute变量
const attributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
const attrArray = new Array(attributes);
for (let i = 0; i < attributes; ++i) {
const info = gl.getActiveAttrib(program, i);
attrArray[i] = gl.getAttribLocation(program, info.name);
if (attrArray[i] < 0) {
console.log(`Failed to get the storage location of ${info.name}`);
continue;
}
gl.vertexAttribPointer(attrArray[i], n, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(attrArray[i]);
}
// uniform变量
const uniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
const uniformArray = new Array(uniforms);
for (let i = 0; i < uniforms; ++i) {
const info = gl.getActiveUniform(program, i);
uniformArray[i] = gl.getUniformLocation(program, info.name);
if (uniformArray[i] < 0) {
console.log(`Failed to get the storage location of ${info.name}`);
}
}
return true;
}