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

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计算机入门到高级架构师开发资料超级大礼包免费送!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天涯学馆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值