Giter Site home page Giter Site logo

nanovg's Introduction

This project is not actively maintained.

NanoVG

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.

Screenshot

screenshot of some text rendered witht the sample program

Usage

The NanoVG API is modeled loosely on HTML5 canvas API. If you know canvas, you're up to speed with NanoVG in no time.

Creating drawing context

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 shapes with NanoVG

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.

Understanding Composite Paths

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);

Rendering is wrong, what to do?

  • 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() and nvgEndFrame()
  • to enable more checks for OpenGL errors, add NVG_DEBUG flag to nvgCreatexxx()
  • if the problem still persists, please report an issue!

OpenGL state touched by the backend

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);

API Reference

See the header file nanovg.h for API reference.

Ports

Projects using NanoVG

License

The library is licensed under zlib license Fonts used in examples:

Discussions

NanoVG mailing list

Links

Uses stb_truetype (or, optionally, freetype) for font rendering. Uses stb_image for image loading.

nanovg's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nanovg's Issues

Newline wrapping

As discussed, this is a request for newline (text wrapping) support in NanoVG's text rendering function, either as a modification to the existing nvgText(), or as a new multi-line text function.

Undefined behavior in nanovg.c, in function nvgRGBA:

The problem is the last term here, the shifting by 24.

unsigned int nvgRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
{
    return (r) | (g << 8) | (b << 16) | (a << 24);
}

Suppose int was at least 32 bit (which is not guaranteed, so better use uint32_t at least). Even though integral promotion is performed only shifting by at most 23 is allowed.

Shifting UCHAR_MAX by 24 yields a negative number, which is undefined behavior, too.

Proposal: Add FillPreserve/StrokePreserve, kill BeginPath.

At the moment, drawing is done via Fill/Stroke, which both preserve state; The user is expected to call BeginPath to clear the current path. This becomes a perpetual nuisance, as calling BeginPath is easy to forget, so paths may be redundantly redrawn, and the mistake is very hard to detect if the paint doesn't change; Additionally, calling BeginPath turns out to be quite annoying if the path needs to be cleared after each operation, which is the usual case.

Additionally, one would expect that BeginPath has a matching EndPath, much like BeginFrame/EndFrame, but it's missing; this is confusing/surprising.

Therefore I would like to suggest following changes in the API, in the same way the Cairo API solves this, which has worked very well for me over the past years:

  1. nvgFill is renamed to nvgFillPreserve, nvgStroke is renamed to nvgStrokePreserve. The functionality stays the same.
  2. nvgBeginPath becomes an internal function and is removed from the header.
  3. A new nvgFill implementation calls nvgFillPreserve, then nvgBeginPath; Likewise, the new nvgStroke implementation calls nvgStrokePreserve, then nvgBeginPath.

It would optionally be possible to rename nvgBeginPath to nvgClearPath and still keep it around, for situations where paths are started but then need not be drawn (for whatever reason), and for cases where existing users just want to do an 1:1 update of their code with a simple rename job.

At this point I should say that I'm totally fine with my proposals being shot down. It's just been things on my mind while I wrote the bindings, and I am also thinking about people (like me) who consider porting code over from cairo. The library is young and I figured this would still be a good time for basic API improvements.

Feature request: Query Transform

I would like to have a way to query the upper 6 values of the current transform matrix, using a function like e.g.

void nvgQueryTransform(struct NVGcontext* ctx, float *mtx);

I'm currently implementing a UI drawing library that makes use of NanoVG's internal stack to do hierarchical transformations; An element of the lib is supposed to layout its children before drawing them, for which it needs to know its current transformation. Without this function, I'd have to do all transformations in my own code, and would not be able to use the stack at all.

C++ linkage problems.

Hi Mikko, I tried out the library but ran into some link problems from C++ ... it might be related to the main header missing the C++ guards for extern "C", as well as trying to return a value to a forward declared struct when in C++ mode.

Forgive my weak git fu, here is a patch inline in the comment.

diff --git a/src/nanovg.h b/src/nanovg.h
index fabe79c..fd8904e 100644
--- a/src/nanovg.h
+++ b/src/nanovg.h
@@ -19,10 +19,25 @@
#ifndef NANOVG_H
#define NANOVG_H

+#ifdef __cplusplus
+extern "C" {
+#endif
+
#define NVG_PI 3.14159265358979323846264338327f

struct NVGcontext;
-struct NVGpaint;
+struct NVGpaint
+{

  • float xform[6];
  • float extent[2];
  • float radius;
  • float feather;
  • unsigned int innerColor;
  • unsigned int outerColor;
  • int image;
  • int repeat;
    +};

enum NVGwinding {
NVG_CCW = 1, // Winding for solid shapes
@@ -355,18 +370,6 @@ enum NVGtexture {
NVG_TEXTURE_RGBA = 0x02,
};

-struct NVGpaint
-{

  • float xform[6];
  • float extent[2];
  • float radius;
  • float feather;
  • unsigned int innerColor;
  • unsigned int outerColor;
  • int image;
  • int repeat;
    -};

struct NVGscissor
{
float xform[6];
@@ -410,5 +413,8 @@ struct NVGcontext* nvgCreateInternal(struct NVGparams* params);
void nvgDeleteInternal(struct NVGcontext* ctx);

+#ifdef __cplusplus
+}
+#endif

#endif // NANOVG_H

OpenGL buffered backed is great!

Hi,

I have updated to latest commit, and found out opengl buffered backed is great! we have amost 100+ fps at full speed. Thanks for this great feature!

We use buffered backed now is because now it support GL2, so a name nanovg_gl3buf.h is not suitable for this backend, what about only nanovg_glbuf.h ?

I have interesting to write a pure software backend (for some old device that have not OpenGL support or OpenGL support is software and very slow, e.g. the old Nokia cellphones). Is pull requests welcome?

regards,
Xavier.

Line caps off by one?

I'm doing some really basic line rendering tests with edge AA turned on and I got the following result. I'm rendering a 4 pixel horizontal line with a stroke width of 1 using the code below.

nvgStrokeColor(vg, nvgRGBA(255,255,255,255));
nvgLineCap(vg, NVG_BUTT);
nvgStrokeWidth(vg, 1.0f);
nvgBeginPath(vg);
nvgMoveTo(vg, 10.5f, 100.5f);
nvgLineTo(vg, 14.5f, 100.5f);

What I'm getting however, is a full 5 pixel line. That's not what I expected from a line segment capped by NVG_BUTT. It would be the result I'd expect when using NVG_SQUARE, but if I do that the line becomes 7 fully white pixels.
Here's a close-up view of what I mean:
linecaps
Cyan outline is the expected stroked line segment using NVG_BUTT.

Is this intended behavior?

Cheers,

Guido

EXC_ARM_DA_ALIGN thrown on armv7

Looks like armv7 requires that pointers be 32bit-aligned, and will throw an EXC_ARM_DA_ALIGN exception otherwise.

I was getting unaligned values from nvg__fragUniformPtr due to gl->fragSize being 173. Changing align to 4 here seems to fix things:
https://github.com/memononen/nanovg/blob/master/src/nanovg_gl.h#L370

I think the real issue is that we need a special case for when align is 1 here:
https://github.com/memononen/nanovg/blob/master/src/nanovg_gl.h#L565

I can submit a pull req if you like.

More info on the armv7 alignment issue: https://brewx.qualcomm.com/bws/content/gi/common/appseng/en/knowledgebase/docs/kb95.html

Line width seems to have a minimum of 1.0

I'm using pixel ratios to have a fixed-size coordinate space to draw in which causes lines of thickness 1.0 to be several physical pixels in size, which is fine.

I do however expect a thickness < 1.0 to differ in size from a thickness of 1.0, but it seems like widths are clamped to 1.0.

For flair, it would be nice to be able to express detail finer than pxRatio.

Is this intended or unintended behaviour?

glnvg__alloc not respecting requested allocation size

Most glnvg__alloc...() functions are not respecting the requested allocation size 'n' on reallocation. The capacity is doubled in size when the buffer doesn't fit anymore, but just doubling it may not be sufficient to hold 'n' extra elements.

E.g. I had (hard to reproduce) memory corruption because glnvg__allocVerts(gl, n=314) was expanding its gl->cverts from 256 to 512 while gl->nverts was at 220.

How to stroke text?

Hi,

I'm writing a Lua language binding for NanoVG, I'm trying to implement context.strokeText, so I wondering how to stroke a text. currently NanoVG can only fill text. Is that right? then how can I implement stroke?

Path winding not working under SDL2

Is there any known issue between NanoVG and SDL2? Or, is there any particular OpenGL state that NanoVG needs in order for path winding (creating holes within shapes) to work, that SDL2 might be messing up?

I've recently switched my project from GLFW to SDL2, and this change has caused NanoVG output to be wrong due to missing shape holes. I've got it narrowed down to a sample program where I can toggle between using GLFW to create the window and context, and having SDL2 do it, and only the GLFW version draws correct holes.

The test program draws a red rectangle, then another green one over top with a hole. Under GLFW, you can see the red showing through, as expected. With SDL2, you just see a solid green rectangle.

This is on Linux, if it matters, using the GL3 version of NanoVG.

Here is the (heavily butchered) test program: https://gist.github.com/Nairou/ffddad31a847ccf4572b

run custom shader in nanovg.

Hi Mikko :-)

I have tried to write a same thing like nanovg, So you know how happy I found this project! it IS great!

I just want a light-weight graphics library can be used in small game with Lua. So I will write a binding to Lua of nanovg. So there are some features I want ask.

There is a game-engine in Lua, [Love2D][love2d.org], it has custom shader support, It allows user to give two shader functions: effect and position, at [this][http://www.love2d.org/wiki/love.graphics.newShader].

It looks good and allow users to modify effects on screen, So may nanovg support custom shader linking/loading?

we can offer two default shader function, and if user do not specified custom shader, we use the default one, what I wonder is how to design a good interface for specify shader uniform/attribute array in a clean way.

Thx for this great work again :)

NV_path_rendering backend

I would like to propose yet another backend for NanoVG based on the NV_path_rendering extension [1]. For my own code, I run primarily on NVIDIA hardware and want to take advantage of anything it has to offer, while still maintaining the portability of NanoVG. Once I have NanoVG integrated into my code, I will give this a shot, but meanwhile, just wanted to throw this idea out there.

[1] https://developer.nvidia.com/nv-path-rendering

Inverse Scissoring

Is there a way with the current API to do inverse scissoring? As in defining an area where you DON'T want to draw?

nvg__bevelJoin Typo/Copy+Paste Bug

I think the second-to-last nvg__vset() call in nvg__bevelJoin() has a copy/paste mistake:

nvg__vset(dst, p1->x + dlx1*rw, p1->y + dly1*rw, lu,1); dst++;

should be:

nvg__vset(dst, p1->x + dlx1*lw, p1->y + dly1*lw, lu,1); dst++;

I could see a difference in the 3rd text line in the example (the one with like the 1 pixel wide vertical gray box).

Jittery text while rotating example dialog.

In the example code I added a simple rotation over time:
rotate += 0.01f;
nvgRotate(vg, rotate/180.0f*NVG_PI);

... to see how the dialog would look with a rotation-based animation. Some of the text looks fine, but on several widgets (and the title bar) the text shakes back and forth as the dialog slowly rotates. Not sure if this is an easy fix. I can't quite tell why some of it works and some doesn't.

(very cool library btw!)

compile error

I cant compile in vs2010, windows 8. I recieve numerous errors.

glTexSubImage2D

I use NANOVG_GL3_IMPLEMENTATION. I get "error 501 after convex fill" when i use glTexSubImage2D. And I don't see other 3d model-mesh in background.

Patch to make NanoVG support MinGW on Windows.

Hi all,

this is a patch for MinGW, a Windows version of gcc, produced native executable file for WIndows. after a little modify, I have successfully bootstrap NanoVG with MinGW, this is the patch:

diff --git a/example/demo.c b/example/demo.c
index d3d6620..3f93a43 100644
--- a/example/demo.c
+++ b/example/demo.c
@@ -13,7 +13,7 @@

 #ifdef _MSC_VER
 #define snprintf _snprintf
-#else
+#elif !defined(__MINGW32__)
 #include <iconv.h>
 #endif

diff --git a/example/perf.c b/example/perf.c
index bf36a61..94113b7 100644
--- a/example/perf.c
+++ b/example/perf.c
@@ -10,7 +10,7 @@

 #ifdef _MSC_VER
 #define snprintf _snprintf
-#else
+#elif !defined(__MINGW32__)
 #include <iconv.h>
 #endif

diff --git a/premake4.lua b/premake4.lua
index 123482d..4d320f1 100644
--- a/premake4.lua
+++ b/premake4.lua
@@ -34,7 +34,7 @@ solution "nanovg"
             defines { "NANOVG_GLEW" }

        configuration { "windows" }
-            links { "glu32","opengl32", "gdi32", "winmm", "user32", "glfw3", "GLEW" }
+            links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32" }
             defines { "NANOVG_GLEW" }

        configuration { "macosx" }
@@ -62,7 +62,7 @@ solution "nanovg"
             defines { "NANOVG_GLEW" }

        configuration { "windows" }
-            links { "glu32","opengl32", "gdi32", "winmm", "user32", "glfw3", "GLEW" }
+            links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32" }
             defines { "NANOVG_GLEW" }

        configuration { "macosx" }
@@ -91,7 +91,7 @@ solution "nanovg"
             defines { "NANOVG_GLEW" }

        configuration { "windows" }
-            links { "glu32","opengl32", "gdi32", "winmm", "user32", "glfw3", "GLEW" }
+            links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32" }
             defines { "NANOVG_GLEW" }

        configuration { "macosx" }
@@ -120,7 +120,7 @@ solution "nanovg"
             defines { "NANOVG_GLEW" }

        configuration { "windows" }
-            links { "glu32","opengl32", "gdi32", "winmm", "user32", "glfw3", "GLEW" }
+            links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32" }
             defines { "NANOVG_GLEW" }

        configuration { "macosx" }
@@ -147,7 +147,7 @@ solution "nanovg"
             links { "X11","Xrandr", "rt", "GL", "GLU", "pthread", "m", "glfw3" }

        configuration { "windows" }
-            links { "glu32","opengl32", "gdi32", "winmm", "user32", "glfw3", "GLEW" }
+            links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32" }
             defines { "NANOVG_GLEW" }

        configuration { "macosx" }
@@ -174,7 +174,7 @@ solution "nanovg"
             links { "X11","Xrandr", "rt", "GL", "GLU", "pthread", "m", "glfw3" }

        configuration { "windows" }
-            links { "glu32","opengl32", "gdi32", "winmm", "user32", "glfw3", "GLEW" }
+            links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32" }
             defines { "NANOVG_GLEW" }

        configuration { "macosx" }

Disabling 'Blending' causes a performance warning.

In my setup, using glDebugMessageCallback(), I'm getting a debug callback when drawing a non-convex, filled shape which appears to be due to the GL_BLEND being disabled at the top of glnvg__fill(). The message is:

Program/shader state performance warning: Fragment Shader is going to be recompiled because the shader key based on GL state mismatches.

This is on a nVidia Quadro 4000. Just wondering if there is a need to disable blending there? I commented it out and it seems to render the demo fine and at the same frame-rate, but I don't think it's fill-bound right now or even drawing that many non-convex shapes.

Enforce winding / polyReverse bug.

So as a test, I commented out the code in nvg__flattenPaths() to "Enforce winding."

// Enforce winding.
if (path->count > 2) {
    area = nvg__polyArea(pts, path->count);
    if (path->winding == NVG_CCW && area < 0.0f)
        nvg__polyReverse(pts, path->count);
    if (path->winding == NVG_CW && area > 0.0f)
        nvg__polyReverse(pts, path->count);
}

as it did not seem necessary given a simple rectangle shape -- the points should have been properly generated from the start.

If this is removed, the shape will then fail the left-turn check inside nvg__expandStrokeAndFill() and presumably go through the slower non-convex fill drawing method.

With the enforce winding removed, nvg__expandStrokeAndFill()'s cross product result needs to be flipped (or the vectors need to be flipped).

So I'm assuming there's a bug then with the comparison in the "Enforce winding" check or the nvg__polyArea function that's causing the cross result to need to be checked differently?

I'm still looking over this, but as the code is now, it seems like every basic shape is going through the nvg_polyReverse() call.

rendering not working on my Ubuntu 13.10/Linux system

While I have compiled and ran nanovg successfully on my mac, I was recently trying to run the example code on my Ubuntu 13.10 laptop, which uses either an Intel or NVIDIA GPU (proprietary, binary driver) that I can select in the BIOS.

Running with either GPU, the example code doesn't render correctly, and only text appears,
rendered_incorrectly

Not being familiar with the underlying rendering technique, there wasn't much I could do to fix it, but I tried to narrow down the issue slightly, by modifying the shader alpha component calculation from "color.w *= strokeAlpha * scissor;", to just "color.w *= scissor;", in which case the rest of the scene appears, but the blending appears off:

hacked_shader

GLES2 issues

When I run my laptop with Intel Mesa drivers, I can get a GLES3 context, and that helps exercise the new GLES2 support. A few things:

  • I don't think GLEW works with GLES2, and it is not working on my system. I would get rid of it for example_gles2.c.
  • You can explicitly request an OpenGL ES context. I needed to do this on my system, otherwise the context was desktop OpenGL.
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
GL_UNPACK_ROW_LENGTH
GL_UNPACK_SKIP_ROWS
GL_UNPACK_SKIP_PIXELS 
  • Finally, the shaders require a precision specifier. Also, it doesn't seem to be required, but it might be worthwhile to add a #version directive to ensure the shaders get treated as GLES2 / GLSL ES 1.0 shaders when running with future version of OpenGL ES (GLES3 is apparently backwards compatible with GLES2).
"#version 100\n"
"precision mediump float;\n"

GLNVG_LOC_TEX not part of uniform buffer

The GLNVG_LOC_TEX binding should always be cached and set, also when compiling with NANOVG_GL_USE_UNIFORMBUFFER as the sampler is not part of the uniform buffer (it's ok in the shader though).

The rendered result doesn't look nice

I was trying to render circles on iPhone 5S. But the circle doesn't look smooth as a circle even in Retina display. I tried to change the mediump to highp but the result was not improved.

This picture shows the result I got, and I enlarged it 2x in Photoshop so it's more clear to see the result is not smooth.
nanovg_circle

The code I was using to render the circle is as follow.

const int kCenterX = (GetWidth() + 1) / 2;
const int kCenterY = (GetHeight() + 1) / 2;

nvgBeginPath(context);
nvgCircle(context, kCenterX, kCenterY, (GetWidth() - 1) / 2 - 2);
nvgFillColor(context, nvgRGBA(110, 201, 235, 180));
nvgFill(context);

nvgBeginPath(context);
nvgCircle(context, kCenterX, kCenterY, (GetWidth() - 1) / 2 - 1);
nvgStrokeColor(context, nvgRGBA(255, 255, 255, 255));
nvgStrokeWidth(context, 3);
nvgStroke(context);

nvgBeginPath(context);
nvgCircle(context, kCenterX, kCenterY, (GetWidth() - 1) / 2 - 7);
nvgFillColor(context, nvgRGBA(255, 255, 255, 255));
nvgFill(context);

The environment for setting OpenGL and nanovg context up is also very intuitive like this: https://github.com/ollix/moui/blob/master/moui/widgets/widget_view.cc

Proposal: Ensure all required GL states are correct in beginFrame

It appears NanoVG doesn't set all states required for it to render correctly, which increases the amount of boilerplate needed on the client side, and also causes all kinds of hard to diagnose side effects if the user is making use of other blackbox GL components.

I'm not sure why this was done, perhaps to make multiple subsequent draw calls more efficient, but in practice, this should not make any noticeable differences in performance.

Among the states mentioned in the docs, which are
glEnable(GL_CULL_FACE)
glCullFace(GL_BACK)
glEnable(GL_BLEND)
glDisable(GL_DEPTH_TEST)

I also had to take care that these states are initialized as follows (still probably not a complete list):
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)

And then there are other obvious ones, which are
glViewport(0,0,frame_width,frame_height)
glClearColor(0,0,0,0)
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)

I would like to propose that the alpha_blend argument in beginFrame is converted to a general flags field, NVG_PREMULTIPLIED_ALPHA and NVG_STRAIGHT_ALPHA control bit 0, and a new NVG_NAKED_FRAME field is introduced, which, when set, does not make any of the above calls; so the default would be that all states are set correctly and the framebuffer is cleared for drawing.

For more granular control, if desired, NVG_NAKED_FRAME could also be a composite of three bits, which is at most NVG_KEEP_STATES (no state changes), NVG_KEEP_VIEWPORT (no viewport change) and NVG_KEEP_FRAMEBUFFER (no clear).

If none or not all of the proposed changes find their way into the codebase, I'd appreciate if the docs would be expanded by the additionally required boilerplate so others don't run into the same problems.

GL_INVALID_ENUM error on init in Windows using gl3

Compiling and running the gl3 sample produces a GL_INVALID_ENUM error on glnvg__checkError("init");. It's not limited to the sample however, as I encounter the same error in my own GL application.

So far I've been unable to track down the source. Everything seems to be working just fine even with the error.

Feature request: HDR rendering

I'm currently using cairo to do dynamic/procedural textures for our game, and I am looking for a more performant, lightweight replacement. NanoVG would qualify (as soon as miter joins / round caps work), but I'm also unhappy with cairo's current limitation to support only 8-bit per channel (http://cairographics.org/manual/cairo-Image-Surfaces.html#cairo-format-t) and so it would be nice if (as NanoVG runs on GL backend) NanoVG would support rendering to 16F/32F textures that I can then use in my deferred rendering engine.

Proposal: merge Stroke/Fill color states, optionally hide NVGpaint/NVGcolor

At the moment there are four different functions to configure draw paint, two for high level, two for low level, two for each stroke / fill, so a 2x2 matrix:

void nvgStrokeColor(struct NVGcontext* ctx, struct NVGcolor color);
void nvgStrokePaint(struct NVGcontext* ctx, struct NVGpaint paint);
void nvgFillColor(struct NVGcontext* ctx, struct NVGcolor color);
void nvgFillPaint(struct NVGcontext* ctx, struct NVGpaint paint);

This complicates the interface somewhat; I can't set the same color/paint for both strokes and fills at the same time - I even feel stupid writing a wrapper that does this for me, as I'm most of the time only using 50% of the setting; The API level also suffers: More paint config functions have become cumbersome as each one would have to be doubled, which is why the implementation details NVGcolor and NVGpaint are exposed, and the rest of the configuration is done through these multi-functional structs.

If both stroke and fill would happen at the same time, the above interface would make sense, but they're never seen at the same time, which lets me conclude that they are both the SAME dude, but with a different beard ;-) Therefore, I would like to propose to merge the separate states into a single one (as it works in Cairo), so that the declarations become:

void nvgColor(struct NVGcontext* ctx, struct NVGcolor color);
void nvgPaint(struct NVGcontext* ctx, struct NVGpaint paint);

Both stroke and fill operation would then source the same paint.

It would be optionally possible to hide NVGcolor/NVGpaint from the interface completely, clearing the header of structs (solving any future alignment or packing problems), and allowing to use only internal structures for context.

nvgColor would then become nvgSourceRGB, nvgSourceRGBA, nvgSourceRGB8, etc., and the old nvgRGB* functions would disappear.

All NVGpaint functions would return void, adapt the same scheme e.g. nvgSourceLinearGradient and set the internal paint directly.

Then the API would work pretty much like the cairo API does.

Of course that means the user can no longer prepare and cache source paints, but it doesn't look like being able to do so would be a big optimization. Users should arrange their calls to group similar batches anyway.

opengl core / gles support?

nanovg looks incredibly useful. Do you have already plans to add support for rendering in an OpenGL Core profile, or with GLES (2/3)?

Support Blur if object is not opaque

Hello,

I would like to create some surface that is semi transparent and that blurs the content behind it. What would be the approach for this, knowing i use nanovg to draw everything

noblur

For instance here i would like see the animated graph be blurred when it is behind the semi transparent window

google group

Would it make sense for there to be a google group or mailing list?

I have lots of questions regarding using NanoVG that probably are not appropriate as Github issues.

Feature request: Hit Testing

It would be great if I could get precise hit testing for paths, in a similar way that Cairo supports it.

An user could draw a path, and, instead of filling/stroking it, query whether a certain point is within the shape, using following two new proposed functions

bool nvgInFill(struct NVGcontext* ctx, float x, float y);
bool nvgInStroke(struct NVGcontext* ctx, float x, float y);

These functions would not commit their fill/stroke, only execute the test. The user would still be able to call fill/stroke afterwards, or merely clear the path.

I reckon these tests wouldn't cover text, but that's probably OK.

Unable to use OTF fonts

You currently use stb_truetype.h for handling fonts, which can't load .otf font files. Any opposition to using freetype instead, other than adding a dependency?

Font not works

I have integrated your library into my engine:

Now i have something like this:

nvgFontSize(vg, 20.0f);
nvgFontFace(vg, "sans");
nvgFillColor(vg, nvgRGBA(255, 255, 255, 32));
nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE);
nvgText(vg, viewport.width - 300, viewport.height - 300, "HELLO WORLD", NULL);

But text is not shown, is there any prerequesities or define i need to add?

Thanks

Demo on Retina display

I'm not sure if this is intentional or not, but the included examples do not seem to distinguish between framebuffer and window size correctly, and therefore the demo doesn't appear as advertised when running with a Retina display:

screen shot 2014-02-13 at 7 51 59 am

The framebuffer size should be indeed be used to set glViewport, but the window size should be used elsewhere. A simple fix is

        glfwGetWindowSize(window, &width, &height);
        nvgBeginFrame(vg, width, height);

Once this is done, the NanoVG demo appears as advertised when running with a Retina display:

screen shot 2014-02-13 at 7 58 50 am

Doesn't build on Mac OS X 10.9.1

Need to add -framework CoreVideo to the gl2 and gl3 examples. Otherwise the linker won't find the CVDisplayLink symbols in glfw

Text 3D transformation

Hi And kudos for your great work on this lib.I have been expecting the source code of GL 3 core module to see if I can use it for text rendering.I found that the vertex shader doesn't use projection matrices,so I can assume the text is always in screen space.I wonder if I should expect any kind of problems if I transform the text with a perspective matrix?
Thanks.

Proposal: add compositing setting to NanoVG.

Hi,

I hope NanoVG could add compositing support. it means, you can set how pixel composition with destination pixel. In HTML5 canvas, these compositing mode are used:

source-over
   glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

source-in
   glBlendFunc(GL_DST_ALPHA, GL_ZERO);

source-out
   glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ZERO);

source-atop
   glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

destination-over
   glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE);

destination-in
   glBlendFunc(GL_ZERO, GL_SRC_ALPHA)

destination-out
   glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);

destination-atop
   glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA);

lighter
   glBlendFunc(GL_ONE, GL_ONE);

darker
   deprecated

copy
   glBlendFunc(GL_ONE, GL_ZERO);

xor
   glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

see here

A function:

void nvgBlendMode(NVGcontext *ctx, int mode);

can be added, and add a field to NVGparams, backend can set correct mode before any drawing.

Performing Layout Calculations

I was a bit curious as to how people were performing layout calculations with NanoVG? Say for something as simple as a Button control that calculates its width based on its text? Or for more complex Row/Column/Table based layout?

The main issue I seem to have is with having to setup the state on a NVGcontext in order to properly calculate a text bounds based on the current font, font-size, font-blur, etc. Normally I'd have an UpdateLayout pass that sizes and positions everything, and then have the Draw come through and render using the context with everything ready to go (possibly even drawing in a background thread).

It seems like one way would be to have a separate context for the update to use that avoids any actual draw calls. Another way would be to use the font directly to compute a bounds for text, but I believe this would not perform the pixel alignment that the actual drawing code performs (though I'm not sure that nvgTextBounds performs this either).

Broken fonts with non 512x512 atlas size.

On Windows I am trying to specify a larger atlas size to the glnvgCreate() call in the example.c file. Setting it to 1024x1024 (or anything other than 512x512) causes a problem with font rendering. The output is corrupt, possibly from bad uv coordinates being used to draw.

Is there some other value that I need to adjust to get this to work?

nanovg-bug

Weird line on shape boundary

This snippet tries to stroke and fill a rectangle with the same color. The result should still look like a rectangle without stroke, but it isn't.

struct NVGcontext* context = nvgCreateGLES2(GetWidth(), GetHeight(), NVG_ANTIALIAS);

glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);

// Fill and stroke for the same rectangle with the same color.
nvgBeginFrame(context, GetWidth(), GetHeight(), GetContentScaleFactor());
nvgBeginPath(context);
nvgRect(context, 0, 0, width(), height());
nvgFillColor(context, nvgRGBA(110, 201, 235, 255));
nvgStrokeColor(context, nvgRGBA(110, 201, 235, 255));
nvgStrokeWidth(context, 10.0f);
nvgFill(context);
nvgStroke(context);
nvgEndFrame(context);

The result picture looks like this, pretty weird.
nanovg

Small glnvg__xformInverse() bug.

In glnvg__xformInverse():
if (det > -1e-6 && det < -1e-6) {

I think the second check should be positive 1e-6 to provide the approximately-zero check.

Fill path doesn't work properly

I was trying to write a simple utility for converting SVG files into nanovg source code. Unfortunately, the result looks a bit weird. To stroke the path, it looks exactly what I want. But to fill the path, nanovg simply draws a rectangle. This picture shows the expected and rendered results by nanovg:
nanovg_path

The code for drawing the path is as follow:

nvgBeginPath(context);
nvgMoveTo(context, 43.438, 11.27);
nvgLineTo(context, 38.485, 11.27);
nvgBezierTo(context, 37.279, 8.237, 34.315, 6.079, 30.865, 6.079);
nvgLineTo(context, 19.135, 6.079);
nvgBezierTo(context, 15.687, 6.079, 12.723, 8.237, 11.518, 11.27);
nvgLineTo(context, 6.561, 11.27);
nvgBezierTo(context, 2.951, 11.27, 0, 14.22, 0, 17.829);
nvgLineTo(context, 0, 39.154);
nvgBezierTo(context, 0.0, 42.759, 2.951, 45.715, 6.561, 45.715);
nvgLineTo(context, 43.438, 45.715);
nvgBezierTo(context, 47.044, 45.715, 50.0, 42.76, 50.0, 39.154);
nvgLineTo(context, 50.0, 17.829);
nvgBezierTo(context, 50, 14.22, 47.044, 11.27, 43.438, 11.27);
nvgClosePath(context);

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.