Since the last blog post, the Freestyle branch has incorporated just a few commits. One of them is concerned with the support of procedural duplication such as DupliVerts and DupliFaces. Now those objects that are generated by these duplication functionalities should get their edges rendererd by Freestyle as you expect. Emission of duplicated objects from particles should work as well.
In the meantime, the Blender Foundation has released Blender 2.5 alpha 1 that incorporates hundreds of bug fixes, recovers missing functionalities, and offers new features. Congratulations to the development team!
It’s been a while since the last time we presented the renders of the week. This time we have some renders from Rylan Wright (Ronin) who is one of active Freestyle branch users. The first image below is a piece of fan art based on Gurren Lagann. The strong strokes are achieved by a combination of qi0.py and japanese_bigbrush.py together with an orthographic camera. The third image shows a cute female character named Winifred from an upcoming publication illustrated by Rylan. Thank you Rylan for sharing the nice artwork!
Since the last blog update, the Freestyle branch has been improved in several directions as described below.
First, further consolidation of the view map creation was carried out to address “2D intersection out of range” warnings. These warnings lead to “3D intersection out of range” warnings, which are in fact a sign of a possible crash. The cause of the issue was in the way of handling a tolerance threshold for floating-point arithmetic errors. Previously, the Freestyle renderer was calculating the threshold (referred to as the computed epsilon) based on the minimum edge size within the scene being rendered. The computed epsilon could be zero when the minimum edge size was very small. This does not seem to make any sense, so that the epsilon calculation was completely omitted. Now a constant epsilon value is used throughout the view map creation regardless of scenes to be rendered.
Next, pixel-based density and Z depth information was recovered. Availability of the pixel-based density and Z depth information depends on enabled passes of a render layer being rendered.
- Density information is available if the diffuse pass of the render layer is enabled. It is accessible through the DensityF0D and DensityF1D functors provided by the Freestyle Python API. These functors return 0 if the diffuse pass is disabled.
- Z depth information is available if the Z pass is enabled. It can be accessed through LocalAverageDepthF0D and LocalAverageDepthF1D. These functors return 0 if the Z pass is disabled.
In the meantime, the support for transparent stroke colors was once reverted and a new implementation was attempted. The previous approach (described in the last blog article) turned to be inappropriate because of incomplete functionality. When two transparent strokes were overlapping, the stroke drawn first was completely overridden by the stroke drawn after the first stroke, instead of two stroke colors being blended. The new approach relies on a native support of transparent vertex colors in Blender. To make it possible, Blender’s internal renderer has been slightly extended to directly support transparent vertex colors (for those who are interested in internal changes: When Material::vcol_alpha is non-zero, the internal renderer takes MCol::a into account). Now overlapping transparent strokes result in color blending as expected. The left image below shows three opaque strokes having variable stroke colors from red to yellow. The right image shows the same strokes but with variable alpha values from 0.8 (red) to 0.2 (yellow).
The new implementation of transparent stroke colors is considered a kind of dirty hack. It may pose an issue when the Freestyle branch is merged into the trunk. Yet another implementation without modifications to the internal renderer would be much acceptable for the core developers. The dev team is going to look for a better approach.
In addition to the planned updates mentioned above, some improvements were made according to suggestions by the branch users. First, changes were made to allow for escaping from rendering by pressing the ESC key. Key press checks are performed 1) before entering Freestyle, and 2) after the completion of the view map creation. Further additions were made to show the progress of the Freestyle rendering process in the status bar of the render result window. Mesh loading, view map creation, and stroke rendering will be reported as the rendering proceeds.
It is remarked that the latest revision 26980 of the Freestyle branch has incorporated all changes included in the Blender 2.5 alpha 1 release.
Now that the instability issues listed in the new to-do list have been mostly addressed, the next target is to recover missing features enumerated in the to-do list. To begin with, the dev team was working on transparent stroke colors during the last week.
In Freestyle, strokes to be rendered are represented with triangle strips. Stroke colors can be constant throughout a stroke, as well as variable for each triangle. Therefore, strokes are rendered by means of vertex colors in Blender. Stroke colors are specified in the RGBA format, whereas vertex colors do not have an alpha component (as a matter of fact, the internal MCol data structure for holding vertex colors has an alpha value, but the Blender internal renderer does not use it). This latter fact makes it difficult to render transparent stroke colors using the Blender internal renderer.
One approach to realize transparent stroke colors is to define transparent materials and assign them to triangles, instead of relying on vertex colors. It is remarked, however, that the maximum number of materials per mesh is 65536. This means that variable stroke colors cannot attain a very high gradient resolution.
Another approach is to employ a different general-purpose 2D rendering engine (such as Cairo) instead of using the Blender internal renderer. In fact, using the internal renderer for stroke rendering in Freestyle is a tricky idea, because Freestyle is a post-processing engine like the compositor and sequencer and thus the internal renderer is considered to have finished its job before Freestyle is invoked. Freestyle creates a temporary scene of its own to render strokes using the internal renderer, which Brecht described as “it looks like a hack.” However, employing an external 2D rendering engine imposes an extra software dependency that would complicate not only code maintenance by the dev team but also user-side build processes in various platforms. These considerations have motivated the use of the Blender internal renderer for stroke rendering in Freestyle.
Back to the problem of implementing transparent stroke colors, we decided to remain with the Blender internal renderer. Since vertex colors do not directly deal with transparency, we here employ a two-pass rendering approach as follows. First, the alpha component of an image is rendered by utilizing the red component of vertex colors as the alpha component of stroke colors (1st pass). The render result is saved into a temporary buffer. Then, the vertex colors of stroke meshes are replaced with RGB values, and the RGB components of the image are rendered (2nd pass). Finally, the alpha and RGB components are merged to produce the render result in the RGBA format. This method has been implemented in revision 26695 of the Freestyle branch. Any kind of feedback on this matter would be greatly appreciated.
In the previous blog article, we reported a crash in rendering complex scenes. The problem turned to be the consequence of an “out of memory” error during stroke rendering. When objects exist out of the view frustum and near the near clipping plane, feature edges in the 3D camera coordinate system are projected to an extremely far location out of the camera view in the 2D image space. These feature edges result in very long strokes with a large number of stroke vertices, which temporarily require a significant memory storage, possibly causing a fatal “out of memory” error. This problem was partially addressed by omitting unnecessary stroke vertices just before the stroke rendering. There is no user-visible negative side effect. Further memory usage improvements are possible on the users’ side (i.e., in a style module) by explicitly selecting feature edges within the camera view. This can be done by applying a custom edge selection predicate as follows:
scene = Freestyle.getCurrentScene()
w = scene.render_data.resolution_x
h = scene.render_data.resolution_y
def __call__(self, inter):
for v in [inter.A(), inter.B()]:
x = v.getProjectedX()
y = v.getProjectedY()
if 0 <= x <= w and 0 <= y <= h:
If you have got a number of “strip vertex 0 non valid” warning messages followed by a crash, then try using the WithinCameraViewUP1D predicate to exclude those feature edges that do not appear in the rendering result. User-side memory consumption contol of this kind should substantially improve the stability of the renderer.
We then moved on to improvements of mesh importing. Now the Freestyle renderer can deal with mesh deforming modifiers including Curve, Mesh Deform, Cloth and Soft Body. Previously, mesh vertices imported from vlak nodes were transformed from the camera coordinate system to the object local coordinate system. This causes a difficulty in recovering mesh vertices in the object local coordinate system when mesh deforming modifiers have been applied. Now the view map creation is carried out based on mesh vertices in the camera coordinate system. This approach requires less transformation matrix operations and thus is faster and less affected by numerical errors.
We also fixed a bug in the handling of aspect ratio settings. The bug caused a strange Y-direction offset of strokes. Now the aspect ratio settings are properly respected.
Finally, we worked on orthographic camera support. Silhouette edge detection and view map creation have been enhanced, and now both perspective and orthographic cameras are supported. The following image is a test render for a comparison of the two camera modes.
Comments, problem reports, and any kind of feedback are welcome as usual. Have fun!