Listing the "Blender Foundation" as copyright holder implied the Blender Foundation holds copyright to files which may include work from many developers. While keeping copyright on headers makes sense for isolated libraries, Blender's own code may be refactored or moved between files in a way that makes the per file copyright holders less meaningful. Copyright references to the "Blender Foundation" have been replaced with "Blender Authors", with the exception of `./extern/` since these this contains libraries which are more isolated, any changed to license headers there can be handled on a case-by-case basis. Some directories in `./intern/` have also been excluded: - `./intern/cycles/` it's own `AUTHORS` file is planned. - `./intern/opensubdiv/`. An "AUTHORS" file has been added, using the chromium projects authors file as a template. Design task: #110784 Ref !110783.
148 lines
4.6 KiB
C++
148 lines
4.6 KiB
C++
/* SPDX-FileCopyrightText: 2020 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \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 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 {
|
|
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 propvalue_maxncpy);
|
|
/* C type callback function (StampCallback). */
|
|
static void extract_layer_manifest(void *_data,
|
|
const char *propname,
|
|
char *propvalue,
|
|
int propvalue_maxncpy);
|
|
};
|
|
|
|
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
|