Output result of individual passes in Cycles standalone

Hi everyone,

I would like to modify the source code of standalone Cycles to output a final image that contains the result of a specific pass e.g. depth, normal, etc.

I started exploring the Cycles source code to understand how to do this and would really appreciate some guidance.

My current progress:

  • The final --output image is written in the Session destructor [1]. I’m assuming the Device contains all the necessary information and the DisplayBuffer only converts it to the desired output format [2]. Maybe the Device also contains the output of different passes and there’s a way to read it?
  • Available passes are defined in kernel_types.h [3]
  • The Film class [4] seems to contain information about which passes will be used, storing the data in an array of passes [5].
  • The only place I found where passes are being added is in the BufferParams [6] constructor. Passes are also configured in the Blender section of the code base but I assume everything there is directly related to Blender integration and not used by Cycles standalone.
  • scene.cpp [7] seems to define the main pipeline
  • The output shouldn’t be gamma corrected – maybe setting display_buffer_linear [8] to true is enough? What about tonemap [9]?

NOTE: I tried adding direct source code links but wasn’t allowed because I’m a new user.

Links:

[1] https://developer.blender.org/diffusion/C/browse/master/src/render/session.cpp;fb39e26c242e4584117aa7584a2d0fbd5cf5ad57$113
[2] https://developer.blender.org/diffusion/C/browse/master/src/render/buffers.cpp;b352637d179acd4e0d525a201ec1975092527926$463
[3] https://developer.blender.org/diffusion/C/browse/master/src/kernel/kernel_types.h;b352637d179acd4e0d525a201ec1975092527926$402
[4] https://developer.blender.org/diffusion/C/browse/master/src/render/film.cpp;b352637d179acd4e0d525a201ec1975092527926$317
[5] https://developer.blender.org/diffusion/C/browse/master/src/render/film.h;b352637d179acd4e0d525a201ec1975092527926$59
[6] https://developer.blender.org/diffusion/C/browse/master/src/render/buffers.cpp;b352637d179acd4e0d525a201ec1975092527926$47
[7] https://developer.blender.org/diffusion/C/browse/master/src/render/scene.cpp;b352637d179acd4e0d525a201ec1975092527926$263
[8] https://developer.blender.org/diffusion/C/browse/master/src/render/session.h;b352637d179acd4e0d525a201ec1975092527926$94
[9] https://developer.blender.org/diffusion/C/browse/master/src/render/session.cpp;b352637d179acd4e0d525a201ec1975092527926$110

Cycles standalone is still pretty much a test application, but improvements to make it more useful would be appreciated. I think you found the most important code. There’s a few steps to this:

Add support for specifying which passes should be rendered in the XML file. Probably with a syntax like this:

<film>
    <pass type="combined" />
    <pass type="normal" />
</film>

Ideally this would be done with the generic node system, turning Pass into a node, similar to what I suggested for Alembic objects here: https://developer.blender.org/D3089#73247

The image output code should be improved, and indeed skip the display transform when writing data passes. Use RenderBuffers::get_pass_rect to get the float data. It could automatically detect if a display transform should be used or not depending if we’re writing to e.g. a PNG or linear EXR, or if we’re writing a color pass or data pass.

We could support writing passes to a multilayer EXR file or to individual files. I think just the former could be fine. If you need more then a filepath could be added to the <pass> tag, but if a single EXR file can be used that simplifies the pipeline.

Did you manage to get this working?

I’m trying to get a buffer with the depth and normals of the rendered image, and what I’ve achieved so far was to add a pass to the scene:

::Pass::add(PassType::PASS_COMBINED, _scene->passes, "Result");
::Pass::add(PassType::PASS_NORMAL, _scene->passes, "Normal");
::Pass::add(PassType::PASS_DIFFUSE_COLOR, _scene->passes, "Albedo");

_scene->film->set_display_pass(PassType::PASS_COMBINED);

I also had to setup the buffer params structure:

BufferParams   session_buffer_params;
session_buffer_params.width = _width;
session_buffer_params.height = _height;
session_buffer_params.full_width = _width;
session_buffer_params.full_height = _height;
session_buffer_params.passes = _scene->passes;

to have storage for the additional passes.

But now, when I render the image, I get some sort of combined image that seems to add all the passes together and I can’t figure out how to extract just what I want. RenderBuffers::get_pass_rect seems to return the same buffer, regardless of the pass name.

Best regards,
Diogo