WebGL(Web Graphics Library)是一种JavaScript API,用于在任何兼容的Web浏览器中进行硬件加速的3D图形渲染,无需插件。它基于OpenGL标准,直接集成到HTML5的Canvas元素中。WebGL使得开发者能够在网页上实现复杂的3D视觉效果。
Three.js是一个流行的JavaScript库,它封装了WebGL的复杂性,提供了一个更易用的接口来创建3D内容。Three.js简化了许多WebGL的底层工作,如顶点缓冲、着色器管理、纹理加载等,让开发者能够专注于构建3D场景和交互。
Three.js创建基本3D场景基本步骤
1. 设置HTML结构:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Three.js Example</title>
<script src="https://cdn.jsdelivr.net/npm/three@0.137.0/build/three.min.js"></script>
</head>
<body>
<script>
// JavaScript代码将放在这里
</script>
</body>
</html>
这里引入了Three.js库的CDN链接。
2. 初始化场景、相机和渲染器:
const scene = new THREE.Scene(); // 创建场景
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); // 创建透视相机
const renderer = new THREE.WebGLRenderer(); // 创建渲染器
renderer.setSize(window.innerWidth, window.innerHeight); // 设置渲染器大小
document.body.appendChild(renderer.domElement); // 将渲染结果添加到页面
场景(Scene)是所有3D对象的容器,相机(Camera)定义了观察3D世界的视角,而渲染器(Renderer)负责将场景呈现到屏幕。
3. 创建3D对象:
const geometry = new THREE.BoxGeometry(1, 1, 1); // 创建一个立方体几何体
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); // 创建基本材质,颜色为绿色
const cube = new THREE.Mesh(geometry, material); // 创建一个网格(Mesh)对象,组合了几何体和材质
scene.add(cube); // 添加到场景
这里创建了一个基本的立方体网格对象。
4. 动画循环:
function animate() {
requestAnimationFrame(animate); // 为了每帧都更新,使用requestAnimationFrame
cube.rotation.x += 0.01; // 更新立方体的旋转
cube.rotation.y += 0.01;
renderer.render(scene, camera); // 渲染场景
}
animate(); // 启动动画
动画循环通过requestAnimationFrame
来实现,每一帧更新立方体的旋转角度并重新渲染。
5. 光照和着色器:
Three.js支持多种光源和自定义着色器,可以为3D对象添加复杂光照效果和自定义表面外观。
6. 交互性:
可以通过监听鼠标和触摸事件来实现对3D对象的交互,例如拖动、缩放、旋转等。
7. 纹理和材质:
通过加载图像文件,可以为3D对象添加纹理,增加视觉真实感。
8. 加载3D模型:
Three.js还支持加载外部3D模型文件,如.obj、.gltf等格式。
9. 动画和关键帧:
THREE.AnimationMixer
可用于创建复杂的动画序列,通过关键帧控制3D对象的各种属性。THREE.KeyframeTrack
用于定义特定时间点上的属性值。THREE.AnimationClip
用于组合多个关键帧轨道,形成一个完整的动画片段。
10. 相机控制器:
- Three.js 提供了多种相机控制器,如
OrbitControls
、FirstPersonControls
等,方便用户在3D空间中平移、旋转和缩放相机视角。
11. 光照系统:
THREE.PointLight
、THREE.DirectionalLight
、THREE.SpotLight
和THREE.AmbientLight
分别表示点光源、平行光、聚光灯和环境光。THREE.LightShadow
可以给光源添加阴影效果。
12. 粒子系统:
THREE.ParticleSystem
和THREE.Points
可用于创建粒子效果,如烟雾、火花、雨滴等。- 配合
THREE.Geometry
和THREE.PointsMaterial
可以定制粒子的形状和外观。
13. 纹理映射:
THREE.TextureLoader
用于加载纹理图像。THREE.CubeTextureLoader
用于加载立方体贴图,常用于环境映射。THREE.VideoTexture
可以将视频作为3D对象的纹理。
14. 几何形状:
- 除了基本的几何形状(如BoxGeometry、SphereGeometry等),Three.js还支持创建更复杂的几何形状,如圆环、圆柱、圆锥等。
- 通过
THREE.Geometry.merge()
方法,可以合并多个几何体。
15. 物理引擎集成:
通过第三方库(如 Cannon.js 或 Ammo.js),可以将物理模拟(如碰撞检测、重力等)引入到Three.js场景中。
16. 自定义着色器:
Three.js 支持 GLSL(OpenGL Shading Language)着色器,允许开发者编写自定义的顶点和片段着色器,实现复杂的光照和表面效果。
17. WebVR 和 WebXR:
对于虚拟现实(VR)和增强现实(AR)的支持,Three.js 提供了 WebVRManager
和 WebXRManager
,以便在兼容的设备上创建沉浸式体验。
Three.js创建3D应用实例
使用Three.js创建一个基本3D立方体应用的示例代码,包括设置场景、相机、渲染器、几何体、材质和动画循环:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Three.js 3D Cube Example</title>
<style>
body { margin: 0; }
canvas { display: block; }
</style>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/three@0.137.0/build/three.min.js"></script>
<script>
// 初始化场景、相机和渲染器
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 创建立方体几何体和材质
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
// 创建立方体网格对象
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
// 设置相机位置
camera.position.z = 5;
// 动画循环
function animate() {
requestAnimationFrame(animate); // 每帧都更新
cube.rotation.x += 0.01; // 旋转立方体
cube.rotation.y += 0.01;
renderer.render(scene, camera); // 渲染场景
}
animate(); // 开始动画
</script>
</body>
</html>
1. 引入Three.js库:
通过CDN引入Three.js的最新版本,这里使用的是v0.137.0。
2. 创建场景、相机和渲染器:
THREE.Scene
是所有3D对象的容器。THREE.PerspectiveCamera
创建一个透视相机,参数分别是视场角、宽高比、近裁剪平面和远裁剪平面。THREE.WebGLRenderer
创建渲染器,设置渲染器的尺寸,并将其添加到HTML页面中。
3. 创建立方体:
THREE.BoxGeometry
创建一个单位立方体几何体。THREE.MeshBasicMaterial
创建一个基本材质,颜色设为绿色。THREE.Mesh
将几何体和材质组合成一个可渲染的网格对象。
4. 设置相机位置:
将相机的Z轴位置设置为5,这样可以从侧面看到立方体。
5. 动画循环:
requestAnimationFrame(animate)
用于在浏览器准备好下一次绘制时调用animate函数,创建平滑的动画效果。- 在
animate
函数中,立方体的X和Y旋转角度每帧都会增加,导致立方体旋转。 renderer.render(scene, camera)
渲染场景,使用当前相机视角。
WebGL创建3D应用
WebGL创建3D应用通常涉及多个步骤,包括设置上下文、创建几何体、定义材质、配置相机、设置光照和渲染循环。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WebGL 3D Cube</title>
<style>
canvas {
display: block;
margin: auto;
width: 80%;
height: 80%;
}
</style>
</head>
<body>
<canvas id="gl-canvas"></canvas>
<script>
const canvas = document.getElementById('gl-canvas');
const gl = canvas.getContext('webgl');
if (!gl) {
alert('Your browser does not support WebGL.');
return;
}
// 定义立方体的顶点坐标
const vertices = [
-1, -1, -1, // 0
1, -1, -1, // 1
1, 1, -1, // 2
-1, 1, -1, // 3
-1, -1, 1, // 4
1, -1, 1, // 5
1, 1, 1, // 6
-1, 1, 1 // 7
];
// 定义立方体的面
const indices = [
// Front face
0, 1, 2,
0, 2, 3,
// Back face
4, 7, 6,
4, 6, 5,
// Top face
3, 2, 6,
3, 6, 7,
// Bottom face
0, 4, 5,
0, 5, 1,
// Right face
1, 5, 6,
1, 6, 2,
// Left face
4, 0, 3,
4, 3, 7
];
// 创建顶点缓冲
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
// 创建索引缓冲
const indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
// 定义顶点着色器
const vertexShaderSource = `
attribute vec3 aVertexPosition;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
void main(void) {
gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aVertexPosition, 1.0);
}
`;
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);
// 定义片段着色器
const fragmentShaderSource = `
void main(void) {
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); // Green color
}
`;
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);
// 创建程序
const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
gl.useProgram(shaderProgram);
// 绑定顶点位置属性
const positionAttributeLocation = gl.getAttribLocation(shaderProgram, 'aVertexPosition');
gl.enableVertexAttribArray(positionAttributeLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.vertexAttribPointer(positionAttributeLocation, 3, gl.FLOAT, false, 0, 0);
// 编译并设置矩阵
const modelViewMatrixLocation = gl.getUniformLocation(shaderProgram, 'uModelViewMatrix');
const projectionMatrixLocation = gl.getUniformLocation(shaderProgram, 'uProjectionMatrix');
const aspect = canvas.clientWidth / canvas.clientHeight;
const fieldOfView = Math.PI * 0.6;
const near = 0.1;
const far = 100.0;
const projectionMatrix = mat4.perspective(mat4.create(), fieldOfView, aspect, near, far);
const modelViewMatrix = mat4.create();
function drawScene() {
gl.viewport(0, 0, canvas.width, canvas.height);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.enable(gl.DEPTH_TEST);
// 旋转立方体
mat4.translate(modelViewMatrix, modelViewMatrix, [0.0, 0.0, -5.0]);
mat4.rotate(modelViewMatrix, modelViewMatrix, Date.now() * 0.001, [0, 1, 0]);
gl.uniformMatrix4fv(projectionMatrixLocation, false, projectionMatrix);
gl.uniformMatrix4fv(modelViewMatrixLocation, false, modelViewMatrix);
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
}
drawScene();
setInterval(drawScene, 1000 / 60); // 60 FPS animation
</script>
</body>
</html>