技术的真相 | 使用 OpenGL 实现线型动画的教程来啦!

本文介绍了如何使用 OpenGL 实现线型动画,通过顶点着色器和片段着色器的配合,克服了传统绘制方法在复杂动画效果时的局限性。详细阐述了 OpenGL 的渲染管线,讲解了如何使用合成法向量绘制平滑折线,并引入局部坐标系统实现动画效果。文章还探讨了抗锯齿和局部坐标绘制圆环等技巧,提供了一种高效、跨平台的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

36c6600697566b43c3e262d35dfce4d1.png

在开发 UI 的时候,难免会遇到设计同学的奇思妙想超出了你的想象范围的情况。比如说,设计同学可能会让你画一个像下面这样不停运动的五角星动画:

db443e115c82278c5f12bdbc7eeeb800.gif

这样的线型动画也不只是为了好玩或者好看,在许多实用的领域比如监控图表或者 AI 可视化的过程中也可以发挥各种作用。

使用程序绘制这样的图形,通常会选择直接调用原生的绘制图像 API,比如 OpenCV 的 Drawing Functions,或者 Windows 下的 GDI/GDI+,或者 Web 下面的 Canvas 的绘制接口,或者 Android/iOS 相应的接口等等。

但对于前面图中这样的需求来说,需要在每一帧中计算需要绘制的线是哪些,从哪里开始到哪里结束,根据直线和曲线选用不同的 API,当线有一定宽度的时候,根据采用的 API 不同往往还会遇到转角的地方效果不尽如人意之类的情况,要实现图中的渐隐效果也会很困难。

写定代码之后,要调整曲线形状也很不容易(比如在五角星的尖上面增加一个小圆角),很可能需要推翻重写。实际运行起来时,还可能会发现因为计算过程过于复杂而产生性能问题。更不用说对于 Windows/Qt/Web/Android/iOS 等多个平台,代码是完全不通用的,极大增加了开发成本。

另一个方案是直接使用更为底层的绘图 API 来实现这样的效果,考虑到跨平台的需要,目前 OpenGL 仍然是一个比较稳妥的方案,尤其是许多设备上的浏览器只支持 WebGL 1.0,如果能在 WebGL 1.0(大约相当于 OpenGL ES 2.0)上仅使用 WebGL API 实现这种线型动画,那么绝大多数平台都可以使用相同的方案进行绘制,代码逻辑很容易迁移。本文介绍的就是这样一种方案。  

OpenGL 基础知识

OpenGL 接口的不同版本有一些很不同的特性,大体上按照固定管线、可编程管线、进一步扩展的可编程管线进行演进,这里按照 OpenGL ES 2.0 版本进行介绍,涉及到的特性基本上可以在目前主流的所有 OpenGL 平台(包括WebGL)上得到支持。

在 OpenGL ES 2.0 版本的可编程管线流程大致可以描述为:

顶点(vertex)数据 → 顶点着色器(vertex shader) → 顶点后处理 → 光栅化(rasterization) → 片段着色器(fragment shader) → 采样后处理

其中,可编程的部分主要指顶点着色器(vertex shader)和片段着色器(fragment shader)两部分,其他部分的功能相对固定。两种着色器使用被称为 GLSL 的编程语言编写,风格和 C 语言类似,主要控制输入数据经过怎样的运算之后得到输出数据,例如,一个简单的 OpenGL ES 2.0(WebGL 1.0)可用的顶点着色器可以如下编写:

 
 
 
 
precision highp float;
precision highp int;


attribute vec2 a_position;
uniform mat4 u_transform;
varying vec2 v_position;


void main(){
  gl_Position = u_transform * vec4(a_position, 0.0, 1.0);
  v_position = a_position;
}

它有一个二维向量类型的顶点属性(attribute)输入 a_position,同时有一个常量(uniform)输入 u_transform,类型是一个 4x4 的矩阵。它输出了 OpenGL 要求的顶点坐标 gl_Position,同时定义了一个输出给片段着色器的结果 v_position。向量被补充为四维齐次坐标向量之后,使用矩阵进行变换,得到的结果作为顶点着色器的输出(用 gl_开头的特定变量表示),同时原始的 a_position 被直接传递给了 v_position,方便在片段着色器里进一步处理。

着色器会针对每个要处理的单元运行一次,顶点着色器是对每个顶点执行一次,片段着色器则是对每个

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值