nanovg
nanovg copied to clipboard
Add infrastructure to compile with emscripten
If you did this, nanovg could be used as the basis of a web based dashboard...or lots of web based stuff I suppose.
The NanoVG API is based on the HTML5 Canvas API.
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D
Using the canvas directly would be faster than rasterizing in JavaScript and drawing that onto a canvas.
I've compiled nanovg with emscripten. It's pretty trivial, here is my makefile:
EXPORTED_FUNCTIONS=EXPORTED_FUNCTIONS="['_nvgBeginFrame','_nvgCancelFrame','_nvgEndFrame','_nvgGlobalCompositeOperation','_nvgGlobalCompositeBlendFunc','_nvgGlobalCompositeBlendFuncSeparate','_nvgRGB','_nvgRGBf','_nvgRGBA','_nvgRGBAf','_nvgLerpRGBA','_nvgTransRGBA','_nvgTransRGBAf','_nvgHSL','_nvgHSLA','_nvgSave','_nvgRestore','_nvgReset','_nvgShapeAntiAlias','_nvgStrokeColor','_nvgStrokePaint','_nvgFillColor','_nvgFillPaint','_nvgMiterLimit','_nvgStrokeWidth','_nvgLineCap','_nvgLineJoin','_nvgGlobalAlpha','_nvgResetTransform','_nvgTransform','_nvgTranslate','_nvgRotate','_nvgSkewX','_nvgSkewY','_nvgScale','_nvgCurrentTransform','_nvgTransformIdentity','_nvgTransformTranslate','_nvgTransformScale','_nvgTransformRotate','_nvgTransformSkewX','_nvgTransformSkewY','_nvgTransformMultiply','_nvgTransformPremultiply','_nvgTransformInverse','_nvgTransformPoint','_nvgDegToRad','_nvgRadToDeg','_nvgImageSize','_nvgDeleteImage','_nvgLinearGradient','_nvgBoxGradient','_nvgRadialGradient','_nvgImagePattern','_nvgScissor','_nvgIntersectScissor','_nvgResetScissor','_nvgBeginPath','_nvgMoveTo','_nvgLineTo','_nvgBezierTo','_nvgQuadTo','_nvgArcTo','_nvgClosePath','_nvgPathWinding','_nvgArc','_nvgRect','_nvgRoundedRect','_nvgRoundedRectVarying','_nvgEllipse','_nvgCircle','_nvgFill','_nvgStroke','_nvgCreateGLES2','_nvgDeleteGLES2','_nvglCreateImageFromHandleGLES2','_nvglImageHandleGLES2']"
# add these symbols for font support:
# ,'_nvgCreateFont','_nvgCreateFontMem','_nvgFindFont','_nvgAddFallbackFontId','_nvgAddFallbackFont','_nvgFontSize','_nvgFontBlur','_nvgTextLetterSpacing','_nvgTextLineHeight','_nvgTextAlign','_nvgFontFaceId','_nvgFontFace','_nvgText','_nvgTextBox','_nvgTextBounds','_nvgTextBoxBounds','_nvgTextGlyphPositions','_nvgTextMetrics','_nvgTextBreakLines'
EMCC_OPTIONS=-s GL_UNSAFE_OPTS=1 -s NO_EXIT_RUNTIME=1 -s $(EXPORTED_FUNCTIONS) # -s GL_PREINITIALIZED_CONTEXT=1
EMCC_INCLUDE=-I ../src
all: nanovg.js
nanovg.js: ../src/nanovg.c ../src/nanovg.h ../src/nanovg_gl.h ../src/nanovg_gl_utils.h nanovg-emscripten.c
(cd ../src && \
emcc -o ../emscripten/nanovg.js nanovg.c ../emscripten/nanovg-emscripten.c -Oz $(EMCC_INCLUDE) $(EMCC_OPTIONS))
debug: ../src/nanovg.c ../src/nanovg.h ../src/nanovg_gl.h ../src/nanovg_gl_utils.h nanovg-emscripten.c
(cd ../src && \
emcc -o ../emscripten/nanovg.js nanovg.c ../emscripten/nanovg-emscripten.c $(EMCC_INCLUDE) $(EMCC_OPTIONS))
clean:
rm -f nanovg.js nanovg.js.*
nanovg-emscripten.c:
#include <GLES2/gl2.h>
#include "nanovg.h"
#define NANOVG_GLES2_IMPLEMENTATION
#include "nanovg_gl.h"
#include "nanovg_gl_utils.h"
The only problem is that you can't handle structures from JavaScript. What I did was to add a few functions to nanovg-emscripten.c to bridge these functions (like setting colors and image patterns).
I was curious to experiment with this. Here is a fork that should compile with emscripten
https://github.com/olilarkin/nanovg/tree/emscripten
you can try it here: https://olilarkin.github.io/nanovg/
it is slow! didn't try and optimise anything
Very nice! However, the wasm code was blocked by my adblocker for some reason…
Anyways, I only get 35fps on my GeForce 1080, there's definitely room for improvement there. I think the most important first step would be to reduce the number of gl calls to the bare minimum.
i get 60FPS in firefox and 25 FPS in chrome!
I've added a JavaScript bindings project and ported the demo.
https://github.com/flyover/nanovg-js
silly me had NVG_DEBUG enabled which was causing slow performance in chrome, but not elsewhere. New version: https://olilarkin.github.io/nanovg/
Can anyone think why Nano VG via WebGL would cause the warning "[.WebGL-0x7f8bff05b400]RENDER WARNING: there is no texture bound to the unit 0" ?
@olilarkin nanovg uses one shader for all fill types and there's if statement choosing which fill type to use. In case of solid fill, there's no texture bound to unit 0. It is be fine by all means, but that webgl implementation might see texture sampler in the shader and whine about it.
I'm seeing the same thing. The problem with it (besides log spam) is that after 100 of these, WebGL in Chrome stops logging altogether, and I'm missing any messages that happen after that, even if they're important.
The Metal port faced the same issue (in legacy Metal versions) and it was resolved by passing an empty texture. Maybe it works for the GL backend, too.
https://github.com/ollix/MetalNanoVG/blob/92351749f97b0ce984c1e54c39a6fb6c2a0e9ed4/src/nanovg_mtl.m#L520-L521
thanks @olliwang I followed roughly what you did in MetalNanoVG and fixed the issue here https://github.com/memononen/nanovg/pull/566