GSoC 2018 project: Implementing a Hair Shader for Cycles
Open, NormalPublic


Hi all,

This is the Phabricator task for my GSoC 2018 project. Please have a look at it, and comment if you have any feedback, expectations, etc.
I'll be making subtasks later for each part/feature/documentation item.

Thanks in advance!

Implementing a Hair Shader for Cycles


Realistic hair or fur is essential when creating a plausible virtual world. In feature animation, this is often used to define the signature look of characters; examples include Pixar’s *Brave* (Iben et al. 2013), and Walt Disney Animation Studios’ *Tangled* (Sadeghi et al. 2010; also Ward et al. 2010) and *Zootopia* (Chiang et al. 2016).

Currently, Cycles has a working hair shader (wiki page, sources), based on Marschner et al. (2003)’s model. Its several assumptions and simplifications make it inaccurate for light colored hair (d’Eon et al. 2011) as well as for most types of fur (Yan et al. 2015). Furthermore, d’Eon et al. (2011) and Khungurn and Marschner (2017) demonstrated it to not be energy conserving.

This project intends to upgrade Cycles’ hair shader to the aforementioned *Zootopia* shader by Chiang et al. (2016), by porting Pharr (2017)’s implementation. Lukas Stockner has made available a WIP patch, which may also serve as a basis for this work.


By having this functionality, the Blender community will be able to render physically accurate, production-level quality hair without resorting to proprietary engines such as RenderMan.


The delivered shader implementation should be expected to include:

  • the node itself (in SVM as well as OSL)
  • node-UI bindings
  • energy conservation tests i.e. white furnace test
  • formal verification tests i.e. correctness of the mathematical primitives
  • Blender-Wiki documentation
  • developer documentation

Project Details

Shader Implementation

Cycles shader nodes are implemented using one of the following choices:

  • simply using a custom Open Shading Language node;
    • these are only usable with CPU renders
  • direct C++ implementation via SVM and OSL (in the sections below).
    • these are available for both CPU and GPU

Anatomy of a Shader

The layout of a Cycles node is as follows (guidance taken from here:

General primitives

Cycles’ mathematical primitives are contained in intern/cycles/util.

Shader closure

Cycles’ BSDF closures are defined in intern/cycles/kernel/closure/. These define the primitives that will be used later by the chosen shader backend.

Shader implementation

Cycles has two backends available for direct shader implementation.

The first is the *Open Shading Language* (OSL, intern/cycles/kernel/osl). These kind of shaders are only usable in the CPU. To implement them, the shader’s closure must be registered first in intern/cycles/kernel/osl/osl_closures.cpp, which makes the necessary functions available for use by the shader itself (intern/cycles/kernel/shaders/).

A similar workflow is followed by the *Shader Virtual Machine* (SVM, intern/cycles/kernel/osl/). Shaders implemented using the SVM can be used in both CPU and GPU renders. In this case, the shader’s BSDF components must be registered in intern/cycles/kernel/closure/bsdf.h, and then the closure is evaluated in the interpreter loop at intern/cycles/kernel/closure/svm_closure.h.

Blender UI registration

New Cycles shader nodes need to be made available to Blender’s UI. This is implemented in the files at source/blender/nodes/shader/nodes, while the general registration calls are available at source/blender/blenkernel/.

The registration logic includes:

  • implementing node sockets i.e. input and output parameters;
  • registering the shader itself with the GPU kernel.

After implementing the shader, the workflow would be as follows:

  • create and implement the registration logic in source/blender/nodes/shader/nodes;
  • reserve a new shader ID at source/blender/blenkernel/BKE_node.h and register it at source/blender/nodes/NOD_static_types.h.
  • declare the new registration function in blender/blenkernel/intern/NOD_shader.h and call it from registerShaderNodes() in node.c.


Blender employs two types of testing:

  • unit tests, in src/test/render_graph_finalize_test.cpp
  • regression tests, implemented as reproducible scenes (lib/tests/cycles/ctests/shader/hair_*.blend)

From a technical point of view, Pharr’s implementation already includes:

  • a white furnace test to ensure energy conservation
  • a statistical test to verify correctness of the custom primitives.

These should be easily ported to Cycles’ unit test framework. As an addition, I can also repurpose the existing hair tests to suit the new shader.


Pharr’s implementation comes out-of-the-box with several customized, high performance primitives e.g. SafeASin and SafePow. They are all defined in terms of C++ standard functions, so there should be no need to change them.

Further optimization could be done with flame graphs and Perfview in Windows (the platform I’m most experienced with). For the GPU version, I could profile it with Nvidia Nsight Visual Studio Edition’s Heads-Up Display.

In addition to the above, I should also test the shader’s:

  • compatibility with different types of lights (point, area, etc.)
  • compatibility with importance sampling mechanisms
  • sampling noise results.

I expect to have testing builds available, if possible via Blender’s experimental-buildbot to receive and act on early feedback.


We divide the shader documentation in two:

  • *developer documentation*: I expect the implementation to be self-documented simultaneously with the coding. There is also very little documentation on Blender’s node architecture as well; I can produce blog posts providing further insight on this.
  • *Blender-Wiki documentation*: apart from the obvious adjustments to the wiki page, I suggest to make the shader’s theoretical background more explicit. A link to the paper, as well as a bit of theoretical background (for those more technically inclined) would suffice.

Project Schedule

Weeks are measured from Mon-Sun to align with GSoC’s Coding Period start date.

Apr 23 – May 13Get acquainted with Blender’s code layout and standards, especially how Cycles nodes are implemented and the available mathematical facilities. Ensure Blender compiles successfully on all work devices.
1May 14 – May 20Review of Pharr’s code. Implement a dummy Cycles node. Verify exposure of shader’s parameters and test setters/getters.
2May 21 – May 27Port Pharr’s shader primitives and statistical tests. Verify they work as expected.
3May 28 – Jun 3Port Pharr’s shading function.
4Jun 4 – Jun 10Test shader functionality. If working, release test build.
5Jun 11 – Jun 17Evaluate received feedback. Start bug fixes.
6Jun 18 – Jun 24Port Pharr’s furnace test. Verify it works as expected.
7Jun 25 – Jul 1Testing and bug fixes.
Jul 2*Uni’s winter break starts here!*
8Jul 2 – Jul 8Repurpose existing regression tests and obtain reference renders.
9Jul 9 – Jul 15General testing and bug fixes.
10Jul 16 – Jul 22User documentation revision.
11Jul 23 – Jul 29Developer documentation revision.
12Jul 30 – Aug 5Reserved week (just in case anything happens)
Aug 6*Finish line!* 👍

These are my university’s holiday dates as well (link in Spanish).

May 1Workers’ Day
2May 25Anniversary of the May Revolution
5Jun 17Anniversary of the death of Martín Miguel de Güemes
6Jun 20Flag’s Day
9Jul 9Independence Day

School conflicts

I have the following *fixed* commitments during the GSoC coding period. The timetable is given in GMT-3:

  • French classes
    • Tue & Thu 1800-2000
  • Postgraduate course “Digital Image Processing”
    • Thu 1230-1400
    • Fri 0800-1000

Any new commitments will be reported and coordinated with my assigned mentor as soon as possible.


The following references include a DOI for your viewing pleasure.

Chiang, Matt Jen-Yuan, Benedikt Bitterli, Chuck Tappan, and Brent Burley. 2016. “A Practical and Controllable Hair and Fur Model for Production Path Tracing.” *Computer Graphics Forum* 35 (2):275–83.

d’Eon, Eugene, Guillaume Francois, Martin Hill, Joe Letteri, and Jean-Marie Aubry. 2011. “An Energy-Conserving Hair Reflectance Model.” *Computer Graphics Forum* 30 (4):1181–7.

Iben, Hayley, Mark Meyer, Lena Petrovic, Olivier Soares, John Anderson, and Andrew Witkin. 2013. “Artistic Simulation of Curly Hair.” In *Proceedings of the 12th Acm Siggraph/Eurographics Symposium on Computer Animation*, 63–71. SCA ’13. New York, NY, USA: ACM.

Khungurn, Pramook, and Steve Marschner. 2017. “Azimuthal Scattering from Elliptical Hair Fibers.” *ACM Trans. Graph.* 36 (2). New York, NY, USA: ACM:13:1–13:23.

Marschner, Stephen R., Henrik Wann Jensen, Mike Cammarano, Steve Worley, and Pat Hanrahan. 2003. “Light Scattering from Human Hair Fibers.” In *ACM Siggraph 2003 Papers*, 780–91. SIGGRAPH ’03. New York, NY, USA: ACM.

Pharr, Matt. 2017. “The Implementation of a Hair Scattering Model.” In *Physically Based Rendering: From Theory to Implementation*, 3rd ed. Boston, MA, USA: Morgan Kaufmann.

Sadeghi, Iman, Heather Pritchett, Henrik Wann Jensen, and Rasmus Tamstorf. 2010. “An Artist Friendly Hair Shading System.” In *ACM Siggraph 2010 Papers*, 56:1–56:10. SIGGRAPH ’10. New York, NY, USA: ACM.

Selzer, Matías Nicolás, Elisabet Arriata, Leonardo Segovia, Nicolás Fernando Gazcón, and Martín Leonardo Larrea. 2017. “Modelos de interacción y aplicaciones en realidad virtual mediante dispositivos móviles.” In *XIX Workshop de Investigadores en Ciencias de la Computación (WICC 2017, ITBA, Buenos Aires)*. Buenos Aires, Argentina.

Ward, Kelly, Maryann Simmons, Andy Milne, Hidetaka Yosumi, and Xinmin Zhao. 2010. “Simulating Rapunzel’s Hair in Disney’s Tangled.” In *ACM Siggraph 2010 Talks*, 22:1–22:1. SIGGRAPH ’10. New York, NY, USA: ACM.

Yan, Ling-Qi, Chi-Wei Tseng, Henrik Wann Jensen, and Ravi Ramamoorthi. 2015. “Physically-Accurate Fur Reflectance: Modeling, Measurement and Rendering.” *ACM Trans. Graph.* 34 (6). New York, NY, USA: ACM:185:1–185:13.

L. E. Segovia (amyspark) triaged this task as Normal priority.
L. E. Segovia (amyspark) created this object with edit policy "Cycles (Project)".

Hey @L. E. Segovia (amyspark), and welcome!
Please rename your task to some more specific name, we have more than one GSoC project this year again. ;)

L. E. Segovia (amyspark) renamed this task from GSoC 2018 project: to GSoC 2018 project: Implementing a Hair Shader for Cycles.Wed, Apr 25, 2:05 PM

@Bastien Montagne (mont29) /facepalm :)

I've edited the task name. Thanks for the heads up!

I don't have much to add to this really.

Some of work planned for at the end like "Repurpose existing regression tests and obtain reference renders." doesn't need a week. But it's also not really possible to do detailed plans that far ahead, maybe there will be more bugs to fix, or maybe some extra features can be added to the shader, so it doesn't really matter.