added vulkan build, and cmake files, removed premake4.lua
2021 update - fixed all errors, this code has no Validation errors and work correctly everywhere.
Thanks to @fzwoch commits by default used TOPOLOGY_TRIANGLE_LIST
, because TOPOLOGY_TRIANGLE_FAN
is optional in Vulkan.
To enable TOPOLOGY_TRIANGLE_FAN edit src/nanovg_vk.h
and set there #define USE_TOPOLOGY_TRIANGLE_FAN
Why I made this - I made it as a "test task for Vulkan related job" a year ago, for me this project has no real use. I would recommend for everyone use imgui if you look for production-ready Vulkan UI. I will not support or update this project at all, the last update was just to fix bugs and Validation errors.
Contact: Join discord server
Build:
build with glfw:
cd build_vulkan
cp -r ../example example
git clone https://github.com/glfw/glfw
mkdir build
cd build
cmake ../
make
glfw used only to get Vulkan surface and Mouse input.
Depth order bug on AMD - I test myself on Nvidia and AMD and have not seen any depth-bugs. But on some AMD videocards depth bugged. I can not test my self so I can not fix it. I dont see any "logical error" myself. Screenshot from Vulkan version of this build on AMD GPU, elements draw in the same order as in OpenGL. Should by fixed by 6ee1009.
This project is not actively maintained.
NanoVG is small antialiased vector graphics rendering library for OpenGL. It has lean API modeled after HTML5 canvas API. It is aimed to be a practical and fun toolset for building scalable user interfaces and visualizations.
The NanoVG API is modeled loosely on HTML5 canvas API. If you know canvas, you're up to speed with NanoVG in no time.
The drawing context is created using platform specific constructor function. If you're using the OpenGL 2.0 back-end the context is created as follows:
#define NANOVG_GL2_IMPLEMENTATION // Use GL2 implementation.
#include "nanovg_gl.h"
...
struct NVGcontext* vg = nvgCreateGL2(NVG_ANTIALIAS | NVG_STENCIL_STROKES);
The first parameter defines flags for creating the renderer.
NVG_ANTIALIAS
means that the renderer adjusts the geometry to include anti-aliasing. If you're using MSAA, you can omit this flags.NVG_STENCIL_STROKES
means that the render uses better quality rendering for (overlapping) strokes. The quality is mostly visible on wider strokes. If you want speed, you can omit this flag.
Currently there is an OpenGL back-end for NanoVG: nanovg_gl.h for OpenGL 2.0, OpenGL ES 2.0, OpenGL 3.2 core profile and OpenGL ES 3. The implementation can be chosen using a define as in above example. See the header file and examples for further info.
NOTE: The render target you're rendering to must have stencil buffer.
Drawing a simple shape using NanoVG consists of four steps: 1) begin a new shape, 2) define the path to draw, 3) set fill or stroke, 4) and finally fill or stroke the path.
nvgBeginPath(vg);
nvgRect(vg, 100,100, 120,30);
nvgFillColor(vg, nvgRGBA(255,192,0,255));
nvgFill(vg);
Calling nvgBeginPath()
will clear any existing paths and start drawing from blank slate. There are number of number of functions to define the path to draw, such as rectangle, rounded rectangle and ellipse, or you can use the common moveTo, lineTo, bezierTo and arcTo API to compose the paths step by step.
Because of the way the rendering backend is build in NanoVG, drawing a composite path, that is path consisting from multiple paths defining holes and fills, is a bit more involved. NanoVG uses even-odd filling rule and by default the paths are wound in counter clockwise order. Keep that in mind when drawing using the low level draw API. In order to wind one of the predefined shapes as a hole, you should call nvgPathWinding(vg, NVG_HOLE)
, or nvgPathWinding(vg, NVG_CW)
after defining the path.
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);
- make sure you have created NanoVG context using one of the
nvgCreatexxx()
calls - make sure you have initialised OpenGL with stencil buffer
- make sure you have cleared stencil buffer
- make sure all rendering calls happen between
nvgBeginFrame()
andnvgEndFrame()
- to enable more checks for OpenGL errors, add
NVG_DEBUG
flag tonvgCreatexxx()
- if the problem still persists, please report an issue!
The OpenGL back-end touches following states:
When textures are uploaded or updated, the following pixel store is set to defaults: GL_UNPACK_ALIGNMENT
, GL_UNPACK_ROW_LENGTH
, GL_UNPACK_SKIP_PIXELS
, GL_UNPACK_SKIP_ROWS
. Texture binding is also affected. Texture updates can happen when the user loads images, or when new font glyphs are added. Glyphs are added as needed between calls to nvgBeginFrame()
and nvgEndFrame()
.
The data for the whole frame is buffered and flushed in nvgEndFrame()
. The following code illustrates the OpenGL state touched by the rendering code:
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);
See the header file nanovg.h for API reference.
The library is licensed under zlib license Fonts used in examples:
- Roboto licensed under Apache license
- Entypo licensed under CC BY-SA 4.0.
- Noto Emoji licensed under SIL Open Font License, Version 1.1
Uses stb_truetype (or, optionally, freetype) for font rendering. Uses stb_image for image loading.