Fix #129435: Bad Cryptomatte output in camera view

The Cryptomatte node produces a bad output when the viewport is in
camera view. That's because compositing is limited to the camera region
in that case, but the node assumes the full viewport size. To fix this,
only consider the compositing region instead of the full viewport.
This commit is contained in:
Omar Emara
2024-10-28 14:14:49 +03:00
parent d6d612dc46
commit f0125f26fd
4 changed files with 32 additions and 3 deletions

View File

@@ -17,7 +17,7 @@
void main()
{
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
vec4 layer = texture_load(layer_tx, texel);
vec4 layer = texture_load(layer_tx, texel + lower_bound);
/* Each Cryptomatte layer stores two ranks. */
vec2 first_rank = layer.xy;

View File

@@ -30,7 +30,7 @@ void main()
/* Each layer stores two ranks, each rank contains a pair, the identifier and the coverage of
* the entity identified by the identifier. */
vec2 first_rank = texture_load(first_layer_tx, texel).xy;
vec2 first_rank = texture_load(first_layer_tx, texel + lower_bound).xy;
float id_of_first_rank = first_rank.x;
/* There is no logic to this, we just compute arbitrary compressed versions of the identifier in

View File

@@ -6,6 +6,7 @@
GPU_SHADER_CREATE_INFO(compositor_cryptomatte_pick)
.local_group_size(16, 16)
.push_constant(Type::IVEC2, "lower_bound")
.sampler(0, ImageType::FLOAT_2D, "first_layer_tx")
.image(0, GPU_RGBA32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
.compute_source("compositor_cryptomatte_pick.glsl")
@@ -13,6 +14,7 @@ GPU_SHADER_CREATE_INFO(compositor_cryptomatte_pick)
GPU_SHADER_CREATE_INFO(compositor_cryptomatte_matte)
.local_group_size(16, 16)
.push_constant(Type::IVEC2, "lower_bound")
.push_constant(Type::INT, "identifiers_count")
.push_constant(Type::FLOAT, "identifiers", 32)
.sampler(0, ImageType::FLOAT_2D, "layer_tx")

View File

@@ -238,6 +238,13 @@ class BaseCryptoMatteOperation : public NodeOperation {
/* Should returns all the Cryptomatte layers in order. */
virtual Vector<GPUTexture *> get_layers() = 0;
/* If only a subset area of the Cryptomatte layers is to be considered, this method should return
* the lower bound of that area. The upper bound will be derived from the operation domain. */
virtual int2 get_layers_lower_bound()
{
return int2(0);
}
void execute() override
{
Vector<GPUTexture *> layers = get_layers();
@@ -297,6 +304,9 @@ class BaseCryptoMatteOperation : public NodeOperation {
GPUShader *shader = context().get_shader("compositor_cryptomatte_pick", ResultPrecision::Full);
GPU_shader_bind(shader);
const int2 lower_bound = this->get_layers_lower_bound();
GPU_shader_uniform_2iv(shader, "lower_bound", lower_bound);
GPUTexture *first_layer = layers[0];
const int input_unit = GPU_shader_get_sampler_binding(shader, "first_layer_tx");
GPU_texture_bind(first_layer, input_unit);
@@ -341,6 +351,8 @@ class BaseCryptoMatteOperation : public NodeOperation {
GPUShader *shader = context().get_shader("compositor_cryptomatte_matte");
GPU_shader_bind(shader);
const int2 lower_bound = this->get_layers_lower_bound();
GPU_shader_uniform_2iv(shader, "lower_bound", lower_bound);
GPU_shader_uniform_1i(shader, "identifiers_count", identifiers.size());
GPU_shader_uniform_1f_array(shader, "identifiers", identifiers.size(), identifiers.data());
@@ -654,13 +666,28 @@ class CryptoMatteOperation : public BaseCryptoMatteOperation {
return std::string(type_name);
}
int2 get_layers_lower_bound() override
{
switch (get_source()) {
case CMP_NODE_CRYPTOMATTE_SOURCE_RENDER: {
const rcti compositing_region = this->context().get_compositing_region();
return int2(compositing_region.xmin, compositing_region.ymin);
}
case CMP_NODE_CRYPTOMATTE_SOURCE_IMAGE:
return int2(0);
}
BLI_assert_unreachable();
return int2(0);
}
/* The domain should be centered with the same size as the source. In case of invalid source,
* fallback to the domain inferred from the input. */
Domain compute_domain() override
{
switch (get_source()) {
case CMP_NODE_CRYPTOMATTE_SOURCE_RENDER:
return Domain(context().get_render_size());
return Domain(context().get_compositing_region_size());
case CMP_NODE_CRYPTOMATTE_SOURCE_IMAGE:
return compute_image_domain();
}