WebGL与Three.js:3D图形在Web上的应用

天涯学馆 2024-07-01 10:33:28 阅读 68

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 提供了多种相机控制器,如 OrbitControlsFirstPersonControls 等,方便用户在3D空间中平移、旋转和缩放相机视角。

11. 光照系统:

THREE.PointLightTHREE.DirectionalLightTHREE.SpotLightTHREE.AmbientLight 分别表示点光源、平行光、聚光灯和环境光。THREE.LightShadow 可以给光源添加阴影效果。

12. 粒子系统:

THREE.ParticleSystemTHREE.Points 可用于创建粒子效果,如烟雾、火花、雨滴等。配合 THREE.GeometryTHREE.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 提供了 WebVRManagerWebXRManager,以便在兼容的设备上创建沉浸式体验。

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>

2500G计算机入门到高级架构师开发资料超级大礼包免费送!



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。