【WebGL实战】3. 让你绘制的2D图形动起来 - WebGL如何实现旋转与动画?

webGL硬核知识:图形渲染管渲染流程,各个阶段对应的API调用方式 顶点处理(Vertex Processing)阶段该阶段主要处理传入的顶点数据,包括顶点坐标、顶点颜色、法线向量等顶点相关的属性信息。进行的操作有坐标变换(例如将顶点从模型坐标系转换到世界坐标系、再到视图坐标系、裁剪坐标系等)以及对顶点属性进行必要的设置和计算等。例如,将一个 3D 模型中各个顶点的初始坐标通过平移、旋转、缩放等矩阵变换,使其放置到正确的空间位置,并且根据光照等需求计算顶点的光照属性(如果在顶点着色器中处理光照部分)。图元装配(Primitive Assembly)阶段。 阅读详情

大家好,我是 同学小张,+v: jasper_8017 一起交流,持续学习C++进阶、OpenGL、WebGL知识技能和AI大模型应用实战案例,持续分享,欢迎大家点赞+关注,共同学习和进步。


本文我们在 上篇文章:【WebGL实战】2. 给2D图形上色:颜色值应该如何传递给着色器? 的基础上,让矩形旋转起来。通过本文,我们将学会如何改变矩形的旋转角度,以及如何实现一个简单的动画效果。

参考:https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL_API/Tutorial/Animating_objects_with_WebGL

0. 如何改变矩形的旋转角度

改变矩形的位置和旋转角度,是通过模型矩阵来实现的。之前的代码,我们的模型矩阵只是将模型进行了平移操作,并没有进行旋转操作。

mat4.translate(
    modelViewMatrix, // destination matrix
    modelViewMatrix, // matrix to translate
    [-0.0, 0.0, -6.0]
); // amount to translate

现在,我们增加一个旋转角度,通过 mat4.rotate 函数来实现。rotate 的第三个参数为旋转的角度(弧度),这里我们给一个0.78,大概是45°。第四个参数是沿哪个轴旋转,这里我们选择[0, 0, 1],沿z轴旋转。z轴是垂直于屏幕的方向。

mat4.rotate(
    modelViewMatrix, // destination matrix
    modelViewMatrix, // matrix to rotate
    0.78, // amount to rotate in radians
    [0, 0, 1]
); // axis to rotate around

加入旋转后,运行代码,结果如下:

在这里插入图片描述

可以看到,矩形的旋转角度已经变成45°了。我们通过改变第三个参数值,也就能改变矩形的旋转角度。

所以,我们作以下改造:

(1)定义一个变量来存储这个旋转角度

let squareRotation = 0.0;

(2)旋转矩阵中将这个变量作为第三个参数

mat4.rotate(
    modelViewMatrix, // destination matrix
    modelViewMatrix, // matrix to rotate
    squareRotation, // amount to rotate in radians
    [0, 0, 1]
); // axis to rotate around

(3)传递这个 squareRotation 值给 drawScene

function drawScene(gl, programInfo, buffers, squareRotation)

squareRotation 值的计算,也是下面实现动画的关键。

1. 如何实现一个简单的动画效果

实现动画效果的思路很简单,就是每隔一段时间,改变矩形的旋转角度。当这个间隔足够小,就能实现比较流畅的动画效果。

(1)我们以时间间隔来作为变量,来计算旋转角度。

let deltaTime = 0;

......

now *= 0.001; // convert to seconds
deltaTime = now - then;
then = now;

......

squareRotation += deltaTime;

(2)接下来,就是让上面这个变量的计算循环起来

let then = 0;
// Draw the scene repeatedly
function render(now) {
    now *= 0.001; // convert to seconds
    deltaTime = now - then;
    then = now;

    drawScene(gl, programInfo, buffers, squareRotation);
    squareRotation += deltaTime;

    requestAnimationFrame(render);
}
requestAnimationFrame(render);

requestAnimationFrame 是一个浏览器提供的 API,它告诉浏览器你希望执行一个动画,并请求浏览器在下次重绘之前调用指定的函数来更新动画。这使得动画的渲染与浏览器的绘制循环同步,有助于实现平滑的动画效果。

使用 requestAnimationFrame 而不是 setTimeout 或 setInterval 的主要优势在于,它更精确地控制了动画的帧率,并考虑了页面的可见性、设备性能和其他可能影响渲染性能的因素。例如,如果页面被最小化或标签页被切换,浏览器可能会暂停或降低 requestAnimationFrame 的调用频率以节省资源。

2. 完整代码

完整js代码如下:

let squareRotation = 0.0;
let deltaTime = 0;

main();

// 从这里开始
function main() {
    const canvas = document.querySelector("#glcanvas");
    // 初始化 WebGL 上下文
    const gl = canvas.getContext("webgl");

    // 确认 WebGL 支持性
    if (!gl) {
        alert("无法初始化 WebGL,你的浏览器、操作系统或硬件等可能不支持 WebGL。");
        return;
    }
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);

    const vsSource = `
    attribute vec4 aVertexPosition;
    attribute vec4 aVertexColor;
    uniform mat4 uModelViewMatrix;
    uniform mat4 uProjectionMatrix;

    varying lowp vec4 vColor;
    void main() {
        gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
        vColor = aVertexColor;
    }
    `;

    const fsSource = `
    varying lowp vec4 vColor;

    void main() {
        gl_FragColor = vColor;
    }
    `;

    const shaderProgram = initShaderProgram(gl, vsSource, fsSource);
    const programInfo = {
        program: shaderProgram,
        attribLocations: {
            vertexPosition: gl.getAttribLocation(shaderProgram, "aVertexPosition"),
            vertexColor: gl.getAttribLocation(shaderProgram, "aVertexColor"),
        },
        uniformLocations: {
            projectionMatrix: gl.getUniformLocation(shaderProgram, "uProjectionMatrix"),
            modelViewMatrix: gl.getUniformLocation(shaderProgram, "uModelViewMatrix"),
        },
    };

    const buffers = initBuffers(gl);

    let then = 0;
    // Draw the scene repeatedly
    function render(now) {
        now *= 0.001; // convert to seconds
        deltaTime = now - then;
        then = now;

        drawScene(gl, programInfo, buffers, squareRotation);
        squareRotation += deltaTime;

        requestAnimationFrame(render);
    }
    requestAnimationFrame(render);
}

function initShaderProgram(gl, vsSource, fsSource) {
    const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
    const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);
    const shaderProgram = gl.createProgram();
    gl.attachShader(shaderProgram, vertexShader);
    gl.attachShader(shaderProgram, fragmentShader);
    gl.linkProgram(shaderProgram);
    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
      alert(
        `Unable to initialize the shader program: ${gl.getProgramInfoLog(
          shaderProgram
        )}`
      );
      return null;
    }
  
    return shaderProgram;
}

function loadShader(gl, type, source) {
    const shader = gl.createShader(type);
    gl.shaderSource(shader, source);
    gl.compileShader(shader);
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
      alert(
        `An error occurred compiling the shaders: ${gl.getShaderInfoLog(shader)}`
      );
      gl.deleteShader(shader);
      return null;
    }
  
    return shader;
}

function initBuffers(gl) {
    const positionBuffer = initPositionBuffer(gl);
    const colorBuffer = initColorBuffer(gl);

    return {
        position: positionBuffer,
        color: colorBuffer,
    };
}

function initColorBuffer(gl) {
    const colors = [
        1.0,
        1.0,
        1.0,
        1.0, // 白
        1.0,
        0.0,
        0.0,
        1.0, // 红
        0.0,
        1.0,
        0.0,
        1.0, // 绿
        0.0,
        0.0,
        1.0,
        1.0, // 蓝
    ];

    const colorBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);

    return colorBuffer;
}

function initPositionBuffer(gl) {
    const positionBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
    const positions = [1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0];
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
  
    return positionBuffer;
}

function drawScene(gl, programInfo, buffers, squareRotation) {
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.clearDepth(1.0);
    gl.enable(gl.DEPTH_TEST);
    gl.depthFunc(gl.LEQUAL);
  
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  
    const fieldOfView = (45 * Math.PI) / 180; // in radians
    const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
    const zNear = 0.1;
    const zFar = 100.0;
    const projectionMatrix = mat4.create();

    mat4.perspective(projectionMatrix, fieldOfView, aspect, zNear, zFar);
  
    const modelViewMatrix = mat4.create();
    mat4.translate(
        modelViewMatrix,
        modelViewMatrix,
        [-0.0, 0.0, -6.0]
    );

    mat4.rotate(
        modelViewMatrix,
        modelViewMatrix,
        squareRotation,
        [0, 0, 1]
    );

    setPositionAttribute(gl, buffers, programInfo);
    setColorAttribute(gl, buffers, programInfo);
    gl.useProgram(programInfo.program);
    gl.uniformMatrix4fv(
        programInfo.uniformLocations.projectionMatrix,
        false,
        projectionMatrix
    );
    gl.uniformMatrix4fv(
        programInfo.uniformLocations.modelViewMatrix,
        false,
        modelViewMatrix
    );
  
    {
        const offset = 0;
        const vertexCount = 4;
        gl.drawArrays(gl.TRIANGLE_STRIP, offset, vertexCount);
    }
}

function setPositionAttribute(gl, buffers, programInfo) {
    const numComponents = 2;
    const type = gl.FLOAT;
    const normalize = false;
    const stride = 0;
    const offset = 0;
    gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position);
    gl.vertexAttribPointer(
        programInfo.attribLocations.vertexPosition,
        numComponents,
        type,
        normalize,
        stride,
        offset
    );
    gl.enableVertexAttribArray(programInfo.attribLocations.vertexPosition);
}

function setColorAttribute(gl, buffers, programInfo) {
    const numComponents = 4;
    const type = gl.FLOAT;
    const normalize = false;
    const stride = 0;
    const offset = 0;
    gl.bindBuffer(gl.ARRAY_BUFFER, buffers.color);
    gl.vertexAttribPointer(
        programInfo.attribLocations.vertexColor,
        numComponents,
        type,
        normalize,
        stride,
        offset,
    );
    gl.enableVertexAttribArray(programInfo.attribLocations.vertexColor);
}

运行结果截图:

在这里插入图片描述

3. 总结

本文我们主要让矩形旋转了起来,首先是如何让矩形旋转,然后是如何实现一个简单的动画(循环)。

如果觉得本文对你有帮助,麻烦点个赞和关注呗 ~~~


  • 大家好,我是 同学小张,持续学习C++进阶、OpenGL、WebGL知识技能和AI大模型应用实战案例
  • 欢迎 点赞 + 关注 👏,持续学习,持续干货输出。
  • +v: jasper_8017 一起交流💬,一起进步💪。
  • 微信公众号搜【同学小张】 🙏

本站文章一览:

在这里插入图片描述

WebGL实战:尤达大师3D模型与动画演示 本文还有配套的精品资源,点击获取 简介:WebGL是一种无需插件即可在Web浏览器中渲染三维图形的JavaScript API。本项目深入探讨了WebGL、3D建模以及如何在Web环境中实现动态模型。内容涵盖WebGL基础、3D建模过程、动画实现、模型加载显示、交互性和性能优化等多个方面,通过尤达大师的3D模型及动画展示了WebGL的强大功能。 1. WebGL基... 阅读详情

相关推荐

WebGL长方体动态变换项目:旋转与缩放

WebGL(Web Graphics Library)是一种JavaScript API,它提供了一个用于在任何兼容的Web浏览器中无需插件就可以进行3D和2D图形渲染的标准方式。它将OpenGL ES 2.0的标准应用到了网页中,使得开发者能够在网页上绘制出复杂的图形。在现实世界中,要观察一个物体,需要一个相机或眼睛作为观察的起点。在WebGL中,虚拟相机用于定义观察世界的方式,它包含位置、朝向和视野范围等属性。虚拟相机的重要性在于,它决定了用户的观察视角,影响了3D场景的视觉效果和用户的交互体验。

weixin_42590539的博客 1244

使用 WebGL 创建 2D 内容

一旦创建 WebGL 上下文创建成功,你就可以在这个上下文里渲染画图了。而对我们而言最简单的事,莫过于绘制一个没有纹理的 2D 图形了。那就让我们从画出一个正方形开始吧。

qq_25547755的博客 1188

html5 WebGL酷炫网页动画特效

6款html5 WebGL酷炫网页动画特效,结合TweenMax、Three.js创建形状,打造出各种动画效果都十分的好看。

WebGL笔记: 2D和WebGL坐标系对比和不同的画图方式, 程序对象通信,顶点着色器,片元着色器

/ 功能:解析着色器文本,整合到程序对象里,关联webgl上下文对象,实现两种语言的相互通信。// 获取着色器文本,这里就是上述我们写的GLSL ES语言着色器代码。// 设置点位, 注意webgl坐标系中的单位。// 绘制顶点 以点来画。工具脚本 util.js。

Wang的专栏 862

Java实现双色球&大乐透随机选号算法——原理详解与代码实战

掌握核心语法:集合操作、随机数生成、排序。贴近实际场景:将编程知识应用于生活问题的解决。

wangchl0932的博客 4952

centos7部署mysql8.0.35,主从复制,主主集群

centos7 linux部署mysql,主从复制,主主模式

zaixiaqin的博客 1980

live2D学习:做好让图片动起来的准备

做好让图片动起来的准备把psd文件通过菜单栏的“打开文件”进行导入或直接把psd文件拖到Live2D Cubism Editor 4.0的面板中。

热爱音乐和二次元! 1677

中小团队必看!用Harbor+Jenkins打造轻量级K3S交付流水线(含成本优化方案)

本文为中小团队详细介绍了如何利用K3S、Harbor与Jenkins构建一套高性价比的自动化交付流水线。内容涵盖单节点K3S集群的效能配置、Harbor镜像仓库的磁盘空间优化、Jenkins共享库实现流水线复用,并提供了完整的实战案例与成本优化方案,帮助团队以较低成本快速落地高效的自动化部署。

weixin_29223603的博客 499

WebGL2 Shader实现的动态图形效果

本文将介绍如何使用WebGL2创建一个动态的图像效果,该效果基于一个经典的着色器。我们将使用JavaScript和GLSL编写代码,并通过使用顶点着色器和片段着色器将其传递给WebGL上下文。通过学习这个例子,你将了解一些基本的WebGL概念,如着色器编程、顶点缓冲区和Uniform变量。在本文中,我们首先创建一个用于渲染的canvas元素并获取WebGL上下文。然后,我们设置一些基本的样式和初始化参数。接下来,我们编写顶点着色器和片段着色器的源代码,并将其编译为WebGL着色器对象。

全栈若城,专注知识分享 943

TeXstudio完整安装配置教程(2025最新版)

至此,你已经完成了TeXstudio的完整安装和配置!现在你可以:✅ 使用TeXstudio编写LaTeX文档✅ 正确编译中英文混排的文档✅ 掌握基本的编辑和配置技巧LaTeX的学习曲线较陡,但一旦掌握,你会发现它在学术写作中的强大之处。建议从简单的文档开始练习,逐步掌握更高级的功能。祝你LaTeX写作顺利!如果有任何问题,欢迎在评论区留言交流。关键词:TeXstudio安装、LaTeX环境配置、中文LaTeX、TeX Live、学术论文写作更新日期:2025年10月。

weixin_51241407的博客 4464

基于YOLOv10的微小目标检测,多头检测器提升小目标检测精度

引入多头检测器助力YOLOv10,暴力提升小目标检测性能

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 2561

Web---2D&3D 转换与动画

一、字体图标一、字体图标目的:使用字体图标技巧实现网页中简洁图标效果1.iconfont的使用1)iconfont的网址2)生成iconfont文件,导入到项目a.创建项目b.创建好项目c.选择自己要使用的图标,点击上面的购物车d.点击购物车添加到项目e.在我的项目中点击下载到本地f. 下载完成以后就会有如下的文件,导入到项目中使用就可以2.购物车案例a.使用link的方式导入iconfont.css文件。

qq_43658148的博客 485

C#实战:从零搭建Vosk离线语音转文字系统

本文手把手教你用C#构建离线语音转文字系统,基于NAudio和Vosk实现全流程开发。首先介绍环境搭建,包括NuGet包安装和中文模型配置,强调16kHz单声道音频格式的关键性。接着详细解析音频预处理转换、Vosk模型初始化及识别过程的核心代码,提供多线程优化建议和实时识别扩展思路。文章包含80%以上代码注释,从常见问题排查到性能优化技巧,完整覆盖从"Hello World"到工业级部署的关键技术点,特别适合需要开发本地化语音识别应用的C#开发者。

墨夶的博客 748

第 3 篇:让图形动起来 - WebGL 2D 变换

本文介绍了如何通过矩阵变换实现WebGL图形的动态效果。核心思路是使用3x3变换矩阵(平移、旋转、缩放)来控制图形位置,而非直接修改顶点坐标。主要技术点包括: 在顶点着色器中添加mat3类型的uniform变量接收变换矩阵 将原始顶点坐标与变换矩阵相乘得到新坐标 在JavaScript中实现基本矩阵运算函数 通过requestAnimationFrame创建动画循环,持续更新旋转角度并重绘 这种方法充分利用GPU的矩阵运算优势,相比直接修改顶点坐标更高效,是图形编程的标准做法。最终实现了一个在画布中心持续旋

waws520的博客 1172

【精细解读】xapp585(多通道LVDS接口ADC)

xapp585的参考设计有Verilog和VHDL两种源码。

FPGA艺术家的博客 526

Agent Harness Engineering: AI Agent 执行管控与安全沙箱 原理与最佳实践

我们正站在计算范式转移的历史节点上。2024-2026 年间,AI 系统从被动的内容生成器(Generative AI)演变为主动的行动执行者(Agentic AI)。这一转变的根本特征是:根据 2026 年初的行业数据:然而,能力的提升伴随着风险的指数级增长。2024-2026 年间发生的多起标志性安全事件揭示了 Agent 系统的脆弱性:案例 1:Slack AI 数据外泄事件(2024 年 8 月)案例 2:制造业供应链攻击(2026 年 Q3)案例 3:Arup 深度诈骗案(2026 年 9 月)这

AI天才研究院 1652

WebGL系列教程七(二维及三维旋转、平移、缩放)

上一篇我们讲了如何进行立方体的纹理贴图,为了方便立方体的贴图后效果的展示,我们对立方体进行了旋转,但代码中并没有进行体现,这一节我们来讲讲旋转、平移、缩放。实际上,在WebGL中进行旋转、平移、缩放只需要乘以相应的旋转、平移、缩放矩阵即可。本文我们通过梳理二维及三维的旋转、平移、缩放矩阵,搞明白了旋转、平移、缩放对应的矩阵,并在WebGL中进行了实验操作,实现了一个立方体的旋转。本文在理解上有一定的难度,尤其是矩阵的变换,需要读者具有一定的线性代数知识,希望读者仔细体会,回见~

AIGIS的博客 1691

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

可视化学习:如何用WebGL绘制3D物体

至此,我们就实现了正立方体的绘制。在3D物体的绘制中,正立方体属于是比较简单的一类,屏幕前的小伙伴们都可以来动手尝试下,感兴趣的小伙伴,还可以尝试去实现圆柱体、正四面体等等这些几何体的绘制。beckyye引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构。

sdgfafg_25的博客 1399

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

WebGL入门绘制、矩阵平移和旋转

WebGL(Web Graphics Library)是一种用于在网页上渲染交互式3D和2D图形的JavaScript API。它不需要任何插件,直接利用电脑的GPU(图形处理器)来加速渲染,是现代浏览器进行游戏开发、数据可视化和三维建模的基石。核心优势:原生集成:与HTML5、Canvas和DOM完美结合。硬件加速:直接调用GPU,性能极高。跨平台:只要浏览器支持,Windows、macOS、Linux乃至移动端均可运行。

qq_28372005的博客 667

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

webgl canvas系列——animation中基本旋转、平移、缩放(模拟冒泡排序过程)

大家好,我是yma16,本文分享webgl canvas系列——animation基本旋转、平移、缩放。

编程知识分享,主打前端 1万+

【愚公系列】2023年12月 WEBGL专题-canvas和webgl的区别

Canvas是一个HTML5元素,可以用于在网页上绘制图形。它可以让开发者使用JavaScript绘制图形和动画,以及实现图形交互。Canvas可以帮助开发者创建交互式的游戏、图表、图像编辑工具等应用程序。Canvas的作用如下:动态绘制图形:开发者可以使用JavaScript动态地绘制图形,包括线条、圆形、矩形、多边形等。动画效果:开发者可以使用JavaScript实现动画效果,例如展示图表数据变化、添加滑动特效等。图像处理:开发者可以使用Canvas进行图像处理,例如对图像进行裁剪、缩放、旋转等操作。游

愚公智库 1万+

WebGL教程(电子书)

WebGL教程(电子书) 最近准备编写一本WebGL快速入门的电子书教程,电子书编写完整后,会免费开源到我的个人技术博客,目前还在编写中,已经写好的会把电子书每一小节以文章的形式发布才CSDN上。 第一章、WebGL零基础入门 1.1 WebGL绘制一个点—第一个程序 1.2 更新中 ...

u014291990的博客 8159

PixiJS - 最快、最灵活的 2D WebGL 渲染引擎

最近还整理一份JavaScript与ES的笔记,一共25个重要的知识点,对每个知识点都进行了讲解和分析。能帮你快速掌握JavaScript与ES的相关知识,提升工作效率。有需要的小伙伴,可以点击下方卡片领取,无偿分享。

小陈的博客 4696

【Web2D/3D】CSS3的2D/3D转换transform、过渡transistion、关键帧动画animation(第一篇)

本篇开始介绍Web2D和3D相关基础知识,会从CSS3的2D/3D转换、过渡、动画,讲到Canvas 2D图形绘制,再到SVG,最后到WebGL。

weixin_45620943的博客 1667

WebGL 之创建 2D 内容

它的职责是确定像素的颜色,通过指定应用到像素的纹理元素(也就是图形纹理中的像素),获取纹理元素的颜色,然后将适当的光照应用于颜色。在观察者视图空间中,观察者(通常是摄像机)位于坐标系的原点,观察方向是坐标系的负Z轴方向,摄像机的朝向和位置决定了观察者视图空间的坐标系。:在顶点着色器中,顶点数据经过模型变换、视图变换和投影变换后,得到的坐标被称为裁剪空间坐标。这个范围内的坐标表示的是相对于视锥体(View Frustum)的位置,超出这个范围的坐标将被裁剪掉,不会显示在最终的图像中。

qq_35094120的博客 1084

如何学习前端图形编程(如Canvas、WebGL)?

前端图形编程,特别是利用Canvas 2D、WebGL和新兴的WebGPU技术,为开发者打开了一扇通往丰富视觉世界的大门。本报告旨在为不同经验水平的学习者提供一条从入门到精通的系统化、结构化的学习路径,分析核心技术、主流工具以及未来的发展趋势。元素上进行绘制的,但它提供的是一个基于OpenGL ES的3D渲染上下文。掌握了框架的基本使用后,深入理解WebGL的高级特性将使你的作品效果和性能都提升一个档次。在踏上图形编程的征程之前,坚实的基础和正确的学习心态是成功的关键。WebGL本质上是在。

破损的天堂鸟博客 954
上一篇: 【AI Agent系列】【阿里AgentScope框架】AgentScope中的RAG实现思路(一)之 LangChainRAG
下一篇: 【AI Agent系列】【阿里AgentScope框架】AgentScope中的RAG实现思路(二)之 LlamaIndexRAG
同学小张
博客等级 码龄12年 1万+粉丝 284原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

同学小张

如果觉得有帮助,欢迎给我鼓励!

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

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

打赏作者

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

抵扣说明:

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

余额充值