Freestyle integration into Blender

January 22, 2017

Benchmark tests of Freestyle suggestive contours

Filed under: Update — The dev team @ 5:01 PM

Suggestive contours are feature edges that are not exactly but almost contours from nearby viewpoints.  They convey a lot of shape information that genuine contours tend to fail to deliver.  Freestyle in Blender is capable of computing suggestive contours from input 3D meshes.  They are computed when a few input parameters of relevance are enabled.  First, the Face Smoothness switch in the Freestyle panel of the Render Layers property window needs to be turned on.  In addition, the Suggestive Contour edge type is checked in the Freestyle Line Set panel.

Suggestive contours in Freestyle tend to be short and highly jagged.  The quality of the feature edges can be improved by a couple of configuration parameters in the Advanced Options section of the Freestyle panel: the Sphere Radius and the Kr Derivative Epsilon (respectively set to 0.1 and zero by default).  Setting the former to a smaller value (say 0.0001) than the default value gives finer suggestive contours.  A larger value (e.g., 100) leads to a much longer computing time and hence not recommended.  The Kr derivative epsilon can redefine what suggestive contours are, and setting it to zero is the most reasonable choice.  It is also interesting to set it equal to a small negative number such as -0.00001, which will result in quite different feature lines.

In the rest of this blog post, we address a question of interest from the perspective of Blender artists: how much is Freestyle in Blender capable of computing quality suggestive contours when compared to other pieces of computer graphics software?  To our knowledge, this aspect has been reported very little so far.  The present reality check is also important from developers’ view point in order to validate the Freestyle implementation of suggestive contours.  As a reference implementation, we chose rtsc (version 1.5) developed by the authors of the SIGGRAPH 2003 paper Suggestive Contours for Conveying Shape.  Benchmark cases were selected from their image gallery acknowledging the availability of test models.


Six test models were taken from the rtsc image gallery in the .ply file format.  The models were fed as input to both test programs without extra geometry manipulations except for scaling and rotation.  Pairs of renders generated by Freestyle and rtsc are compared without image retouching (except for image scaling and trimming).  Blue lines are suggestive contours, while silhouettes (occluding contours) are shown in green.  Additional parameters for the tested programs are highlighted below:

  • rtsc: Fade lines = disabled, Draw in color = enabled, Trim SC = enabled, SC thresh = 0.
  • Freestyle: The sphere radius, as well as the minimum 2D length for eliminating micro edges, were tuned on a case-by-case basis to make individual renders similar to the rtsc results.  Actual parameter values are reported below.  The Kr derivative epsilon was set to zero throughout the tests.


Model: armadillo.ply, left: Freestyle (sphere radius = 0.000001; minimum 2D length = 5), right: rtsc.


Model: brain2.ply, left: Freestyle (sphere radius = 0.001; minimum 2D length = 5), right: rtsc.


Model: bunny2.ply, left: Freestyle (sphere radius = 0.0001; minimum 2D length = 10), right: rtsc.


Model: golfball.ply, left: Freestyle (sphere radius = 0.001; minimum 2D length = 5), right: rtsc.


Model: horse2.ply, left: Freestyle (sphere radius = 0.0001; minimum 2D length = 5), right: rtsc.


Model: lucy.ply, left: Freestyle (sphere radius = 0.00001; minimum 2D length = 5), right: rtsc.


Model: lucy.ply, left: Freestyle (sphere radius = 0.001; minimum 2D length = 10), right: rtsc.



  • Overall, the Freestyle implementation of suggestive contours was capable of capturing a majority of the feature edges detected by the reference implementation (rtsc).  This clearly confirms the Freestyle implementation of suggestive contours works fine in general.
  • Freestyle suggestive contours tended to be short (i.e., broken into pieces) and jagged even after the tuning of the input parameters, whereas the rtsc results gave more consistent lines.  This kind of difference deserves code checking and opens additional benchmark analyses on the Freestyle side.
  • There was a minimum sphere radius value that led to visual differences (the reported values might not be the minimum).  Further decreasing the sphere radius didn’t change the computed suggestive contours.

Ridges and valleys in Freestyle

The reference program also helped find out that ridges and valleys in Freestyle are something different from what these feature edges are supposed to be.  For example, the second test case using lucy.ply as input gave the following render by Freestyle when ridges and valleys were drawn (in red) in addition to suggestive contours and silhouettes.


The following renders by rtsc show ridges (left), valleys (center), and so-called “zeros of mean curvature (H = 0)” (right) in addition to suggestive contours.


Freestyle ridges and valleys most look like the zeros of mean curvature.  This finding also opens further investigation.

July 7, 2014

Line color priority

Filed under: Update — The dev team @ 2:46 PM

Line color priority is one of per-material line color settings introduced in a recent commit (7915d7277ac8).  This parameter allows artists to fine tune line colors at material boundaries.  The present blog post is a quick demonstration of the new feature.

The first image below suffers from a visual artifact that alternate line colors appear at material boundaries.  This problem is caused by the lack of information based on which one of the two materials could be chosen to determine the line color at material boundaries.

Line color priority is intended to address the documented issue.  Specifically, line color priority is an integer value (zero by default) specified for each material, and is used to pick up the material having a higher value at material boundaries.

The second image below shows an improved result where the priority values of the blue and white materials were set to 1 and 0, respectively (see the third image below for line color settings of the blue material).  Since a higher priority was given to the blue material, now lines along material boundaries are always drawn in blue.

priority_default_tn priority_blue_tn material_ui_tn

April 9, 2014

Experimental variable line thickness shaders

Filed under: Update — The dev team @ 2:24 AM

A discussion in the bf-blender-npr mailing list turned out to be productive with new ideas and artist-driven coding experiments.  This blog article presents two experimental Python style modules for Freestyle in Blender as a result of the discussion.  The scripts have been tested with Blender 2.70.

Crease angle dependent thickness


Video clip:

This style module draws crease lines with variable line thickness depending on the angle between the two faces on both sides of each crease line segment.

from freestyle.chainingiterators import *
from freestyle.predicates import *
from freestyle.shaders import *
from freestyle.types import Operators
import math

class CreaseAngleDependentThicknessShader(StrokeShader):
    def __init__(self, angle1, angle2, thickness1, thickness2):
        self.__a1 = angle1
        self.__a2 = angle2
        self.__t1 = thickness1
        self.__t2 = thickness2

    def shade(self, stroke):
        delta_a = self.__a2 - self.__a1
        delta_t = self.__t2 - self.__t1
        fac = 1 / delta_a
        for v in stroke:
            fe = v.first_svertex.get_fedge(v.second_svertex)
            if not fe.is_smooth:
                angle = math.degrees(math.acos(
                if angle < self.__a1:
                    t = self.__t1
                elif angle > self.__a2:
                    t = self.__t2
                    t = self.__t1 + delta_t * (angle - self.__a1) * fac
                #print(angle, t)
                v.attribute.thickness = (t/2, t/2)

upred = AndUP1D(QuantitativeInvisibilityUP1D(0), pyNatureUP1D(Nature.CREASE))
Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(upred))
shaders_list = [
    CreaseAngleDependentThicknessShader(70, 120, 5, 0),
    ConstantColorShader(0, 0, 0),
Operators.create(TrueUP1D(), shaders_list)

Curvature dependent contour line thickness


Video clip:

This style module draws contour lines with variable line thickness as a function of radial curvatures.  In short, curvatures are a property of surface that tells you how quickly the surface bends.  With the script below, thicker contour lines are drawn when the contours lie on more quickly bending areas of the surface, while thinner lines appear in more flat areas.

from freestyle.chainingiterators import *
from freestyle.predicates import *
from freestyle.shaders import *
from freestyle.types import Operators
import math

class VariableContourThicknessShader(StrokeShader):
    def __init__(self, Kr1, Kr2, thickness1, thickness2):
        self.__k1 = Kr1
        self.__k2 = Kr2
        self.__t1 = thickness1
        self.__t2 = thickness2

    def shade(self, stroke):
        delta_k = self.__k2 - self.__k1
        delta_t = self.__t2 - self.__t1
        fac = 1 / delta_k
        for v in stroke:
            c1 = v.first_svertex.curvatures
            c2 = v.second_svertex.curvatures
            if c1 is None and c2 is None:
                v.attribute.thickness = (0, 0)
            if c1 is None:
                Kr = abs(c2[4])
            elif c2 is None:
                Kr = abs(c1[4])
                Kr = abs(c1[4]) + v.t2d * (abs(c2[4]) - abs(c1[4]))
            if Kr < self.__k1:
                t = self.__t1
            elif Kr > self.__k2:
                t = self.__t2
                t = self.__t1 + delta_t * (Kr - self.__k1) * fac
            #print(Kr, t)
            v.attribute.thickness = (t/2, t/2)

upred = QuantitativeInvisibilityUP1D(0)
Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(upred))
shaders_list = [
    VariableContourThicknessShader(0.001, 0.01, 0, 10),
    ConstantColorShader(1, 0, 0),
Operators.create(TrueUP1D(), shaders_list)

BF Development Fund project on Freestyle and NPR

Filed under: Update — The dev team @ 2:20 AM

Thanks to the sponsors of the Blender Foundation (BF) Development Fund, a full-time job position has been granted for the development of non-photorealistic (NPR) rendering capabilities in Blender.  The project duration is three months from the 1st of April, 2014.  The proposed work components include Freestyle performance improvements in terms of time and space, better artists experience in interactions with Freestyle, and more general Blender development, all in view of an extensive use of Freestyle and Blender NPR features in the production of the Gooseberry open film.  Below you will find a document summarizing the project elements foreseen in the upcoming months:

As a fresh restart, this blog is going to be used for posting updates on relevant activities in the newly funded project.

Interested Blender artists are kindly invited to the bf-blender-npr mailing list for discussing Freestyle and NPR topics.

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!

August 5, 2012

Development updates on August 5

Filed under: Update — The dev team @ 11:40 AM

Since the last blog update, the Freestyle branch made a slow but steady progress.  Here is a brief summary of new elements and user-visible changes in the Freestyle rendering engine and its user interface.

General usability improvements

1. New options for specifying unit line thickness has been added in the Post Processing tab in the Render buttons.  These options allow you to define unit line thickness in two different modes:

  • Absolute mode: The unit line thickness is given by a user-specified number in units of pixels.  The default value is 1.
  • Relative mode: The unit line thickness is scaled by the proportion of the present vertical image resolution to 480 pixels.  For instance, the unit line thickness is 1 with the image height set to 480, 1.5 with 720, and 2 with 960.

2. A long-standing bug due to an inappropriate removal of singular points in stroke creation was fixed.

The previous stroke creation procedure was trying to clean stroke topology by removing overlapping stroke vertices in the same 2D location.  The idea was to avoid having to address this kind of singularity during subsequent stroke shading.  In-depth analyses revealed, however, that this was a wrong way to ensure clean stroke topology, since just deleting overlapping vertices may break the continuity of the underlying series of FEdges on top of which the stroke has been built.  Such a break of linked FEdges was a major cause of frequent failure in CurvePoint::getFEdge().

The implemented solution aims to address the singularity issue by adding small offsets to the 2D location of overlapping vertices and making them non-overlapping to each other.  Since the offsets only result in sub-pixel differences, the impact on visual outcomes is expected to be negligible.

In addition, an attempt was made to fix an instability issue in stroke rendering due to a failure of Normal2DF0D with smooth FEdges.  The fix is to avoid generating new FEdgeSmooth instances whose length is shorter than epsilon.

3. The response of the ESC key for stopping Freestyle rendering has been improved throughout the rendering process.  The rendering with Freestyle consists of several steps including: (1) mesh data loading, (2) winged edge construction, (3) silhouette edge detection, (4) view map construction, and (5) stroke drawing.  All these steps have been extended to frequently check if the ESC key is pressed, so that users can abort time-consuming rendering at any point of time.

4. New operators have been introduced for adding the data paths to Freestyle edge/face mark properties of selected edges/polygons into the active keying set.  These operators are intended to make it easy to keyframe a number of Freestyle edge/face marks.

  • Add Edge Marks to Keying Set (bpy.ops.scene.freestyle_add_edge_marks_to_keying_set)
  • Add Face Marks to Keying Set (bpy.ops.scene.freestyle_add_face_marks_to_keying_set)

These operators are accessible from the Space bar menu by entering the operator names, as illustrated in the following screen captures.


5. The lower limit of Kr derivative epsilon has been changed from 0 to -1000 so as to permit a negative value.

New elements in the Parameter Editor mode

1. New options for controlling the position of stroke thickness have been introduced.  These options enable a better control on the position of stroke thickness with respect to stroke backbone geometry.  Three predefined positions are:

  • center: thickness is evenly split to the left and right side of the stroke geometry.
  • inside: strokes are drawn within object boundary.
  • outside: strokes are drawn outside the object boundary.

Another option called “relative” allows you to specify the relative position by a number between 0 (inside) and 1 (outside).

The following renders show the effects of the three predefined positions.


The following render is an example of the relative position with the thickness ratio set to 0.3.

The thickness position options are applied only to strokes of the edge types SILHOUETTE and BORDER, since these are the only edge types defined in terms of object boundary.  Strokes of other edge types are always drawn using the “center” option.

The thickness position options are also applied only when chaining is disabled or the Plain chaining is used with the Same Object option enabled (as shown below).  The default “center” positioning is used otherwise.

2. Sphere radius and Kr derivative epsilon have been recovered in the Parameter Editor mode.  Several users requested the recovery as the removal of the two parameters was considered over-simplification for advanced users (see the blog article on April 2 for the rationale of the removal).  As in the Python Scripting mode, the two parameters are in the “advanced edge detection options” section and disabled by default.

Bug fixes

  • Fix for Freestyle-related UI components showing up in the Render buttons when Cycles was selected.
  • Fix for NaN (not a number) in the Z component of projected points.  This issue arose when the Z depth of the bounding box of the scene being rendered is zero.
  • Fix for emitted objects of a particle system not rendered properly.  The problem was reported by octane98 with a sample .blend file.  Thanks!
  • Fix for the WithinImageBorderUP1D predicate not working with a ViewEdge such that none of the SVertices are within the image boundary but an FEdge intersects with the image boundary.
  • Fix for X and Y aspect ratios not working properly with Freestyle stroke rendering.  The problem was reported by octane98 through the BA Freestyle thread.  Thanks!
  • Fix for the Selection by Group not working correctly when the specified group was empty. The problem was reported by vicentecarro with an example .blend file to reproduce the issue.  Thanks!
  • Fix for a crash due to a corruption of data for addressing degenerate triangles in imported mesh data.
  • Fix for a crash in the single layer mode with Freestyle enabled.

Freestyle user activities

Freestyle branch users are active and keep sharing their results and new ideas through the, personal blogs, and so on.  Recently mclelun has started new project “the Overweight Boss” using Blender and Freestyle.  Here is a couple of excellent results from him.  The dev team is very grateful for his achievement! is a new hub site for gathering information about non-photorealistic (NPR) rendering with Blender.  Freestyle tips and results are part of the new site’s main topics.  In addition, a new discussion thread has been open for collecting feature requests, new ideas and thoughts to improve Freestyle.  If you have something that you want to see in Freestyle in the future, you are definitely encouraged to post it in this discussion thread.

April 3, 2012

Development updates on April 2

Filed under: Update — The dev team @ 1:45 AM

The Blender Freestyle branch spent a few months of relatively less development activities due to limited time resources.  Here is a short summary of new features and bug fixes since the last blog update.

New features and changes in the Parameter Editor mode

The following two stroke geometry modifiers have been added.

  • 2D Offset: Adds two-dimensional offsets to stroke backbone geometry.
  • 2D Transform: Applies two-dimensional scaling and rotation to stroke backbone geometry.

The 2D Offset geometry modifier has four parameters: start, end, X and Y.  The first two parameters add offset values in the direction perpendicular to the stroke direction.  The offset values are linearly interpolated from the beginning to the end of a stroke.  The X and Y parameters add absolute horizontal and vertical offset values.  The following image illustrates the effects of these parameters.

The 2D Transform modifier transforms stroke geometry by X and Y scaling factors and a rotation angle.  The center (pivot) of these 2D transformations can be: the stroke center, the beginning and the end of the stroke, a point along the stroke (specified by a value between 0 and 1, called stroke pivot parameter), and absolute 2D point (specified by X and Y coordinate values).

Example renders below demonstrate the effects of 2D offset, scaling and rotation (from left to right), where three external contours were modified separately with different modifier parameters.


With a view to a better use of screen space, the locations of edge type options within the Selection by Edge Types have been rearranged as shown below.  Frequently used edge types come first, and less used ones come after.

The two edge types “Ridge” and “Valley” have been unified into “Ridge & Valley”, since the Valley edge type is merely an alias of Ridge in the present Freestyle implementation.

Sphere radius and Kr derivative epsilon were removed from the Parameter Editor mode.  Now sphere radius of 1.0 and Kr derivative epsilon of 0.0 are used by default.  The rationale of the removal is two-fold: little predictability and very minor artistic values.  The effects of these parameters are hard to estimate in advance, which likely leads to a frustration of users due to repeated trials and unpredicted results.  Therefore, the two parameters are considered to have quite limited artistic values.  Proper definitions of the two parameters more and less require the knowledge of differential geometry and would not make sense to most artists for which the Parameter Editor is intended.

Sphere radius and Kr derivative epsilon are still available in the Python Scripting mode, but now in an “advanced options” section that is disabled and hidden by default.  In this way new users are properly warned, while expert users with specific technical needs can enable these options if they want.  The same default values mentioned above are used when the two parameters are disabled in the Python Scripting mode.

Fix for degenerate triangles in imported mesh data

A line visibility issue was identified by means of a .blend file supplied by a branch user.  The issue was caused by so-called degenerate triangles that are triangular faces whose area is zero.  It is useful to distinguish two types of degenerate triangles as follows.  Let A, B and P denote the three vertices of a triangle.  The triangle is said a degenerate triangle if:

  1. A and B are in the same position in the 3D space; or
  2. the distance between point P and line segment AB is zero.

Note that the former condition is a special case of the latter.  Degenerate triangles in the first form can be (and have been) addressed in the same way as the standard Remove Doubles command in Blender.  Those in the second form, on the other hand, are more difficult to address and thus require special treatment.

For what concerns line visibility in Freestyle, degenerate triangles become harmless if they are transformed into non-zero area triangles.  Hence, a preprocessor of imported mesh data from Blender to Freestyle was implemented to resolve degenerate triangles in the second form, where two different approaches to the solution of the issue have been attempted.

One approach is to check if a degenerate triangle is part of a quad face.  This checking is easily done by testing if three of the four vertices are colinear (i.e., they are lying on a line).  If that is the case, then depending on how the quad is separated into two triangles, one of them can be a degenerate triangle.  Degenerate triangles of this form is addressed by rotating the diagonal edge of the quad face without affecting the visual outcome.

The other approach is to add a very small offset to P so that the resulting triangles have a non-zero area.  The visual side-effect of this solution is likely to occur at a sub-pixel level, and thus considered negligible.

Several other attempts were made to explore the best way to handle degenerate triangles, and the two solutions above are found the most effective.  The dev team still keeps close eyes to the line visibility issue due to degenerate triangles.  More fixes will follow if some other sources of degenerate triangles are identified.  Problem reports on this matter are very welcome.

Bug fixes and miscellaneous improvements

The following user-visible bugs were fixed, many of which were kindly reported by branch users.

  • Color management was not working properly with Freestyle.
  • Color ramps were not immediately updated during the manipulation of a color picker.
  • The Selection by Image Border was not working correctly.
  • A crash due to invalid pointers within a copied line set was fixed.  Now the line set buffer is cleared when a new .blend file is opened, so that a line set may not be copied and pasted between .blend files.
  • The Backbone Stretcher geometry modifier had a hard-coded limit that the effect was applied to stokes with 2D length longer than 50.  Now the geometry modifier can be applied to strokes of any length.
  • A crash with FSAA enabled and Freestyle disabled was fixed.
  • Line style names were not made unique after a new name was set.

The dev team is grateful to branch users for their active testing of the software and problem reports.

Freestyle artwork by branch users

An increasing number of Blender artists have been sharing their results with Freestyle, through the Freestyle thread, personal blogs, tweets and so on.  Here, two excellent pieces of artwork by RONIN (left) and s12a (right) are presented.


Many thanks for your contributions, RONIN and s12a!

December 19, 2011

Development updates on December 18

Filed under: Update — The dev team @ 1:02 AM

Since the last blog update, the development in the Blender Freestyle branch mainly focused on stability improvements, as well as on an extended capability of the Parameter Editor mode, which is intended to be an artist-friendly GUI for interactive manipulation of line style parameters.  Major additions and changes are highlighted as follows.

Updates in the Parameter Editor mode

The function of the ‘+’ button to the right of a line style name in the Freestyle: Line Style tab has been changed so as to make a copy of the active line style instead of creating a new line style with default settings.  This is meant to be consistent with the creation of new data blocks in other parts of Blender (for instance, creating a new material will result in a copy of the active material).  Also a button to make a single-user copy of a line style (i.e., the button that indicates the number of users) has been implemented.

Copy and paste operations for line sets have been added to make it easy to duplicate the settings of a line set.

It is recalled that line sets have a reference to a line style.  When the settings of a line set A having a reference to a line style X is pasted into a line set B, the latter line set will have a reference to X.  That is, the paste operation changes the line style references, but does not modify the settings of line styles.  If you also want a copy of the referenced line style after the paste operation, you have to make it using the copy operation for line styles as described above.

An extended set of conditions for feature edge selection by edge types has been introduced.  Each edge type check button in the Selection by Edge Types has now an associated toggle button to exclude the edge type from the feature edge selection.  This allows you to select, for instance, those edges that are silhouette lines but not external contours by enabling the two edge types and also the toggle button for external contours, as shown in the screen shot below.

A new option for disabling the chaining of feature edges has been added to the ‘Stroke’ panel of the Freestyle: Line Style tab.  This option is useful for examining the initial set of feature edges in the view map.

New options for splitting chains of feature edges by a minimum and maximum 2D angle and by a 2D length limit have been added to the ‘Stroke’ panel of the Freestyle: Line Style tab.  These options are useful for splitting long strokes into small pieces.  See the example renders of the Guiding Lines geometry modifier below for an example use of splitting by 2D length.

Three new stroke geometry modifiers have been implemented.

  • Polygonization
  • Guiding Lines
  • Blueprint

The Polygonization geometry modifier transforms smooth strokes into jagged polylines.  The “error” parameter specifies how much deviation is allowed from the original stroke geometry (the larger the error parameter is, the more jagged the resulting polylines are).  The following test renders illustrate the effect of the Polygonization modifier: (a) without applying the modifier, strokes along arcs are smooth; (b) with the polygonization modifier applied with the error parameter set to 5, the strokes are transformed into jagged polylines; and (c) the error parameter set to 20 gives more jagged polylines.


The Guiding Lines geometry modifier replaces a stroke with a straight line connecting both ends of the stroke.  This modifier will produce reasonable results when strokes are short enough, because shorter strokes are more likely to be well approximated by straight lines.  Therefore, it is recommended to use this modifier together with the splitting options (by 2D angle or by 2D length) mentioned above.  The following images show how splitting and geometry modifiers can be combined: (a) smooth strokes along arcs are split into small pieces by the 2D Length option; (b) the Guiding Lines gemoetry modifier is then applied to approximate the split stroke segments by straight lines; and (c) the Backbone Stretch geometry modifier is further applied to extend both ends of each straight stroke.


The render below is a combination of the Guiding Lines and Spatial Noise geometry modifiers.  Both modifiers were applied to two identical line sets to duplicate the guiding lines.  The line sets contain only external contours.  The Spatial Noise modifier was applied before the Guiding Lines modifier, so that two sets of guiding lines display some variability.

The Blueprint geometry modifier produces a blueprint using circular, elliptic, and square contour strokes.  A blueprint here refers to those lines drawn in the beginning of free-hand drawing to capture the silhouette of objects with a simple shape such as circles, ellipses and squares, as illustrated below.


The Perlin Noise 1D geometry modifier had an issue that noise frequency was relative to the stroke length (i.e., the number of noise displacement values was the same for strokes of different lengths).  This resulted in very noisy short strokes and much less noisy long strokes.  Now the noise frequency is relative to the distance from the starting point of a stroke.  That is, two strokes of the same length will be distorted by the same number of noise displacement values, whereas longer strokes will have more noise displacement values along stroke.

Stability improvements

  • A fix was made to address duplicated feature edges due to a numerical instability of line clipping by near/far Z planes.
  • View map construction was not properly taking face marks into account.  This caused incorrect (and unpredictable) feature edge selection results when face marks were used.
  • A crash caused by temporary scenes for stroke rendering was fixed.  Freestyle generates a temporary scene containing a number of stroke meshes to achieve stroke rendering using the Blender internal renderer.  This temporary scene may appear in the outliner and undergo user interaction when the stroke rendering takes a long time.  The crash was due to the deletion of the scene without taking care of references to the scene from screens, one of which was the outliner.
  • The interaction between Blender and Freestyle was revised to address a crash when two scenes in the compositor have different render resolution (i.e., image width and height, scaled by a percent parameter).
  • Stroke rendering instability with stroke geometry shaders was addressed.  Stroke::Resample(int nPoints) was not properly working when a wrong value was returned from Stroke::getLength2D(), resulting in repeated warning messages “Warning: incorrect points number” during stroke rendering.  The main cause was that stroke geometry shaders did not update the two-dimensional (2D) length (also referred to as curvilinear abscissa) after they modified the 2D points of stroke vertices.  Now all stroke geometry shaders make explicit calls for Stroke::UpdateLength() that has been introduced for recomputing the 2D length.
  • A bug in Operators.recursiveSplit() that splitting could not take place within the last segment of a chain was fixed.

Remarks on the merge into the trunk

The dev team has been receiving an increasing number of questions from branch users concerning the merge into the trunk (i.e., official release of Blender).  It is remarked that the merge has already been agreed with the core Blender developers of the trunk, and the only major question is when the merge is done.

In June 2010, the dev team defined a list of unfinished components that need to be done before the merge is finally asked.  The list includes three major components: (a) GUI for the Parameter Editor mode; (b) feature edge detection at the intersection of two faces; and (c) Freestyle Python API improvements.  Subjective achievement rates of the three components are 90%, 0%, and 80%, respectively.  In other words, the Freestyle branch needs more development before it gets ready for code review that is required for the merge to happen.

At the moment the official release of Blender 2.62 is planned in February 2012, but it is unlikely that Freestyle is included into this release because of the short deadline for code review in January.

Considering an admittedly limited amount of time resources, it is still difficult to predict when all the unfinished components are done and the code review for the merge can be asked.  We appreciate the understanding and patience of branch users.

October 25, 2011

Development updates on October 25

Filed under: Update — The dev team @ 12:47 AM

Since the last blog post, branch development mainly focused on stability improvements of the Freestyle renderer and new functionality for fine control of feature edge selection.

Stability improvements with the face smoothness option

Several branch users kindly reported that Freestyle failed when the Face Smoothness option was enabled and object materials were used to determine line colors.  When the Face Smoothness option is enabled, the view map computed from a given 3D scene is populated by not only sharp FEdges (i.e., edges in the original meshes) but also smooth FEdges (i.e., newly constructed edges across faces).  This situation often resulted in a failure of the getFEdge() method (defined in the Interface0D class and its subclasses) used to obtain the FEdge between two given 0D elements (such as SVertices and CurvePoints).  The instability of getFEdge() caused many related issues because the method is widely used in other predicates and functions that rely on it.  The most prominent example of related user-visible problems is a failure of the built-in MaterialF0D class that retrieves object materials of given 0D elements, as seen in the problem reports from branch users.

The persistent failure of getFEdge() was resulting from several bugs in the view map construction algorithm.  These bugs were fixed through careful code revisions and intensive testing.  Also, the built-in MaterialF0D turned out to be incapable of handling Curve objects (such as chains and strokes), so that a new CurveMaterialF0D class has been introduced to address the material retrieval in the case of Curve objects.

These changes have improved the stability of the renderer with the Face Smoothness enabled.  The dev team is very grateful to those branch users who provided the bug reports together with .blend files to reproduce the issues.  The .blend files were indeed indispensable test cases during the bug hunting.

Fine control of feature edge selection with mesh face and edge marks

With the aim of allowing for fine control of feature edge selection, new “face marks” and “edge marks” have been introduced in mesh data blocks.  In the edit mode of a mesh object, face marks can be put to selected faces by choosing Mesh > Faces > Mark Freestyle Face from the menu of a 3D View window or Ctrl-F > Mark Freestyle Face from the context menu.  Similarly, edge marks can be put to selected edges by Mesh > Edges > Mark Freestyle Edge or Ctrl-E > Mark Freestyle Edge.  These marks should work fine with the Subdivision Surface and Mirror modifiers.

Moreover, two new conditions for feature edge selection have been added to the Parameter Editor mode, as described below:

  1. The Selection by Edge Types option now includes the new Edge Mark type, which can be used to (de)select feature edges having edge marks.  This option can be used to add to (or remove from) the view map arbitrary edges of mesh objects.
  2. Selection by Face Marks option has been newly introduced, in which face marks are used for feature edge selection in two ways.  One option is called “One Face” which is to (de)select feature edges if one of faces on the left and right of each feature edge has a face mark.  The other option is “Both Faces” to (de)select feature edges if both faces on the left and right have a face mark.  Those feature edges that meet the conditions are selected if the Inclusive option is enabled; they are deselected if the Exclusive option is turned on.

The following screenshot shows the new GUI controls (highlighted in red) based on face and edge marks.

Edge marks are useful when you want to draw lines along particular mesh edges.  The following example images demonstrate the use of edge marks.


The image on the left shows a sphere mesh with edge marks (in the edit mode).  In a 3D View window, edge marks are displayed in light green.  The image on the right is a render without the Edge Mark type enabled in the Selection by Edge Types option (the black line shows the silhouette of the sphere).  The image below is a rendering result with the Edge Mark type enabled.  The blue lines indicate those resulting from mesh edges with edge marks.

Face marks are useful for removing lines from certain portions of mesh surfaces.  Suppose that two faces of the default cube have face marks as shown in the image on the left below.  Marked faces are displayed in light green.  The image on the right is a rendering result without using the Selection by Face Marks option.


The following images show how rendering results vary with four combinations of the Inclusive/Exclusive and One Face/Both Faces toggle options.  Notice that only the edge between the two marked faces is (de)selected when the Both Faces option is used, while all the edges touching the marked faces are (de)selected when the One Face option is enabled.



Renders from branch users

In the meantime, branch users have been sharing their renders made with Blender and Freestyle.  Here are some selected rendering results.

Toon rendering of Sintel by jikz (the model is base on Sintel Lite 2.57b by BenDansie):


Architectural line drawing by flokkievids:

Many thanks to jikz and flokkievids for the excellent contributions!

September 25, 2011

Development updates on September 25

Filed under: Update — The dev team @ 4:39 PM

The work on the Freestyle integration into Blender is still ongoing.  Since the last updates, a number of new functionalities and stability improvements has been implemented as summarized below.

Enhancement of the Parameter Editor mode

New line style controls have been added to the Parameter Editor mode that is intended to be an artist-friendly GUI for manipulating line styles without any user efforts on Python scripting.  Recent major additions and changes are described as follows.

  • A new line style option for sketchy chaining of feature edges has been added.  The conventional default chaining method is now called Plain, while the new chaining option is called Sketchy.  The latter option allows for generating chains of feature edges with sketchy multiple strokes.  Both Plain and Sketchy chaining options have the Same Object toggle button in common, whereas the Sketchy option has an additional option called Rounds.  With the Same Object option enabled, only feature edges of the same object are chained.  The Rounds option specifies the number of rounds in sketchy strokes.  The following render shows a visual effect of sketchy chaining (3 rounds, with the Spatial Noise geometry modifier specified to enhance the sketchy appearance of strokes).

  • A calligraphic thickness modifier has been implemented.  This modifier gives strokes variable thickness that looks as if they are drawn with a broad and flat pen for calligraphy.  The following test render illustrates a typical effect of calligraphic thickness.

  • A new parameter called Angle has been added to the Perlin Noise 1D and 2D geometry modifiers to specify a displacement direction in degrees (zero degree indicates the positive X direction).  The following images demonstrate how the Angle parameter makes a difference in rendering results (left: the Angle parameter set to 45 degrees; right: 135 degrees).


  • The behavior of the Perlin Noise 1D geometry modifier has been changed so that it works differently from the Perlin Noise 2D geometry modifier.  Now the Perlin Noise 1D modifier distorts strokes using the curvilinear abscissa of stroke vertices as the input of the Perlin noise generator.  It is remarked that curvilinear abscissa is a scalar value between 0 and 1.  The first and last vertices of a stroke have the values 0 and 1, respectively, and the values for other stroke vertices are linearly interpolated over the stroke.  Therefore, the Perlin Noise 1D modifier gives identical noise displacements to strokes if the strokes have the same length and sampling interval (the latter is specified by the Sampling geometry modifier).  In contrast, the Perlin Noise 2D modifier generates noisy displacements using 2D coordinates of stroke vertices as the input of the noise generator.  Therefore, strokes in different positions in a render will be distorted with different displacements by the Perlin 2D noise generator even if the strokes have the same length and sampling interval.  The differences between the Perlin Noise 1D and 2D modifiers are illustrated in the following test renders.  The image on the left shows a set of vertical lines and another set of star-shaped strokes, both distorted by the Perlin Noise 1D modifier.  Strokes in each set of lines have identical noisy displacements, because of the same stroke length and sampling interval.  The image on the right shows a render of the same scene with the Perlin Noise 2D modifier, which gives different displacements to each of the strokes because of their 2D positions in the image that are different from each other.


  • New line style options for selecting chains by min/max 2D lengths have been added.  Using these options you can select strokes that are longer and/or shorter than specified stroke lengths.

Link and Append

A proper support for the Link and Append commands has been implemented.  Now you can link/append line styles as well as scenes with line styles from within other .blend files.

Stability improvements and bug fixes

An attempt to fix the long-standing issue of occasional infinite straight lines has been made.  The fix is still not the best solution, but seems to yield much better results as illustrated in the following test renders (left: examples of unwanted infinite lines due to the bug; right: infinite lines no longer appear after the bug fix).


Since the solution looks quite effective, a temporary workaround (implemented by means of a custom chaining rule) for infinite straight lines was removed.  This change has resulted in much cleaner strokes.  If you have suffered from a lot of segmented strokes that are supposed to be a single straightforward stroke, then using the latest Freestyle branch would be a solution for the issue.

In addition, several other bug fixes have been made to improve the general stability of the Freestyle renderer.  Most of the bugs were reported by branch users, some with example .blend files for reproducing the problems.  These reports were really invaluable, and we appreciate the feedback from the branch users.

Concluding remarks

That is all for now.  More additions to the Parameter Editor mode as well as further development work on other priority tasks (i.e., unfinished components that must be completed before the merge into the trunk is asked) are anticipated in the next weeks.

Older Posts »

Blog at