Welcome to mirror list, hosted at ThFree Co, Russian Federation.

BKE_cryptomatte.hh « blenkernel « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: dd08f7b5c4f87e019b9822e754c938be9e464bb2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/* SPDX-License-Identifier: GPL-2.0-or-later
 * Copyright 2020 Blender Foundation. All rights reserved. */

/** \file
 * \ingroup bke
 */

#pragma once

#include <optional>
#include <string>

#include "BKE_cryptomatte.h"

#include "BLI_hash_mm3.h"
#include "BLI_map.hh"
#include "BLI_string_ref.hh"

#include "BKE_cryptomatte.h"

struct ID;

namespace blender::bke::cryptomatte {

/**
 * Format to a cryptomatte meta data key.
 *
 * Cryptomatte stores meta data. The keys are formatted containing a hash that
 * is generated from its layer name.
 *
 * The output of this function is:
 * 'cryptomatte/{hash of layer_name}/{key_name}'.
 */
std::string BKE_cryptomatte_meta_data_key(const StringRef layer_name,
                                          const StringRefNull key_name);

/**
 * Extract the cryptomatte layer name from the given `render_pass_name`.
 *
 * Cryptomatte passes are formatted with a trailing number for storing multiple samples that belong
 * to the same cryptomatte layer. This function would remove the trailing numbers to determine the
 * cryptomatte layer name.
 *
 * # Example
 *
 * A render_pass_name could be 'View Layer.CryptoMaterial02'. The cryptomatte layer would be 'View
 * Layer.CryptoMaterial'.
 *
 * \note The return type is a sub-string of `render_pass_name` and therefore cannot outlive the
 * `render_pass_name` internal data.
 */
StringRef BKE_cryptomatte_extract_layer_name(const StringRef render_pass_name);

struct CryptomatteHash {
  uint32_t hash;

  CryptomatteHash(uint32_t hash);
  CryptomatteHash(const char *name, int name_len)
  {
    hash = BLI_hash_mm3((const unsigned char *)name, name_len, 0);
  }

  static CryptomatteHash from_hex_encoded(blender::StringRef hex_encoded);
  std::string hex_encoded() const;

  /**
   * Convert a cryptomatte hash to a float.
   *
   * Cryptomatte hashes are stored in float textures and images. The conversion is taken from the
   * cryptomatte specification. See Floating point conversion section in
   * https://github.com/Psyop/Cryptomatte/blob/master/specification/cryptomatte_specification.pdf.
   *
   * The conversion uses as many 32 bit floating point values as possible to minimize hash
   * collisions. Unfortunately not all 32 bits can be used as NaN and Inf can be problematic.
   *
   * Note that this conversion assumes to be running on a L-endian system.
   */
  float float_encoded() const
  {
    uint32_t mantissa = hash & ((1 << 23) - 1);
    uint32_t exponent = (hash >> 23) & ((1 << 8) - 1);
    exponent = MAX2(exponent, (uint32_t)1);
    exponent = MIN2(exponent, (uint32_t)254);
    exponent = exponent << 23;
    uint32_t sign = (hash >> 31);
    sign = sign << 31;
    uint32_t float_bits = sign | exponent | mantissa;
    float f;
    memcpy(&f, &float_bits, sizeof(uint32_t));
    return f;
  }
};

struct CryptomatteLayer {
  blender::Map<std::string, CryptomatteHash> hashes;

#ifdef WITH_CXX_GUARDEDALLOC
  MEM_CXX_CLASS_ALLOC_FUNCS("cryptomatte:CryptomatteLayer")
#endif

  static std::unique_ptr<CryptomatteLayer> read_from_manifest(blender::StringRefNull manifest);
  uint32_t add_ID(const struct ID &id);
  void add_hash(blender::StringRef name, CryptomatteHash cryptomatte_hash);
  std::string manifest() const;

  std::optional<std::string> operator[](float encoded_hash) const;
};

struct CryptomatteStampDataCallbackData {
  struct CryptomatteSession *session;
  blender::Map<std::string, std::string> hash_to_layer_name;

  /**
   * Extract the hash from a stamp data key.
   *
   * Cryptomatte keys are formatted as "cryptomatte/{layer_hash}/{attribute}".
   */
  static blender::StringRef extract_layer_hash(blender::StringRefNull key);

  /* C type callback function (StampCallback). */
  static void extract_layer_names(void *_data, const char *propname, char *propvalue, int len);
  /* C type callback function (StampCallback). */
  static void extract_layer_manifest(void *_data, const char *propname, char *propvalue, int len);
};

const blender::Vector<std::string> &BKE_cryptomatte_layer_names_get(
    const CryptomatteSession &session);
CryptomatteLayer *BKE_cryptomatte_layer_get(CryptomatteSession &session,
                                            const StringRef layer_name);

struct CryptomatteSessionDeleter {
  void operator()(CryptomatteSession *session)
  {
    BKE_cryptomatte_free(session);
  }
};

using CryptomatteSessionPtr = std::unique_ptr<CryptomatteSession, CryptomatteSessionDeleter>;

}  // namespace blender::bke::cryptomatte