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:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user