Cycles: Write Cryptomatte metadata according to the specification
authorLukas Stockner <lukas.stockner@freenet.de>
Wed, 7 Nov 2018 03:05:47 +0000 (04:05 +0100)
committerLukas Stockner <lukas.stockner@freenet.de>
Thu, 8 Nov 2018 00:07:54 +0000 (01:07 +0100)
Reviewers: brecht, sergey, swerner

Subscribers: creamsurfer, Tanguy, Noss, SteffenD

Differential Revision: https://developer.blender.org/D3862

intern/cycles/blender/blender_session.cpp
intern/cycles/blender/blender_session.h
intern/cycles/blender/blender_util.h
intern/cycles/render/object.cpp
intern/cycles/render/object.h
intern/cycles/render/shader.cpp
intern/cycles/render/shader.h

index e05351eea40e82eb3d642ac0512d05cb87e34547..75c7dcee05e9a023b9886e45a69045b70713912d 100644 (file)
@@ -35,6 +35,7 @@
 #include "util/util_function.h"
 #include "util/util_hash.h"
 #include "util/util_logging.h"
+#include "util/util_murmurhash.h"
 #include "util/util_progress.h"
 #include "util/util_time.h"
 
@@ -370,6 +371,17 @@ void BlenderSession::update_render_tile(RenderTile& rtile, bool highlight)
                do_write_update_render_tile(rtile, false, false);
 }
 
+static void add_cryptomatte_layer(BL::RenderResult& b_rr, string name, string manifest)
+{
+       string identifier = string_printf("%08x", util_murmur_hash3(name.c_str(), name.length(), 0));
+       string prefix = "cryptomatte/" + identifier.substr(0, 7) + "/";
+
+       render_add_metadata(b_rr, prefix+"name", name);
+       render_add_metadata(b_rr, prefix+"hash", "MurmurHash3_32");
+       render_add_metadata(b_rr, prefix+"conversion", "uint32_to_float32");
+       render_add_metadata(b_rr, prefix+"manifest", manifest);
+}
+
 void BlenderSession::render()
 {
        /* set callback to write out render results */
@@ -477,15 +489,28 @@ void BlenderSession::render()
                                break;
                }
 
+               BL::RenderResult b_full_rr = b_engine.get_result();
                if(is_single_layer) {
-                       BL::RenderResult b_rr = b_engine.get_result();
                        string num_aa_samples = string_printf("%d", session->params.samples);
-                       b_rr.stamp_data_add_field("Cycles Samples", num_aa_samples.c_str());
+                       render_add_metadata(b_full_rr, "Cycles Samples", num_aa_samples);
                        /* TODO(sergey): Report whether we're doing resumable render
                         * and also start/end sample if so.
                         */
                }
 
+               if(scene->film->cryptomatte_passes & CRYPT_OBJECT) {
+                       add_cryptomatte_layer(b_full_rr, b_rlay_name+".CryptoObject",
+                                             scene->object_manager->get_cryptomatte_objects(scene));
+               }
+               if(scene->film->cryptomatte_passes & CRYPT_MATERIAL) {
+                       add_cryptomatte_layer(b_full_rr, b_rlay_name+".CryptoMaterial",
+                                             scene->shader_manager->get_cryptomatte_materials(scene));
+               }
+               if(scene->film->cryptomatte_passes & CRYPT_ASSET) {
+                       add_cryptomatte_layer(b_full_rr, b_rlay_name+".CryptoAsset",
+                                             scene->object_manager->get_cryptomatte_assets(scene));
+               }
+
                /* free result without merging */
                end_render_result(b_engine, b_rr, true, true, false);
 
index 08f5c873bef5274852bd6b012b71a30c6980be2a..540fa6a8a845586d74bbb387c4bf47f59ecad6bc 100644 (file)
@@ -169,6 +169,9 @@ protected:
 
        /* Update tile manager to reflect resumable render settings. */
        void update_resumable_tile_manager(int num_samples);
+
+       /* Add metadata for cryptomatte layers to the render result. */
+       void add_cryptomatte_metadata(string layer_prefix);
 };
 
 CCL_NAMESPACE_END
index 7e61888348b88638d24cfb417d85992e6cfc7966..09ae9bea313d5c127c4f4ea73c4a33b10212a4fc 100644 (file)
@@ -243,6 +243,12 @@ static inline float *image_get_float_pixels_for_frame(BL::Image& image,
        return BKE_image_get_float_pixels_for_frame(image.ptr.data, frame);
 }
 
+static inline void render_add_metadata(BL::RenderResult& b_rr, string name, string value)
+{
+       b_rr.stamp_data_add_field(name.c_str(), value.c_str());
+}
+
+
 /* Utilities */
 
 static inline Transform get_transform(const BL::Array<float, 16>& array)
index a56a8a6ec58e8a85691dd5837c068114cf922380..dc7a1043208f3d41cad95859cd67d1cc21a5b7d7 100644 (file)
@@ -27,6 +27,7 @@
 #include "util/util_logging.h"
 #include "util/util_map.h"
 #include "util/util_progress.h"
+#include "util/util_set.h"
 #include "util/util_vector.h"
 #include "util/util_murmurhash.h"
 
@@ -844,4 +845,37 @@ void ObjectManager::tag_update(Scene *scene)
        scene->light_manager->need_update = true;
 }
 
+string ObjectManager::get_cryptomatte_objects(Scene *scene)
+{
+       string manifest = "{";
+
+       unordered_set<ustring, ustringHash> objects;
+       foreach(Object *object, scene->objects) {
+               if(objects.count(object->name)) {
+                       continue;
+               }
+               objects.insert(object->name);
+               uint32_t hash_name = util_murmur_hash3(object->name.c_str(), object->name.length(), 0);
+               manifest += string_printf("\"%s\":\"%08x\",", object->name.c_str(), hash_name);
+       }
+       manifest[manifest.size()-1] = '}';
+       return manifest;
+}
+
+string ObjectManager::get_cryptomatte_assets(Scene *scene)
+{
+       string manifest = "{";
+       unordered_set<ustring, ustringHash> assets;
+       foreach(Object *ob, scene->objects) {
+               if(assets.count(ob->asset_name)) {
+                       continue;
+               }
+               assets.insert(ob->asset_name);
+               uint32_t hash_asset = util_murmur_hash3(ob->asset_name.c_str(), ob->asset_name.length(), 0);
+               manifest += string_printf("\"%s\":\"%08x\",", ob->asset_name.c_str(), hash_asset);
+       }
+       manifest[manifest.size()-1] = '}';
+       return manifest;
+}
+
 CCL_NAMESPACE_END
index bd44b35aba312600dcb1af1d0dc8c7593b070cd8..288c3f5457af29a6a01ecd2e1fb792156b761400 100644 (file)
@@ -116,6 +116,9 @@ public:
 
        void apply_static_transforms(DeviceScene *dscene, Scene *scene, Progress& progress);
 
+       string get_cryptomatte_objects(Scene *scene);
+       string get_cryptomatte_assets(Scene *scene);
+
 protected:
        void device_update_object_transform(UpdateObjectTransformState *state,
                                            Object *ob,
index 8d0cec7b14e83c2d20f184ec7239bb0cd5850fd4..a827f611583db5a59f3f98044f21421e4ae513e7 100644 (file)
@@ -699,4 +699,20 @@ float ShaderManager::linear_rgb_to_gray(float3 c)
        return dot(c, rgb_to_y);
 }
 
+string ShaderManager::get_cryptomatte_materials(Scene *scene)
+{
+       string manifest = "{";
+       unordered_set<ustring, ustringHash> materials;
+       foreach(Shader *shader, scene->shaders) {
+               if(materials.count(shader->name)) {
+                       continue;
+               }
+               materials.insert(shader->name);
+               uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0);
+               manifest += string_printf("\"%s\":\"%08x\",", shader->name.c_str(), cryptomatte_id);
+       }
+       manifest[manifest.size()-1] = '}';
+       return manifest;
+}
+
 CCL_NAMESPACE_END
index 58314a1e31017b9718461a297a1fe95fc6d9d570..8073138404853c736892fde2f999dd7fe1c17e0a 100644 (file)
@@ -197,6 +197,8 @@ public:
 
        float linear_rgb_to_gray(float3 c);
 
+       string get_cryptomatte_materials(Scene *scene);
+
 protected:
        ShaderManager();