引言
WebGL(Web Graphics Library)是一种在网页上实现三维图形的JavaScript API。它允许开发者使用HTML5 Canvas元素在浏览器中创建和显示3D图形。对于想要在网页上展示动态、交互式3D内容的人来说,WebGL是一个非常有用的工具。本教程将为你提供10个实用的WebGL案例教程,帮助你从零开始,轻松上手WebGL。
案例一:绘制基本形状
在WebGL中,首先需要了解如何绘制基本形状,如点、线、三角形等。以下是一个简单的示例,展示如何使用WebGL绘制一个三角形。
// 初始化WebGL上下文
var canvas = document.getElementById('canvas');
var gl = canvas.getContext('webgl');
// 定义顶点数据
var vertices = new Float32Array([
0.0, 0.5, -0.5,
-0.5, -0.5, -0.5,
0.5, -0.5, -0.5
]);
// 创建缓冲区对象
var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
// 设置顶点着色器
var vertexShader = `
attribute vec3 position;
void main() {
gl_Position = vec4(position, 1.0);
}
`;
// 编译顶点着色器
var vertexShaderObject = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShaderObject, vertexShader);
gl.compileShader(vertexShaderObject);
// 设置片元着色器
var fragmentShader = `
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;
// 编译片元着色器
var fragmentShaderObject = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShaderObject, fragmentShader);
gl.compileShader(fragmentShaderObject);
// 创建程序对象
var program = gl.createProgram();
gl.attachShader(program, vertexShaderObject);
gl.attachShader(program, fragmentShaderObject);
gl.linkProgram(program);
gl.useProgram(program);
// 获取顶点位置变量
var positionLocation = gl.getAttribLocation(program, 'position');
gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(positionLocation);
// 绘制三角形
gl.drawArrays(gl.TRIANGLES, 0, 3);
案例二:绘制立方体
在了解了如何绘制基本形状后,接下来我们将学习如何绘制一个立方体。以下是一个示例,展示如何使用WebGL绘制一个立方体。
// 初始化WebGL上下文
var canvas = document.getElementById('canvas');
var gl = canvas.getContext('webgl');
// 定义顶点数据
var vertices = new Float32Array([
// 前面
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
// 后面
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
-1.0, 1.0, -1.0,
// 左面
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0,
// 右面
1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
// 上面
-1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
// 下面
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, -1.0, -1.0
]);
// 创建缓冲区对象
var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
// 设置顶点着色器
var vertexShader = `
attribute vec3 position;
void main() {
gl_Position = vec4(position, 1.0);
}
`;
// 编译顶点着色器
var vertexShaderObject = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShaderObject, vertexShader);
gl.compileShader(vertexShaderObject);
// 设置片元着色器
var fragmentShader = `
void main() {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
`;
// 编译片元着色器
var fragmentShaderObject = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShaderObject, fragmentShader);
gl.compileShader(fragmentShaderObject);
// 创建程序对象
var program = gl.createProgram();
gl.attachShader(program, vertexShaderObject);
gl.attachShader(program, fragmentShaderObject);
gl.linkProgram(program);
gl.useProgram(program);
// 获取顶点位置变量
var positionLocation = gl.getAttribLocation(program, 'position');
gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(positionLocation);
// 绘制立方体
gl.drawArrays(gl.TRIANGLES, 0, 36);
案例三:绘制球体
球体是三维图形中常见的形状之一。以下是一个示例,展示如何使用WebGL绘制一个球体。
// 初始化WebGL上下文
var canvas = document.getElementById('canvas');
var gl = canvas.getContext('webgl');
// 定义顶点数据
var vertices = new Float32Array([
// 球体顶点数据
]);
// 创建缓冲区对象
var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
// 设置顶点着色器
var vertexShader = `
attribute vec3 position;
void main() {
gl_Position = vec4(position, 1.0);
}
`;
// 编译顶点着色器
var vertexShaderObject = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShaderObject, vertexShader);
gl.compileShader(vertexShaderObject);
// 设置片元着色器
var fragmentShader = `
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;
// 编译片元着色器
var fragmentShaderObject = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShaderObject, fragmentShader);
gl.compileShader(fragmentShaderObject);
// 创建程序对象
var program = gl.createProgram();
gl.attachShader(program, vertexShaderObject);
gl.attachShader(program, fragmentShaderObject);
gl.linkProgram(program);
gl.useProgram(program);
// 获取顶点位置变量
var positionLocation = gl.getAttribLocation(program, 'position');
gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(positionLocation);
// 绘制球体
gl.drawArrays(gl.TRIANGLES, 0, vertices.length / 3);
案例四:绘制粒子系统
粒子系统是一种在三维场景中创建大量粒子的技术。以下是一个示例,展示如何使用WebGL绘制一个简单的粒子系统。
// 初始化WebGL上下文
var canvas = document.getElementById('canvas');
var gl = canvas.getContext('webgl');
// 定义顶点数据
var vertices = new Float32Array([
// 粒子顶点数据
]);
// 创建缓冲区对象
var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
// 设置顶点着色器
var vertexShader = `
attribute vec3 position;
void main() {
gl_Position = vec4(position, 1.0);
}
`;
// 编译顶点着色器
var vertexShaderObject = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShaderObject, vertexShader);
gl.compileShader(vertexShaderObject);
// 设置片元着色器
var fragmentShader = `
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;
// 编译片元着色器
var fragmentShaderObject = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShaderObject, fragmentShader);
gl.compileShader(fragmentShaderObject);
// 创建程序对象
var program = gl.createProgram();
gl.attachShader(program, vertexShaderObject);
gl.attachShader(program, fragmentShaderObject);
gl.linkProgram(program);
gl.useProgram(program);
// 获取顶点位置变量
var positionLocation = gl.getAttribLocation(program, 'position');
gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(positionLocation);
// 绘制粒子系统
gl.drawArrays(gl.POINTS, 0, vertices.length / 3);
案例五:绘制光照效果
光照效果是三维图形中非常重要的一部分。以下是一个示例,展示如何使用WebGL绘制一个具有光照效果的立方体。
// 初始化WebGL上下文
var canvas = document.getElementById('canvas');
var gl = canvas.getContext('webgl');
// 定义顶点数据
var vertices = new Float32Array([
// 立方体顶点数据
]);
// 创建缓冲区对象
var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
// 设置顶点着色器
var vertexShader = `
attribute vec3 position;
attribute vec3 normal;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform vec3 lightPosition;
void main() {
vec3 normal = normalize(normalMatrix * normal);
vec3 lightDir = normalize(lightPosition - position);
float diff = max(dot(normal, lightDir), 0.0);
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0) * diff;
}
`;
// 编译顶点着色器
var vertexShaderObject = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShaderObject, vertexShader);
gl.compileShader(vertexShaderObject);
// 设置片元着色器
var fragmentShader = `
void main() {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
`;
// 编译片元着色器
var fragmentShaderObject = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShaderObject, fragmentShader);
gl.compileShader(fragmentShaderObject);
// 创建程序对象
var program = gl.createProgram();
gl.attachShader(program, vertexShaderObject);
gl.attachShader(program, fragmentShaderObject);
gl.linkProgram(program);
gl.useProgram(program);
// 获取顶点位置变量
var positionLocation = gl.getAttribLocation(program, 'position');
gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(positionLocation);
// 获取法线变量
var normalLocation = gl.getAttribLocation(program, 'normal');
gl.vertexAttribPointer(normalLocation, 3, gl.FLOAT, false, 0, 12);
gl.enableVertexAttribArray(normalLocation);
// 设置模型视图矩阵和投影矩阵
var modelViewMatrix = mat4.create();
var projectionMatrix = mat4.create();
mat4.lookAt(modelViewMatrix, [0, 0, 5], [0, 0, 0], [0, 1, 0]);
mat4.perspective(projectionMatrix, glMatrix.toRadian(45), canvas.width / canvas.height, 0.1, 100.0);
// 设置光照位置
var lightPosition = [5.0, 5.0, 5.0, 1.0];
// 绘制立方体
gl.uniformMatrix4fv(gl.getUniformLocation(program, 'modelViewMatrix'), false, modelViewMatrix);
gl.uniformMatrix4fv(gl.getUniformLocation(program, 'projectionMatrix'), false, projectionMatrix);
gl.uniform3fv(gl.getUniformLocation(program, 'lightPosition'), lightPosition);
gl.drawArrays(gl.TRIANGLES, 0, vertices.length / 3);
案例六:绘制纹理映射
纹理映射是将二维图像映射到三维物体表面的技术。以下是一个示例,展示如何使用WebGL绘制一个具有纹理映射的立方体。
// 初始化WebGL上下文
var canvas = document.getElementById('canvas');
var gl = canvas.getContext('webgl');
// 定义顶点数据
var vertices = new Float32Array([
// 立方体顶点数据
]);
// 定义纹理坐标数据
var texCoords = new Float32Array([
// 立方体纹理坐标数据
]);
// 创建缓冲区对象
var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
var texCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, texCoords, gl.STATIC_DRAW);
// 设置顶点着色器
var vertexShader = `
attribute vec3 position;
attribute vec2 texCoord;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
varying vec2 vTexCoord;
void main() {
gl_Position = vec4(position, 1.0);
vTexCoord = texCoord;
}
`;
// 编译顶点着色器
var vertexShaderObject = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShaderObject, vertexShader);
gl.compileShader(vertexShaderObject);
// 设置片元着色器
var fragmentShader = `
varying vec2 vTexCoord;
uniform sampler2D texture;
void main() {
gl_FragColor = texture2D(texture, vTexCoord);
}
`;
// 编译片元着色器
var fragmentShaderObject = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShaderObject, fragmentShader);
gl.compileShader(fragmentShaderObject);
// 创建程序对象
var program = gl.createProgram();
gl.attachShader(program, vertexShaderObject);
gl.attachShader(program, fragmentShaderObject);
gl.linkProgram(program);
gl.useProgram(program);
// 获取顶点位置变量
var positionLocation = gl.getAttribLocation(program, 'position');
gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(positionLocation);
// 获取纹理坐标变量
var texCoordLocation = gl.getAttribLocation(program, 'texCoord');
gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(texCoordLocation);
// 加载纹理
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
var image = new Image();
image.src = 'path/to/texture.jpg';
image.onload = function() {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.bindTexture(gl.TEXTURE_2D, null);
};
// 设置模型视图矩阵和投影矩阵
var modelViewMatrix = mat4.create();
var projectionMatrix = mat4.create();
mat4.lookAt(modelViewMatrix, [0, 0, 5], [0, 0, 0], [0, 1, 0]);
mat4.perspective(projectionMatrix, glMatrix.toRadian(45), canvas.width / canvas.height, 0.1, 100.0);
// 绘制立方体
gl.uniformMatrix4fv(gl.getUniformLocation(program, 'modelViewMatrix'), false, modelViewMatrix);
gl.uniformMatrix4fv(gl.getUniformLocation(program, 'projectionMatrix'), false, projectionMatrix);
gl.drawArrays(gl.TRIANGLES, 0, vertices.length / 3);
案例七:绘制动画效果
动画效果是三维图形中非常重要的一部分。以下是一个示例,展示如何使用WebGL绘制一个具有动画效果的立方体。
”`javascript // 初始化WebGL上下文 var canvas = document.getElementById(‘canvas’); var gl = canvas.getContext(‘webgl’);
// 定义顶点数据 var vertices = new Float32Array([
// 立方体顶点数据
]);
// 创建缓冲区对象 var vertexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
// 设置顶点着色器 var vertexShader = `
attribute vec3 position;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;
// 编译顶点着色器 var vertexShaderObject = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShaderObject, vertexShader); gl.compileShader(vertexShaderObject);
// 设置片元着色器 var fragmentShader = `
void main() {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
`;
// 编译片元着色器 var fragmentShaderObject = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader