NVIDIA Developer Zone

NV Path Rendering

(Shortcut to downloads)

(Shortcut to demo/tutorial videos)

NVIDIA's Release 275 drivers for Windows, Linux, FreeBSD, and Solaris provide full GPU-acceleration of a style of 2D graphics known as path rendering.  Path rendering specifies a scene as a sequence of resolution-independent outlines, known as paths, that can be filled or stroked.  Such paths can be painted with constant colors, linear or radial gradients, or images.  Unlike bitmap images, apath rendering content can be arbitrarily zoomed and rescaled without pixelized results.  Path rendering contents are also easy to edit and animate because an artist can manipulate or edit the underlying paths that make up the scene instead of having to manipulate individual pixels.  For this reason and manyother advantages, path rendering powers important 2D graphics standards such as PostScript, PDF, Scalable Vector Graphics (SVG), Adobe Flash, TrueType and OpenType font rendering, Office drawings, Adobe Illustrator, HTML 5 Canvas, and more.

 

Today most path rendering is preformed with the CPU.  However,in much the same way nearly all 3D rendering is now performed on the GPU, NVIDIA expects applications over the next year to migrate their path rendering to the faster and more efficient GPU.  Traditionally, the GPU has focused its efforts on accelerating 3D graphics for games and 3D content creation.  However, with the increased flexibility and performancebenefitsof NVIDIA's CUDA-capable GPUs, path rendering is a task best performed on and by the GPU.

 

The NV_path_rendering extension to OpenGL is supported in Release 275 drivers and beyond with all CUDA-capable NVIDIA GPUs.  This encompasses GeForce 8 and newer series GPUs.  Here you'll find an introduction to the NV_path_rendering approach to GPU-accelerated path rendering.  The accompanying software development kit (NVprSDK) and pre-compiled demos (NVprDEMOs) demonstrate the path rendering quality and performance achievable with NV_path_rendering.  Accompanying presentations and whitepapers explain how application programmers can start making use of NV_path_rendering today.

 

If you have questions about NV_path_rendering, send email to nvpr-support at nvidia dot com

Downloads

 

by RBurkersroda
postd on Apr 25 2012 at 03:04AM

glPathGlyphsNV() in combination with GL_SYSTEM_FONT_NAME_NV seems to be language dependent.
On a German system something like "Arial Bold" as font name is not working because the function requires "Arial Fett", which is the German counterpart, although this string is not stored in the corresponding .ttf file.
Is there a chance to implement another option so the font name has to match the universal string that is stored in the file and not a name, which is only useful in a user interface? Apart from that it would also be nice to be able to specify PostScript font names but we have already implemented a solution by parsing all font files in the system folder and storing the names in a map. This routine could also be our alternative for the issue by caching the file paths and using them with GL_FILE_NAME_NV, but that requires some code alterations.

by Mark Kilgard
postd on Apr 25 2012 at 07:59PM

Hopefully I can provide some suggestions for your problem.
First, what operating system are you using?  GL_SYSTEM_FONT_NAME_NV provides a font named based on the system convention.  On Windows, that is feeding the ASCII font name to CreateFontIndirectA to get the font.  For Linux/FreeBSD/Solaris, that is using FontConfig's API.
If you are wanting the bold version of Arial, have you tried using the GL_BOLD_BIT_NV bit and simply specifying "Arial" as an alternative to "Arial Bold" or "Arial Fett".  I hope that would be locale independent.
Based on MSDN documentation, it seems like either the English or locale-specific name should work:

The font mapper for CreateFont,CreateFontIndirect, and CreateFontIndirectEx recognizes both the English and the localized typeface name, regardless of locale.

Setting the GL_BOLD_BIT corresponds to searching for FC_WEIGHT_BOLD for the FC_WEIGHT pattern for FontConfig.  For Win32, it corresponds to setting the lfWeight member to FW_BOLD in the LOGFONTA structure.
- Mark

by RBurkersroda
postd on May 11 2012 at 05:56AM

Thank you for your answer.

I do not know why but unfortunately something like "Arial Bold" does not work on our German system and our application only knows that font name, so it cannot automatically substitute it by "Arial Fett" or "Arial" and the GL_BOLD_BIT_NV flag.
Here is what we do: We are loading a Photoshop file and rendering it using OpenGL. The fonts used in those files have got PostScript names and so we are parsing all system fonts to map PostScript to TrueType. But instead of using the GL_SYSTEM_FONT_NAME_NV as before we are now storing the file names, too. So we can actually load the correct font using the path name and GL_FILE_NAME_NV.
But I encountered another issue doing so: The kerning does not seem to work anymore. It does not matter what value is specified for glGetPathSpacingNV(), every time the result looks like 0.0f when using a system font. Because the FreeType DLL is required for font loading I assume that the kerning values are not (correctly) transferred from FreeType to your library as they are when using the system functions.

Can you confirm that? And is or will there be a solution to the problem?

by Malcolmb
postd on Apr 13 2012 at 01:56PM

Is there any plan to finish off the SVG implementation? It seems like a lot of font rendering doesn't happen right now in .svg files I load.

by Mark Kilgard
postd on Apr 13 2012 at 02:25PM

Malcolmb, you are correct to observe that the SVG support in NVprSDK's nvpr_svg example is incomplete, particularly in the area of support the SVG <text> tag.
   nvpr_svg is meant to demonstrate the path rendering of SVG.
   There are other examples (nvpr_textwheel, nvpr_basic, nvpr_tiger3d) that demonstrate text rendering but not in the context of SVG.
   Complete source code for nvpr_svg is included in the NVprSDK so someone could work on support SVG's <text> tages.  nvpr_does have some limited non-SVG support to render glyphs.  You'll find there's a "Scalable fonts..." menu item so you can evaluate the rendering quality of various TrueType fonts.
    I also encourage you to get the latest Release 300 drivers from NVIDIA's web site.  You'll find these drivers contain remarkable improvements in the performance of NV_path_rendering for both Fermi and Kepler GPUs,  You can get the beta Windows drivers from:
  http://www.nvidia.com/object/win7-winvista-64bit-301.24-beta-driver.html
  http://www.nvidia.com/object/win7-winvista-32bit-301.24-beta-driver.html
  http://www.nvidia.com/object/winxp-301.24-beta-driver.html
By exploiting a unique programmable front-end processor in Fermi and Kepler GPUs, we've greatly reduced the CPU overhead when transitioning between the "stencil" and "cover" steps and thereby your GPU spends more time path rendering and with less CPU overhaed.
- Mark Kilgard

by sqrt-1
postd on Oct 02 2011 at 05:30AM

In the demo nvpr_gradient.c, this line generates a GL error:
glPathColorGenNV(GL_PRIMARY_COLOR, GL_NONE, GL_RGBA, NULL);

as:

When /genMode/ is NONE, then /colorFormat/ must be NONE;
otherwise INVALID_ENUM is generated.

by McSeem
postd on Aug 02 2011 at 08:46PM

I found my face in your presentation. It's so funny. It's here
http://developer.download.nvidia.com/assets/gamedev/files/An_Introductio...
At about 67th page. The photo was taken with a cheap camcoder, in a cheap bathroom in front of the mirror, in a cheap apartment at 507 Cadwalader Cir, Exton, PA. And then vectorized into SVG. But I can't remember where I published it, maybe in the mail list or somewhere else. But anyways, it looks like you guys had a look at antigrain.com, and it's nice to see my face in your slides. However, it would also be great to mention AGG too. No need for anything official, just a couple of informal words.

by Mark Kilgard
postd on Aug 03 2011 at 01:03PM

McSeem,

> However, it would also be great to mention AGG too. No need for anything official, just a couple of informal words.

When developing NV_path_rendering, we definitely looked at Anti-Grain Graphics (AGG).  Yes, that's where the mcseem2.svg file came from.  You can find the SVG file for it both in the NVprDEMOs.zip and NVprSDK.zip distributions.

AGG's focus on high-quality path rendering was a big inspiration to make sure GPU-accelerated path rendering really handled the hard situations well.  Conflation of coverage and opacity (transparency) was one of the quality goals of NV_path_rendering that was inspired by AGG.  Particularly this page:

  http://www.antigrain.com/svg/index.html

See the svg/characters/xenia4.svg & svg/characters/mcseen2.svg content in nvpr_svg's library of SVG examples to see how nicely NV_path_rendering handles this situation.

The nvpr_svg example in the SDK has back-ends for lots of alternative path rendering libraries (Cairo, Skia, Qt, OpenVG, and Direct2D) but not AGG.  We regret not having an AGG back-end but it was going to be pretty involved since no one was familiar with AGG.  I'd love someone to code up an AGG back-end so it would be possible to do performance and quality comparisons with all the different publically-available path rendeirng systems out there.

Is anyone experienced with AGG up to the task?

- Mark

by McSeem
postd on Aug 02 2011 at 10:30PM

This is the original picture that was vectorized. http://antigrain.com/mcseem/mcseem_2003_2.jpg
But I still can't find the SVG. Can you please send it to mcseem at antigrain.com?

P.S. Thank you guys, I have a tiny chance to become famous Lena! :-)

by Cyphre
postd on Sep 08 2011 at 06:37AM

Hello McSeem! Nice to see you are alive :) Once again thanks for the great Antigrain code. Even if this HW accelerated extension would eventually become a new standard I believe I'll be using AGG as fallback for CPU high-quality fast rendering.

by sopyer
postd on Jul 29 2011 at 10:59AM

Any chance you will release algorithms behind this extension? Is it based on C. Loop and J.Blinn paper on vector graphics and OpenGL red book trick for polygon rasterization using stencil? Also I wander what is the point to release it as NV OpenGL extension instead of standalone library. I just have implemented similar approach and I have not used anything vendor or API specific to make it work...

by Mark Kilgard
postd on Jul 29 2011 at 01:33PM

Good question, sopyer.  You can review the NV_path_rendering specification to learn about the rendering model.  It explains all the gory details of how the OpenGL state machine affects the point containment determinations made during path fill and stroke stenciling.

The NV_path_rendering approach takes inspiration from the approaches you cite but makes sure to match the massively parallel and pipelined nature of NVIDIA's CUDA-capable GPUs.  While various efforts have tried to implement path rendering as a layered library atop OpenGL, that approach generally results in underwhelming performance and incomplete feature support.  When path rendering complex scenes (and there are plenty of such scenes in the nvpr_svg demo for you to play with), there are lots of paths and they use the full complement of path rendering features.  For excellent performance, NVIDIA found it makes way more sense to execute algorithms that work below the OpenGL API.  You also get a much simpler programming model this way.

With NV_path_rendering, it is easy to specify a path object in any of a number of forms:

  1. Strings, using either the standard Scalable Vector Graphics (SVG) grammar or the PostScript user path syntax.
  2. Directly from an array of path commands and cooresponding path coordinates.
  3. From the Unicode character point of a TrueType/OpenType system font or one of the standard fonts built into NV_path_rendering.
  4. Weighting two or more existing paths.

Once you've got your path specified, you can transform for rendering by OpenGL's standard modelview, projection, and viewport/depth-range transforms with standard clipping planes applied.  Generating colors, texture coordinate sets, or the fog coordinate is straightforward and this generation can automatically be tied to path space coordinates, eye-space coordinates, or a normalized object bounding box space.  This makes it very straightforward to support the gradients in path rendering standards such as SVG.

The goal with NV_path_rendering is to support the union of all path rendering features in the established path rendering standards.  those standards aren't limited to just "simple" paths that contain only linear segments and quadratic Bezier segments; instead there's support for cubic Bezier segments and partial elliptical arcs as well.  The arcs in NV_path_rendering are parameterized in both the SVG way and the PostScript way.  Likewise correct stroking is hard due to the high-order (in the polynomial sense) nature of the boundary representation of stroked paths; NV_path_rendering goes through exceptional lengths to accurately determine stroked point containment while still being faster than CPU approaches.  And it does this with the full variety of join styles, end caps, dash patterns, dash offsets, dash offset reset modes, and dash caps.  This is what you need to be able to render PostScript, PDF, SVG, etc. content properly.

Another problem with "layered libraries" with OpenGL is libraries tend to assume they can manipulate the OpenGL context's state in ways that make it hard to mix the library's OpenGL usage with the application's OpenGL usage.  With NV_path_rendering, we wanted to make sure that path rendering co-exists with conventional 3D rendering in a really seamless way.  There's a well-defined interaction between NV_path_rendering commands and the rest of OpenGL.

I hope this helps.

- Mark

by msomeone
postd on Jul 29 2011 at 10:29AM

Awesome! Was dreaming about API like this about three years, and now it's released.
I can throw away custom font and vector graphics rendering implementation ontop of OpenGL and use NVpr, it's so nice.
Thanks to NV and all NVpr team, great job!

by ljbade
postd on Jul 28 2011 at 04:19PM

Wow! You guys sure have put a lot of work into this. I researched implementing OpenGL based 2D rendering earlier this year but gave up as I could not get it fast enough... hopefully this API will change that.

I hope the API still fast for offscreen buffer rendering as I need to read the data back to the CPU for PNG compression.

by Mark Kilgard
postd on Jul 29 2011 at 09:33AM

Ljbade, thanks for the feedback.  I think you'll find NV_path_rendering is very fast and because you can mix path rendering with conventional 3D rendering such as depth tested occlusion, projective viewing, and programmable shaders, you can do a lot with NV_path_rendering that you wouldn't easily be able to do with conventional path rendering systems.

As far as speed, yes, NV_path_rendering is very fast.  It is generate 4x to 10x to many more times faster than conventional CPU-based path rendering on a fast GPU.  If you download NVprDEMOS.zip, try this command line:

      nvpr_svg.exe -svg svg/complex/Celtic_round_dogs.svg -animate -cairo

With runs the nvpr_svg (GPU-accelerated SVG viewer demo) on a particular SVG scene showing celtic dogs (feel free to load the SVG in a modern browser).  On my GeForce 480, I get 2210 fps rendering the scene while the Cairo-rendered window (click on each window to measure each renderer's speed) renders at 83 fps.  That's 25+x faster.  If you don't believe the scene is really rendering at these rates, toggle the '=' key to add zooming/rotation to the continuous rendering.

Perfomance definitely varies with the particular scene, but the GPU is much faster than the CPU.  Also keep in mind that CPU-based path rendering eats up your CPU cycles.  So if you spend CPU resources path rendering, you lose those CPU resources for other tasks.  With NV_path_rendering, path objects can be rendered completely by the GPU so you off-load the hard work to the GPU, freeing the CPU for use by your application.

I hope the API still fast for offscreen buffer rendering as I need to read the data back to the CPU for PNG compression.

Good question.  Yes, you can using NV_path_rendeirng to render into OpenGL framebuffer objects (FBOs) just like any other rendering.  There's not currently an example of this usage in the NVprSDK, but it would be straightforward to accomplish.

A few notes...

Use the latest 280.19 beta drivers for best results.  Get them from:

  http://www.nvidia.com/object/win7-winvista-64bit-280.19-beta-driver.html
  http://www.nvidia.com/object/winxp-280.19-beta-driver.html

For those who want to "try out" the GPU-accelerated path rendering:
1)  get the 280.19 or later driver installed (if you already have 275.xx installed that works too)
2)  download the Windows demos from http://developer.download.nvidia.com/assets/gamedev/files/NVprDEMOs.zip
3)  run any of the 14 demos; the nvpr_svg is the most elaborate demo

Hints about using nvpr_svg:

  1. see the ReadMe_nvpr_svg.txt file for complete details
  2. space bar animates the current scene, rotating & zooming, with a frames/second
  3. the 'f' and 'F' keys advance through SVG scenes (you can also pick them from the pop-up menu, right click for it)
  4. you can pan/zoom/rotate the scene; left click and drag zoom/rotates (up/down zooms in/out; left/right rotates clockwise/counter-clockwise), middle click & drag pans (Ctrl+middle click & drag does a "slow" drag to see antialiasing quality)
  5. 'C' (capital C) toggles "warp" points that let you projectively warp any scene; left click and drag the warp points
  6. 'c' (lowercase C) toggles the control points that you can also drag around with the mouse; showing the control points for the scene gives you some idea of the path complexity ('i' prints scene statistics)
  7. The "Antialiasing..." pop-up menu item lets you control samples per pixel; you need the 280.11 driver for this to work right (oops, a driver bug got fixed... expect a crash on 275.xx drivers)
  8. Use the 'n' key toggles a "comparison" window that lets you compare the NV_path_rendering speed to Cairo, Skia, Qt, and Direct2D (on Windows Vista/7 systems).  Once the window appears, there's a pop-up menu to select between different renderers.  The space bar animates the current window (GPU-accelerated or alternative) and both report frames/second numbers.

For non-Windows users, the task is a little more involved since you have to build the demos from the NVprSDK source code found at:

  http://developer.download.nvidia.com/assets/gamedev/files/NVprSDK.zip

To build the NVprSDK code, you'll need a C++ compiler, GNU make, GLUT, FreeType2, and the Cg Toolkit to compile the demos.  See the ReadMe.txt for details.  But you'll get the same demos as in NVprSDK.  Windows programmers can likewise build the demos from source code.  They'll need the DirectX SDK (for nvpr_svg's Direct2D support) and the Cg Toolkit.  Windows programmers can build from the provided Visual Studio 2008 or 2010 projects.

I hope this helps.

- Mark