Freestyle integration into Blender

October 23, 2012

Development updates on October 23

Filed under: Update — The dev team @ 9:09 PM

Development in the Freestyle branch for the last two months was kind of quiet but still includes several important bug fixes and improvements in rendering stability and quality.  Here is a short summary of code base updates from a technical perspective.

Code base updates

1. Experimental fix for incorrect view edge visibility

Given a 3D scene populated with mesh objects, Freestyle generates a data structure called view map consisting of view edges.  Each view edge is basically a polyline, i.e., a series of connected straight edges (referred to as FEdges) originated from the input mesh objects.

The problem addressed here is an ages old issue that the visibility of view edges in the view map may be incorrect. The main cause of this issue is that view edges are constructed from a series of FEdges without testing the visibility of individual edges being concatenated.  In a subsequent processing stage the view edges are split into pieces if two view edges intersect with each other in the 2D image coordinate system.  The visibility of the view edges is then computed by taking account of occluding faces in the 3D scene.  In many cases this procedure results in correct line visibility, but not always (that is the problem).

A simple solution experimentally implemented here is not to chain FEdges at all.  Instead, view edges are constructed from at most one FEdge now.  This leads to better line visibility results, but at the cost of a much larger view edge count, which may impose a performance penalty in the following processing stages.  For now this solution is only applied to sharp FEdges (roughly corresponding to edges in the input mesh data; specifically, silhouette, crease, border, edge mark, contour, external contour, and material boundary).

A better solution would be to reorder the three steps of view edges construction mentioned above, i.e., first splitting FEdges at 2D intersection, computing the visibility of the FEdges, and then concatenating them to build view edges.  This solution will require a bigger refactoring, and thus is left for future work at the moment.

2. Performance improvements of temporary scene generation for stroke rendering

Two-dimensional strokes (e.g., silhouette and crease lines) are automatically generated from a given 3D scene and superimposed on top of the Combined pass.  For this purpose, a temporary scene populated by mesh data representing the 2D strokes is created and rendered with the Blender Internal (BI).

Individual strokes are translated into distinct mesh objects, resulting in a large number of mesh objects. This is especially true when chaining is disabled and strokes are made of at most one view edge.  Because of the aforementioned change in the view map construction, the view map is likely populated by a large number of view edges (e.g., on the order of ten thousand).  As a result, the temporary scene generation may take an appreciable amount of time.  This issue was reported by a branch user with a fairly complex 3D scene that results in more than 11000 strokes.

In a discussion of this issue in the bf-committers mailing list, Joshua Leung (aligorith) kindly provided the dev team with insightful performance analysis results concerning the generation of many mesh objects at once.  As a matter of fact, mesh objects are full Blender objects and not intended to be a lightweight data structure for quick throwaway geometry generation in a time-critical loop.  A solution suggested by Joshua is to extend the BI to render stroke meshes through a new lightweight data structure specifically designed for that purpose.  Another possible direction is to rely on an external 2D rendering engine as discussed earlier.  Because of other priority tasks in the branch development, these solutions are kept for future options.

For now, a quick attempt was made to optimize the performance of temporary scene generation directly based on the performance analysis results by Joshua.  The following plots compare the performance of stroke mesh generation before (left) and after the performance optimization (right).


The performance improvement is significant with the average time per stroke 15 times shorter than the non-optimized timing result.  Still it can be seen that the elapsed time per mesh object tends to increase over time (because of a linear search over existing objects in the scene to make object names unique).  Additionally, there is some non-linear time component, whose source is unknown at the moment and further performance analysis is required.

3. Additional improvements

  • Fix for OCIO-based color management not working properly with Freestyle.
  • New button to make a copy of the active modifier in the Parameter Editor mode.  Code contribution by flokkievids, thanks!

User artwork showcase

An active user base is a key for a successful free software project.  In this sense the Freestyle integration project is very well supported by an increasing number of computer graphics artists all over the world.  Here is a mini gallery of selected artwork by three branch users.

“Fries” by Rylan Wright (RONIN) is a funny stop motion animation clip showing a conversation between two friends of him trying to figure out what to have for lunch.

The following fan-art image of Japanese Anime “Kei-On!” is done by Mohe & Shiratama (Moonlight Jellyfish).  Their modeling and rendering workflow is illustrated in this blog article (in Japanese).

“Japanese Railway’s 140th Anniversary” by mato.sus304 is a series of cool scenery shots showing trains in urban areas.  A making-of blog article about the production workflow of this movie clip is available here (in Japanese).

Thank you RONIN, Mohe & Shiratama, and mato.sus304 for using Freestyle for the excellent artwork!


Blog at