使用 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有何区别?
3209 2
|
C++ 芯片 编译器
STM32F103标准外设库—— 新建工程与库函数(四)
STM32F103标准外设库—— 新建工程与库函数(四)
664 0
STM32F103标准外设库—— 新建工程与库函数(四)
AC/DC电源模块设计原理、优化技术和应用案例三个方面进行阐述
AC/DC电源模块是一种将交流电转换成直流电的设备,广泛应用在各种电子设备中。其设计和优化是为了提高转换效率、降低功耗和提高性能稳定性。本文将从设计原理、优化技术和应用案例三个方面进行阐述。
AC/DC电源模块设计原理、优化技术和应用案例三个方面进行阐述
|
人工智能 编解码 算法
VideoFusion:开源视频处理神器!一键去黑边水印,AI提升画质+批量剪辑全搞定
VideoFusion 是一款开源的AI视频剪辑工具,支持自动去除视频黑边、水印和字幕,提供批量处理、画质提升等功能,适合视频创作者和自媒体运营者使用。
1695 3
|
Java Apache
Java 使用word模板创建word文档报告教程
Java 使用word模板创建word文档报告教程
1146 0
Java 使用word模板创建word文档报告教程
|
JavaScript
Vue中router路由的使用、router-link的使用(在项目中的实际运用方式)
这篇文章介绍了Vue中router路由和router-link的使用方式,包括router配置、router-link在模板中的使用,以及实现的导航菜单和页面路由效果。
Vue中router路由的使用、router-link的使用(在项目中的实际运用方式)
|
存储 缓存 编解码
【Uniapp 专栏】实用的 Uniapp 性能优化实战策略
【5月更文挑战第12天】本文介绍了提升Uniapp性能的实战策略,包括组件化开发、数据管理与缓存、页面加载优化、资源压缩、代码简化、网络请求优化、路由管理、内存监控、性能测试与监控以及结合平台特性。通过这些方法,可改善用户体验,实现应用性能的持续优化。
756 3
|
SQL Java 数据处理
实时计算 Flink版产品使用问题之使用MavenShadePlugin进行relocation并遇到只包含了Java代码而未包含Scala代码,该怎么办
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
存储 SQL 缓存
MySQL中间件ProxySQL介绍
ProxySQL 是一个高性能的SQL 代理。ProxySQL有一个高级多核体系结构。支持数十万并发连接,可以多路复用到后端服务器上。 作为守护进程运行。而且有一个进程监视这个守护进程,并在守护进程崩溃时重启守护进程,以减少停机时间。这个守护进程接受来自MySQL客户端的请求,并将其转发到后端的MySQL服务器上。 ProxySQL被设计为可以连续运行而且不需要重启。大多数配置可以在运行时使用类似SQL语句的查询完成。
2570 109
MySQL中间件ProxySQL介绍
elementUI el-tabs 实现动态选项卡页面效果
elementUI el-tabs 实现动态选项卡页面效果

热门文章

最新文章