使用 WebGL 创建 3D 动画

简介: 【10月更文挑战第3天】使用 WebGL 创建 3D 动画

使用 WebGL 创建 3D 动画

WebGL 是一种用于渲染交互式 3D 图形的标准,它不需要任何插件就能在现代浏览器中运行。本文将介绍如何使用 WebGL 和 JavaScript 来创建一个简单的旋转立方体动画。

1. 设置基本的 HTML 结构

首先,我们需要创建一个 HTML 文件,包含一个 <canvas> 元素来显示 WebGL 渲染的内容。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebGL Cube</title>
    <style>
        body {
     margin: 0; }
        canvas {
     width: 100%; height: 100vh; display: block; }
    </style>
</head>
<body>
    <canvas id="cubeCanvas"></canvas>
    <script src="webgl-cube.js"></script>
</body>
</html>

2. 初始化 WebGL 上下文

接下来,在 webgl-cube.js 文件中,我们需要初始化 WebGL 上下文,并设置一些基本的属性。

const canvas = document.getElementById('cubeCanvas');
const gl = canvas.getContext('webgl');

if (!gl) {
   
    console.error('Unable to initialize WebGL. Your browser may not support it.');
}

// 设置视口大小
gl.viewport(0, 0, canvas.width, canvas.height);

// 清除颜色
gl.clearColor(0.0, 0.0, 0.0, 1.0);

// 清除深度缓冲区
gl.clearDepth(1.0);

// 开启深度测试
gl.enable(gl.DEPTH_TEST);

3. 创建顶点着色器和片段着色器

为了绘制3D图形,我们需要定义顶点着色器和片段着色器。这两个着色器负责处理顶点数据和像素着色。

function createShader(gl, type, source) {
   
    const shader = gl.createShader(type);
    gl.shaderSource(shader, source);
    gl.compileShader(shader);
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
   
        console.error(gl.getShaderInfoLog(shader));
        gl.deleteShader(shader);
        return null;
    }
    return shader;
}

const vertexShaderSource = `
attribute vec4 a_position;
void main() {
    gl_Position = a_position;
}`;

const fragmentShaderSource = `
precision mediump float;
void main() {
    gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}`;

4. 编译着色器并创建着色器程序

编译着色器并创建一个着色器程序,该程序将用于渲染。

const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);

const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);

if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
   
    console.error("Unable to initialize the shader program.");
}

gl.useProgram(program);

5. 定义几何体数据

为了绘制一个立方体,我们需要定义它的顶点坐标。

const positions = [
    // 前面
    -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
];

const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

const positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 3, gl.FLOAT, false, 0, 0);

6. 绘制立方体

最后,我们需要一个函数来绘制立方体,并让它旋转起来。

let angle = 0;

function drawScene() {
   
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    const matrix = mat4.create();
    mat4.rotateX(matrix, matrix, degToRad(angle));
    mat4.rotateY(matrix, matrix, degToRad(angle));

    const u_matrix = gl.getUniformLocation(program, "u_matrix");
    gl.uniformMatrix4fv(u_matrix, false, matrix);

    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 36);

    requestAnimationFrame(drawScene);
}

function degToRad(degrees) {
   
    return degrees * Math.PI / 180;
}

angle += 0.5;
requestAnimationFrame(drawScene);

以上代码创建了一个旋转的3D立方体。你可以在此基础上扩展,添加更多的几何体、纹理或者光照效果。WebGL 是一个强大的工具,通过它你可以创建出非常丰富的3D体验。

相关文章
|
消息中间件 安全 Kafka
一文搞懂Kafka中的listeners配置策略
1. listeners中的plaintext controller external是什么意思? 2. Kraft模式下controller和broker有何区别? 3. 集群节点之间同步什么数据,通过哪个端口,是否可以自定义端口? 4. 客户端通过哪个端口连接到kafka,通过9092连接的是什么,broker还是controller? 5. 为controller配置了单独的端口有什么用? 6. control.plane.listener.name与controller.listener.names有何区别?
2566 2
|
虚拟化 Windows
解决Enable-WindowsOptionalFeature : 功能名称 Microsoft-Hyper-V 未知。
解决Enable-WindowsOptionalFeature : 功能名称 Microsoft-Hyper-V 未知。
3321 0
解决Enable-WindowsOptionalFeature : 功能名称 Microsoft-Hyper-V 未知。
|
11月前
|
缓存 JavaScript 开发者
网页离线缓存 Service Worke
网页离线缓存 Service Worke
325 4
|
11月前
|
运维 负载均衡 安全
深度解析:Python Web前后端分离架构中WebSocket的选型与实现策略
深度解析:Python Web前后端分离架构中WebSocket的选型与实现策略
306 0
|
8月前
html5+svg太空人404动画模板源码
html5+svg太空人404动画模板源码
99 17
|
存储 缓存 JavaScript
npm link 与 pnpm link 的用法以及不同之处
npm link 与 pnpm link 的用法以及不同之处
1054 0
|
JavaScript
Vue中router路由的使用、router-link的使用(在项目中的实际运用方式)
这篇文章介绍了Vue中router路由和router-link的使用方式,包括router配置、router-link在模板中的使用,以及实现的导航菜单和页面路由效果。
Vue中router路由的使用、router-link的使用(在项目中的实际运用方式)
|
存储 缓存 编解码
【Uniapp 专栏】实用的 Uniapp 性能优化实战策略
【5月更文挑战第12天】本文介绍了提升Uniapp性能的实战策略,包括组件化开发、数据管理与缓存、页面加载优化、资源压缩、代码简化、网络请求优化、路由管理、内存监控、性能测试与监控以及结合平台特性。通过这些方法,可改善用户体验,实现应用性能的持续优化。
560 3
|
JSON API 数据库
Django的web框架Django Rest_Framework精讲(一)
Django的web框架Django Rest_Framework精讲(一)
482 1
elementUI el-tabs 实现动态选项卡页面效果
elementUI el-tabs 实现动态选项卡页面效果