跳至正文

轻量级绘图库NanoVG使用简介

开源项目地址:https://github.com/memononen/nanovg

一 NanoVG

NanoVG是一个跨平台、基于OpenGL的矢量图形渲染库。它非常轻量级,用C语言实现,代码不到5000行,非常精简地实现了一套HTML5 Canvas API,做为一个实用而有趣的工具集,用来构建可伸缩的用户界面和可视化效果。

二 使用

NanoVG API的设计完全基于HTML5 Canvas API。如果熟悉Canvas,很快就能掌握它的使用。

创建绘图上下文

绘图上下文通过平台特定的构造函数来创建,如果使用OpenGL 2.0后端,可以按以下方式创建:

#define NANOVG_GL2_IMPLEMENTATION // Use GL2 implementation.
#include "nanovg_gl.h"
...
struct NVGcontext* vg = nvgCreateGL2(NVG_ANTIALIAS | NVG_STENCIL_STROKES);

第一个参数用于定义创建渲染器的标志。

  • NVG_ANTIALIAS 表示渲染器会调整几何图形以包含抗锯齿。如果使用MSAA,则可以省略此标志。
  • NVG_STENCIL_STROKES 表示渲染器使用更高质量的渲染针对(重叠的)笔画。该质量在较宽的笔画上最为显著。如果追求速度,可以省略此标志。

目前NanoVG有一个OpenGL后端:nanovg_gl.h,支持OpenGL 2.0、OpenGL ES 2.0、OpenGL 3.2核心级和OpenGL ES 3。可根据需要选择。有关详细信息,请参阅头文件和示例。

注意:渲染目标必须具有模板缓冲区。

绘制形状

使用NanoVG绘制简单形状有四个步骤:1)开始一个新形状,2)定义要绘制的路径,3)设置填充或描边,4)最后填充或描边路径。

nvgBeginPath(vg);
nvgRect(vg, 100,100, 120,30);
nvgFillColor(vg, nvgRGBA(255,192,0,255));
nvgFill(vg);

调用nvgBeginPath()将清除任何现有路径,并从一个空白画布开始绘制。有许多函数可以定义要绘制的路径,例如矩形、圆角矩形和椭圆形,或者使用常见的moveTo,lineTo,bezierTo和arcTo 等API逐步组合路径。

理解复合路径

由于NanoVG中渲染后端的构建方式,绘制复合路径(即包含多个路径定义孔和填充的路径)需要进行更多的操作。NanoVG使用偶数/奇数填充规则,而默认情况下路径以逆时针顺序排列。在使用低级别的绘制API时要注意这一点。为了将预定义形状之一作为孔,应该在定义路径之后调用nvgPathWinding(vg,NVG_HOLE)nvgPathWinding(vg,NVG_CW)

nvgBeginPath(vg);
nvgRect(vg, 100,100, 120,30);
nvgCircle(vg, 120,120, 5);
nvgPathWinding(vg, NVG_HOLE);   // Mark circle as a hole.
nvgFillColor(vg, nvgRGBA(255,192,0,255));
nvgFill(vg);

OpenGL后端状态

OpenGL后端会影响以下状态:

当纹理被上传或更新时,以下像素存储将设置为默认值:GL_UNPACK_ALIGNMENTGL_UNPACK_ROW_LENGTHGL_UNPACK_SKIP_PIXELSGL_UNPACK_SKIP_ROWS。纹理绑定也会受到影响。当用户加载图像或添加新的字体字形时,可能会产生纹理更新。字形将在调用nvgBeginFrame()nvgEndFrame()之间根据需要添加。

整个帧的数据会在nvgEndFrame()中缓冲和刷新。以下代码说明了渲染代码所涉及的OpenGL状态:

glUseProgram(prog);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilMask(0xffffffff);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_ALWAYS, 0, 0xffffffff);
glActiveTexture(GL_TEXTURE0);
glBindBuffer(GL_UNIFORM_BUFFER, buf);
glBindVertexArray(arr);
glBindBuffer(GL_ARRAY_BUFFER, buf);
glBindTexture(GL_TEXTURE_2D, tex);
glUniformBlockBinding(... , GLNVG_FRAG_BINDING);

三 后记

NanoVG通常集成在一些渲染引擎中用来绘制2D文本,但它默认不支持字体阴影,如果想支持,需要下载一个NanoVG的扩展库,原始地址是:https://github.com/memononen/nanovg-ex,但目前已经找不到了。

标签:

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注