From d6fa68eb587507625fb0cb6a1fbfbd9a2c97f4af Mon Sep 17 00:00:00 2001 From: Omar Emara Date: Fri, 21 Mar 2025 12:03:09 +0100 Subject: [PATCH] Compositor: Add boolean socket support This patch adds support for boolean sockets in the compositor. This involves adding a new Bool ResultType and handling it in relevant code. For shader operations, booleans are passes as floats since GPUMaterial does not yet support boolean types. Pull Request: https://projects.blender.org/blender/blender/pulls/136296 --- source/blender/compositor/COM_result.hh | 4 +- .../compositor/intern/conversion_operation.cc | 2 +- .../intern/input_single_value_operation.cc | 5 + .../multi_function_procedure_operation.cc | 5 + .../intern/realize_on_domain_operation.cc | 2 + source/blender/compositor/intern/result.cc | 27 +++++ .../compositor/intern/shader_operation.cc | 40 +++++-- source/blender/compositor/intern/utilities.cc | 2 + .../shaders/infos/compositor_convert_info.hh | 103 ++++++++++++++++++ .../gpu_shader_compositor_store_output.glsl | 7 ++ ...gpu_shader_compositor_type_conversion.glsl | 74 +++++++++++++ .../nodes/composite/node_composite_tree.cc | 2 +- .../nodes/node_composite_file_output.cc | 8 ++ .../composite/nodes/node_composite_image.cc | 1 + tests/python/bl_node_group_interface.py | 2 +- 15 files changed, 273 insertions(+), 11 deletions(-) diff --git a/source/blender/compositor/COM_result.hh b/source/blender/compositor/COM_result.hh index 2f172558afb..8c6a5829afd 100644 --- a/source/blender/compositor/COM_result.hh +++ b/source/blender/compositor/COM_result.hh @@ -41,6 +41,7 @@ enum class ResultType : uint8_t { Int, Int2, Color, + Bool, }; /* The precision of the data. CPU data is always stored using full precision at the moment. */ @@ -129,7 +130,7 @@ class Result { * which will be identical to that stored in the data_ member. The active variant member depends * on the type of the result. This member is uninitialized and should not be used if the result * is not a single value. */ - std::variant single_value_ = 0.0f; + std::variant single_value_ = 0.0f; /* The domain of the result. This only matters if the result was not a single value. See the * discussion in COM_domain.hh for more information. */ Domain domain_ = Domain::identity(); @@ -449,6 +450,7 @@ BLI_INLINE_METHOD int64_t Result::channels_count() const switch (type_) { case ResultType::Float: case ResultType::Int: + case ResultType::Bool: return 1; case ResultType::Float2: case ResultType::Int2: diff --git a/source/blender/compositor/intern/conversion_operation.cc b/source/blender/compositor/intern/conversion_operation.cc index 256dce2edb1..46939a8c863 100644 --- a/source/blender/compositor/intern/conversion_operation.cc +++ b/source/blender/compositor/intern/conversion_operation.cc @@ -53,7 +53,7 @@ void ConversionOperation::execute() GPU_shader_bind(shader); if (this->get_input().type() == ResultType::Color && - ELEM(this->get_result().type(), ResultType::Float, ResultType::Int)) + ELEM(this->get_result().type(), ResultType::Float, ResultType::Int, ResultType::Bool)) { float luminance_coefficients[3]; IMB_colormanagement_get_luminance_coefficients(luminance_coefficients); diff --git a/source/blender/compositor/intern/input_single_value_operation.cc b/source/blender/compositor/intern/input_single_value_operation.cc index 70ed9afbc39..54a8868d992 100644 --- a/source/blender/compositor/intern/input_single_value_operation.cc +++ b/source/blender/compositor/intern/input_single_value_operation.cc @@ -39,6 +39,11 @@ void InputSingleValueOperation::execute() result.set_single_value(value); break; } + case SOCK_BOOLEAN: { + const bool value = input_socket_->default_value_typed()->value; + result.set_single_value(value); + break; + } case SOCK_VECTOR: { const float3 value = input_socket_->default_value_typed()->value; result.set_single_value(value); diff --git a/source/blender/compositor/intern/multi_function_procedure_operation.cc b/source/blender/compositor/intern/multi_function_procedure_operation.cc index b7ac56a48a3..bddfe226593 100644 --- a/source/blender/compositor/intern/multi_function_procedure_operation.cc +++ b/source/blender/compositor/intern/multi_function_procedure_operation.cc @@ -219,6 +219,11 @@ mf::Variable *MultiFunctionProcedureOperation::get_constant_input_variable(DInpu constant_function = &procedure_.construct_function>(value); break; } + case SOCK_BOOLEAN: { + const bool value = input->default_value_typed()->value; + constant_function = &procedure_.construct_function>(value); + break; + } case SOCK_VECTOR: { const float3 value = float3(input->default_value_typed()->value); constant_function = &procedure_.construct_function>(value); diff --git a/source/blender/compositor/intern/realize_on_domain_operation.cc b/source/blender/compositor/intern/realize_on_domain_operation.cc index 8f5407c3759..08b859572a9 100644 --- a/source/blender/compositor/intern/realize_on_domain_operation.cc +++ b/source/blender/compositor/intern/realize_on_domain_operation.cc @@ -137,6 +137,7 @@ const char *RealizeOnDomainOperation::get_realization_shader_name() case ResultType::Int: case ResultType::Int2: case ResultType::Float2: + case ResultType::Bool: /* Realization does not support internal image types. */ break; } @@ -152,6 +153,7 @@ const char *RealizeOnDomainOperation::get_realization_shader_name() case ResultType::Int: case ResultType::Int2: case ResultType::Float2: + case ResultType::Bool: /* Realization does not support internal image types. */ break; } diff --git a/source/blender/compositor/intern/result.cc b/source/blender/compositor/intern/result.cc index 39ab4946d14..302f470f6ea 100644 --- a/source/blender/compositor/intern/result.cc +++ b/source/blender/compositor/intern/result.cc @@ -59,6 +59,9 @@ eGPUTextureFormat Result::gpu_texture_format(ResultType type, ResultPrecision pr return GPU_R16I; case ResultType::Int2: return GPU_RG16I; + case ResultType::Bool: + /* No bool texture formats, so we store in an 8-bit integer. Precision doesn't matter. */ + return GPU_R8I; } break; case ResultPrecision::Full: @@ -78,6 +81,9 @@ eGPUTextureFormat Result::gpu_texture_format(ResultType type, ResultPrecision pr return GPU_R32I; case ResultType::Int2: return GPU_RG32I; + case ResultType::Bool: + /* No bool texture formats, so we store in an 8-bit integer. Precision doesn't matter. */ + return GPU_R8I; } break; } @@ -100,6 +106,10 @@ eGPUTextureFormat Result::gpu_texture_format(eGPUTextureFormat format, ResultPre case GPU_RG16I: return format; + /* Used to store booleans where precision doesn't matter. */ + case GPU_R8I: + return format; + case GPU_R32F: return GPU_R16F; case GPU_RG32F: @@ -127,6 +137,10 @@ eGPUTextureFormat Result::gpu_texture_format(eGPUTextureFormat format, ResultPre case GPU_RG32I: return format; + /* Used to store booleans where precision doesn't matter. */ + case GPU_R8I: + return format; + case GPU_R16F: return GPU_R32F; case GPU_RG16F: @@ -166,6 +180,9 @@ ResultPrecision Result::precision(eGPUTextureFormat format) case GPU_R32I: case GPU_RG32I: return ResultPrecision::Full; + /* Used to store booleans where precision doesn't matter. */ + case GPU_R8I: + return ResultPrecision::Full; default: break; } @@ -195,6 +212,8 @@ ResultType Result::type(eGPUTextureFormat format) case GPU_RG16I: case GPU_RG32I: return ResultType::Int2; + case GPU_R8I: + return ResultType::Bool; default: break; } @@ -239,6 +258,8 @@ const CPPType &Result::cpp_type(const ResultType type) return CPPType::get(); case ResultType::Int2: return CPPType::get(); + case ResultType::Bool: + return CPPType::get(); } BLI_assert_unreachable(); @@ -262,6 +283,8 @@ const char *Result::type_name(const ResultType type) return "int2"; case ResultType::Int: return "int"; + case ResultType::Bool: + return "bool"; } BLI_assert_unreachable(); @@ -328,6 +351,9 @@ void Result::allocate_single_value() case ResultType::Int2: this->set_single_value(int2(0)); break; + case ResultType::Bool: + this->set_single_value(false); + break; } } @@ -648,6 +674,7 @@ void Result::update_single_value_data() } case ResultType::Int: case ResultType::Int2: + case ResultType::Bool: GPU_texture_update(this->gpu_texture(), GPU_DATA_INT, this->single_value().get()); break; } diff --git a/source/blender/compositor/intern/shader_operation.cc b/source/blender/compositor/intern/shader_operation.cc index c0c340d4048..08e4bc550bf 100644 --- a/source/blender/compositor/intern/shader_operation.cc +++ b/source/blender/compositor/intern/shader_operation.cc @@ -176,6 +176,12 @@ static void initialize_input_stack_value(const DInputSocket input, GPUNodeStack stack.vec[0] = int(value); break; } + case SOCK_BOOLEAN: { + /* GPUMaterial doesn't support bool, so it is stored as a float. */ + const bool value = input->default_value_typed()->value; + stack.vec[0] = float(value); + break; + } case SOCK_VECTOR: { const float3 value = float3(input->default_value_typed()->value); copy_v3_v3(stack.vec, value); @@ -200,6 +206,9 @@ static const char *get_set_function_name(const ResultType type) case ResultType::Int: /* GPUMaterial doesn't support int, so it is passed as a float. */ return "set_value"; + case ResultType::Bool: + /* GPUMaterial doesn't support bool, so it is passed as a float. */ + return "set_value"; case ResultType::Float3: return "set_rgb"; case ResultType::Color: @@ -345,6 +354,8 @@ static const char *get_store_function_name(ResultType type) return "node_compositor_store_output_float"; case ResultType::Int: return "node_compositor_store_output_int"; + case ResultType::Bool: + return "node_compositor_store_output_bool"; case ResultType::Float3: return "node_compositor_store_output_float3"; case ResultType::Color: @@ -443,6 +454,10 @@ static const char *glsl_store_expression_from_result_type(ResultType type) /* GPUMaterial doesn't support int, so it is passed as a float, and we need to convert it * back to int before writing it. */ return "ivec4(int(value))"; + case ResultType::Bool: + /* GPUMaterial doesn't support bool, so it is passed as a float and stored as an int, and we + * need to convert it back to bool and then to an int before writing it. */ + return "ivec4(bool(value))"; case ResultType::Float3: return "vec4(value, 0.0)"; case ResultType::Color: @@ -474,6 +489,7 @@ static ImageType gpu_image_type_from_result_type(const ResultType type) return ImageType::FLOAT_2D; case ResultType::Int: case ResultType::Int2: + case ResultType::Bool: return ImageType::INT_2D; } @@ -486,6 +502,8 @@ void ShaderOperation::generate_code_for_outputs(ShaderCreateInfo &shader_create_ const std::string store_float_function_header = "void store_float(const uint id, float value)"; /* GPUMaterial doesn't support int, so it is passed as a float. */ const std::string store_int_function_header = "void store_int(const uint id, float value)"; + /* GPUMaterial doesn't support bool, so it is passed as a float. */ + const std::string store_bool_function_header = "void store_bool(const uint id, float value)"; const std::string store_float3_function_header = "void store_float3(const uint id, vec3 value)"; const std::string store_color_function_header = "void store_color(const uint id, vec4 value)"; const std::string store_float4_function_header = "void store_float4(const uint id, vec4 value)"; @@ -500,6 +518,7 @@ void ShaderOperation::generate_code_for_outputs(ShaderCreateInfo &shader_create_ if (GPU_backend_get_type() != GPU_BACKEND_METAL) { shader_create_info.typedef_source_generated += store_float_function_header + ";\n"; shader_create_info.typedef_source_generated += store_int_function_header + ";\n"; + shader_create_info.typedef_source_generated += store_bool_function_header + ";\n"; shader_create_info.typedef_source_generated += store_float3_function_header + ";\n"; shader_create_info.typedef_source_generated += store_color_function_header + ";\n"; shader_create_info.typedef_source_generated += store_float4_function_header + ";\n"; @@ -512,6 +531,7 @@ void ShaderOperation::generate_code_for_outputs(ShaderCreateInfo &shader_create_ * the functions. */ std::stringstream store_float_function; std::stringstream store_int_function; + std::stringstream store_bool_function; std::stringstream store_float3_function; std::stringstream store_color_function; std::stringstream store_float4_function; @@ -520,6 +540,7 @@ void ShaderOperation::generate_code_for_outputs(ShaderCreateInfo &shader_create_ const std::string store_function_start = "\n{\n switch (id) {\n"; store_float_function << store_float_function_header << store_function_start; store_int_function << store_int_function_header << store_function_start; + store_bool_function << store_bool_function_header << store_function_start; store_float3_function << store_float3_function_header << store_function_start; store_color_function << store_color_function_header << store_function_start; store_float4_function << store_float4_function_header << store_function_start; @@ -555,6 +576,9 @@ void ShaderOperation::generate_code_for_outputs(ShaderCreateInfo &shader_create_ case ResultType::Int: store_int_function << case_code.str(); break; + case ResultType::Bool: + store_bool_function << case_code.str(); + break; case ResultType::Float3: store_float3_function << case_code.str(); break; @@ -577,19 +601,17 @@ void ShaderOperation::generate_code_for_outputs(ShaderCreateInfo &shader_create_ const std::string store_function_end = " }\n}\n\n"; store_float_function << store_function_end; store_int_function << store_function_end; + store_bool_function << store_function_end; store_float3_function << store_function_end; store_color_function << store_function_end; store_float4_function << store_function_end; store_float2_function << store_function_end; store_int2_function << store_function_end; - shader_create_info.compute_source_generated += store_float_function.str() + - store_int_function.str() + - store_float3_function.str() + - store_color_function.str() + - store_float4_function.str() + - store_float2_function.str() + - store_int2_function.str(); + shader_create_info.compute_source_generated += + store_float_function.str() + store_int_function.str() + store_bool_function.str() + + store_float3_function.str() + store_color_function.str() + store_float4_function.str() + + store_float2_function.str() + store_int2_function.str(); } static const char *glsl_type_from_result_type(ResultType type) @@ -600,6 +622,9 @@ static const char *glsl_type_from_result_type(ResultType type) case ResultType::Int: /* GPUMaterial doesn't support int, so it is passed as a float. */ return "float"; + case ResultType::Bool: + /* GPUMaterial doesn't support bool, so it is passed as a float. */ + return "float"; case ResultType::Float3: return "vec3"; case ResultType::Color: @@ -624,6 +649,7 @@ static const char *glsl_swizzle_from_result_type(ResultType type) switch (type) { case ResultType::Float: case ResultType::Int: + case ResultType::Bool: return "x"; case ResultType::Float3: return "xyz"; diff --git a/source/blender/compositor/intern/utilities.cc b/source/blender/compositor/intern/utilities.cc index 01110174fbc..0855e3d1e05 100644 --- a/source/blender/compositor/intern/utilities.cc +++ b/source/blender/compositor/intern/utilities.cc @@ -58,6 +58,8 @@ ResultType get_node_socket_result_type(const bNodeSocket *socket) return ResultType::Float; case SOCK_INT: return ResultType::Int; + case SOCK_BOOLEAN: + return ResultType::Bool; case SOCK_VECTOR: /* Vector sockets can also be ResultType::Float4 or ResultType::Float2, but the * developer is expected to define that manually since there is no way to distinguish them diff --git a/source/blender/compositor/shaders/infos/compositor_convert_info.hh b/source/blender/compositor/shaders/infos/compositor_convert_info.hh index a7326b47d75..9cedfe52de9 100644 --- a/source/blender/compositor/shaders/infos/compositor_convert_info.hh +++ b/source/blender/compositor/shaders/infos/compositor_convert_info.hh @@ -66,6 +66,13 @@ DEFINE_VALUE("CONVERT_EXPRESSION(value)", "vec4(float_to_float4(value.x))") DO_STATIC_COMPILATION() GPU_SHADER_CREATE_END() +GPU_SHADER_CREATE_INFO(compositor_convert_float_to_bool) +ADDITIONAL_INFO(compositor_convert_float_shared) +IMAGE(0, GPU_R8I, WRITE, INT_2D, output_img) +DEFINE_VALUE("CONVERT_EXPRESSION(value)", "ivec4(float_to_bool(value.x))") +DO_STATIC_COMPILATION() +GPU_SHADER_CREATE_END() + /* -------------------------------------------------------------------- * Int to other. */ @@ -112,6 +119,13 @@ DEFINE_VALUE("CONVERT_EXPRESSION(value)", "vec4(int_to_float4(value.x))") DO_STATIC_COMPILATION() GPU_SHADER_CREATE_END() +GPU_SHADER_CREATE_INFO(compositor_convert_int_to_bool) +ADDITIONAL_INFO(compositor_convert_int_shared) +IMAGE(0, GPU_R8I, WRITE, INT_2D, output_img) +DEFINE_VALUE("CONVERT_EXPRESSION(value)", "ivec4(int_to_bool(value.x))") +DO_STATIC_COMPILATION() +GPU_SHADER_CREATE_END() + /* -------------------------------------------------------------------- * Int2 to other. */ @@ -158,6 +172,13 @@ DEFINE_VALUE("CONVERT_EXPRESSION(value)", "vec4(int2_to_float4(value.xy))") DO_STATIC_COMPILATION() GPU_SHADER_CREATE_END() +GPU_SHADER_CREATE_INFO(compositor_convert_int2_to_bool) +ADDITIONAL_INFO(compositor_convert_int_shared) +IMAGE(0, GPU_R8I, WRITE, INT_2D, output_img) +DEFINE_VALUE("CONVERT_EXPRESSION(value)", "ivec4(int2_to_bool(value.xy))") +DO_STATIC_COMPILATION() +GPU_SHADER_CREATE_END() + /* -------------------------------------------------------------------- * Float2 to other. */ @@ -204,6 +225,13 @@ DEFINE_VALUE("CONVERT_EXPRESSION(value)", "vec4(float2_to_float4(value.xy))") DO_STATIC_COMPILATION() GPU_SHADER_CREATE_END() +GPU_SHADER_CREATE_INFO(compositor_convert_float2_to_bool) +ADDITIONAL_INFO(compositor_convert_float_shared) +IMAGE(0, GPU_R8I, WRITE, INT_2D, output_img) +DEFINE_VALUE("CONVERT_EXPRESSION(value)", "ivec4(float2_to_bool(value.xy))") +DO_STATIC_COMPILATION() +GPU_SHADER_CREATE_END() + /* -------------------------------------------------------------------- * Float3 to other. */ @@ -250,6 +278,13 @@ DEFINE_VALUE("CONVERT_EXPRESSION(value)", "vec4(float3_to_float4(value.xyz))") DO_STATIC_COMPILATION() GPU_SHADER_CREATE_END() +GPU_SHADER_CREATE_INFO(compositor_convert_float3_to_bool) +ADDITIONAL_INFO(compositor_convert_float_shared) +IMAGE(0, GPU_R8I, WRITE, INT_2D, output_img) +DEFINE_VALUE("CONVERT_EXPRESSION(value)", "ivec4(float3_to_bool(value.xyz))") +DO_STATIC_COMPILATION() +GPU_SHADER_CREATE_END() + /* -------------------------------------------------------------------- * Color to other. */ @@ -300,6 +335,14 @@ DEFINE_VALUE("CONVERT_EXPRESSION(value)", "vec4(color_to_float4(value))") DO_STATIC_COMPILATION() GPU_SHADER_CREATE_END() +GPU_SHADER_CREATE_INFO(compositor_convert_color_to_bool) +ADDITIONAL_INFO(compositor_convert_float_shared) +PUSH_CONSTANT(VEC3, luminance_coefficients_u) +IMAGE(0, GPU_R8I, WRITE, INT_2D, output_img) +DEFINE_VALUE("CONVERT_EXPRESSION(value)", "ivec4(color_to_bool(value, luminance_coefficients_u))") +DO_STATIC_COMPILATION() +GPU_SHADER_CREATE_END() + /* -------------------------------------------------------------------- * Float4 to other. */ @@ -346,6 +389,66 @@ DEFINE_VALUE("CONVERT_EXPRESSION(value)", "vec4(float4_to_color(value))") DO_STATIC_COMPILATION() GPU_SHADER_CREATE_END() +GPU_SHADER_CREATE_INFO(compositor_convert_float4_to_bool) +ADDITIONAL_INFO(compositor_convert_float_shared) +IMAGE(0, GPU_R8I, WRITE, INT_2D, output_img) +DEFINE_VALUE("CONVERT_EXPRESSION(value)", "ivec4(float4_to_bool(value))") +DO_STATIC_COMPILATION() +GPU_SHADER_CREATE_END() + +/* -------------------------------------------------------------------- + * Bool to other. + */ + +GPU_SHADER_CREATE_INFO(compositor_convert_bool_to_float) +ADDITIONAL_INFO(compositor_convert_int_shared) +IMAGE(0, GPU_R16F, WRITE, FLOAT_2D, output_img) +DEFINE_VALUE("CONVERT_EXPRESSION(value)", "vec4(bool_to_float(bool(value.x)), vec3(0.0))") +DO_STATIC_COMPILATION() +GPU_SHADER_CREATE_END() + +GPU_SHADER_CREATE_INFO(compositor_convert_bool_to_int) +ADDITIONAL_INFO(compositor_convert_int_shared) +IMAGE(0, GPU_R16I, WRITE, INT_2D, output_img) +DEFINE_VALUE("CONVERT_EXPRESSION(value)", "ivec4(bool_to_int(bool(value.x)), ivec3(0))") +DO_STATIC_COMPILATION() +GPU_SHADER_CREATE_END() + +GPU_SHADER_CREATE_INFO(compositor_convert_bool_to_int2) +ADDITIONAL_INFO(compositor_convert_int_shared) +IMAGE(0, GPU_RG16I, WRITE, INT_2D, output_img) +DEFINE_VALUE("CONVERT_EXPRESSION(value)", "ivec4(bool_to_int2(bool(value.x)), ivec2(0))") +DO_STATIC_COMPILATION() +GPU_SHADER_CREATE_END() + +GPU_SHADER_CREATE_INFO(compositor_convert_bool_to_float2) +ADDITIONAL_INFO(compositor_convert_int_shared) +IMAGE(0, GPU_RG16F, WRITE, FLOAT_2D, output_img) +DEFINE_VALUE("CONVERT_EXPRESSION(value)", "vec4(bool_to_float2(bool(value.x)), vec2(0.0))") +DO_STATIC_COMPILATION() +GPU_SHADER_CREATE_END() + +GPU_SHADER_CREATE_INFO(compositor_convert_bool_to_float3) +ADDITIONAL_INFO(compositor_convert_int_shared) +IMAGE(0, GPU_RGBA16F, WRITE, FLOAT_2D, output_img) +DEFINE_VALUE("CONVERT_EXPRESSION(value)", "vec4(bool_to_float3(bool(value.x)), 0.0)") +DO_STATIC_COMPILATION() +GPU_SHADER_CREATE_END() + +GPU_SHADER_CREATE_INFO(compositor_convert_bool_to_color) +ADDITIONAL_INFO(compositor_convert_int_shared) +IMAGE(0, GPU_RGBA16F, WRITE, FLOAT_2D, output_img) +DEFINE_VALUE("CONVERT_EXPRESSION(value)", "vec4(bool_to_color(bool(value.x)))") +DO_STATIC_COMPILATION() +GPU_SHADER_CREATE_END() + +GPU_SHADER_CREATE_INFO(compositor_convert_bool_to_float4) +ADDITIONAL_INFO(compositor_convert_int_shared) +IMAGE(0, GPU_RGBA16F, WRITE, FLOAT_2D, output_img) +DEFINE_VALUE("CONVERT_EXPRESSION(value)", "vec4(bool_to_float4(bool(value.x)))") +DO_STATIC_COMPILATION() +GPU_SHADER_CREATE_END() + /* -------------------------------------------------------------------- * Color to channel. */ diff --git a/source/blender/compositor/shaders/library/gpu_shader_compositor_store_output.glsl b/source/blender/compositor/shaders/library/gpu_shader_compositor_store_output.glsl index 783766c34ae..be64cfa32e0 100644 --- a/source/blender/compositor/shaders/library/gpu_shader_compositor_store_output.glsl +++ b/source/blender/compositor/shaders/library/gpu_shader_compositor_store_output.glsl @@ -55,3 +55,10 @@ void node_compositor_store_output_int2(const float id, vec3 value, out vec3 out_ store_int2(floatBitsToUint(id), value); out_value = value; } + +/* GPUMaterial doesn't support bool, so it is passed as a float. */ +void node_compositor_store_output_bool(const float id, float value, out float out_value) +{ + store_bool(floatBitsToUint(id), value); + out_value = value; +} diff --git a/source/blender/compositor/shaders/library/gpu_shader_compositor_type_conversion.glsl b/source/blender/compositor/shaders/library/gpu_shader_compositor_type_conversion.glsl index 6ef8a93ba0e..115df158c19 100644 --- a/source/blender/compositor/shaders/library/gpu_shader_compositor_type_conversion.glsl +++ b/source/blender/compositor/shaders/library/gpu_shader_compositor_type_conversion.glsl @@ -36,6 +36,11 @@ vec4 float_to_float4(float value) return vec4(value); } +bool float_to_bool(float value) +{ + return value > 0.0; +} + /* -------------------------------------------------------------------- * Int to other. */ @@ -70,6 +75,11 @@ vec4 int_to_float4(int value) return float_to_float4(int_to_float(value)); } +bool int_to_bool(int value) +{ + return value > 0; +} + /* -------------------------------------------------------------------- * Float2 to other. */ @@ -104,6 +114,11 @@ vec4 float2_to_float4(vec2 value) return vec4(value, 0.0, 0.0); } +bool float2_to_bool(vec2 value) +{ + return !all(equal(value, vec2(0.0))); +} + /* -------------------------------------------------------------------- * Float3 to other. */ @@ -138,6 +153,11 @@ vec4 float3_to_float4(vec3 value) return vec4(value, 0.0); } +bool float3_to_bool(vec3 value) +{ + return !all(equal(value, vec3(0.0))); +} + /* -------------------------------------------------------------------- * Color to other. */ @@ -172,6 +192,11 @@ vec4 color_to_float4(vec4 value) return value; } +bool color_to_bool(vec4 value, vec3 luminance_coefficients) +{ + return color_to_float(value, luminance_coefficients) > 0.0; +} + /* -------------------------------------------------------------------- * Float4 to other. */ @@ -206,6 +231,11 @@ vec4 float4_to_color(vec4 value) return value; } +bool float4_to_bool(vec4 value) +{ + return !all(equal(value, vec4(0.0))); +} + /* -------------------------------------------------------------------- * Int2 to other. */ @@ -240,6 +270,50 @@ vec4 int2_to_float4(ivec2 value) return vec4(vec2(value), 0.0, 0.0); } +bool int2_to_bool(ivec2 value) +{ + return !all(equal(value, ivec2(0))); +} + +/* -------------------------------------------------------------------- + * Bool to other. + */ + +float bool_to_float(bool value) +{ + return float(value); +} + +int bool_to_int(bool value) +{ + return int(value); +} + +vec2 bool_to_float2(bool value) +{ + return vec2(value); +} + +vec3 bool_to_float3(bool value) +{ + return vec3(value); +} + +vec4 bool_to_color(bool value) +{ + return vec4(value); +} + +vec4 bool_to_float4(bool value) +{ + return vec4(value); +} + +ivec2 bool_to_int2(bool value) +{ + return ivec2(value); +} + /* -------------------------------------------------------------------- * GPUMatrial-specific implicit conversion functions. * diff --git a/source/blender/nodes/composite/node_composite_tree.cc b/source/blender/nodes/composite/node_composite_tree.cc index a64a6fee4ce..51353fe286e 100644 --- a/source/blender/nodes/composite/node_composite_tree.cc +++ b/source/blender/nodes/composite/node_composite_tree.cc @@ -138,7 +138,7 @@ static bool composite_node_tree_socket_type_valid(blender::bke::bNodeTreeType * blender::bke::bNodeSocketType *socket_type) { return blender::bke::node_is_static_socket_type(*socket_type) && - ELEM(socket_type->type, SOCK_FLOAT, SOCK_INT, SOCK_VECTOR, SOCK_RGBA); + ELEM(socket_type->type, SOCK_FLOAT, SOCK_INT, SOCK_BOOLEAN, SOCK_VECTOR, SOCK_RGBA); } static bool composite_validate_link(eNodeSocketDatatype /*from*/, eNodeSocketDatatype /*to*/) diff --git a/source/blender/nodes/composite/nodes/node_composite_file_output.cc b/source/blender/nodes/composite/nodes/node_composite_file_output.cc index be66bb8ec94..fb92d6b2dc3 100644 --- a/source/blender/nodes/composite/nodes/node_composite_file_output.cc +++ b/source/blender/nodes/composite/nodes/node_composite_file_output.cc @@ -703,6 +703,8 @@ class FileOutputOperation : public NodeOperation { break; case ResultType::Int: file_output.add_pass(pass_name, view_name, "V", buffer); + case ResultType::Bool: + file_output.add_pass(pass_name, view_name, "V", buffer); break; } } @@ -737,6 +739,11 @@ class FileOutputOperation : public NodeOperation { CPPType::get().fill_assign_n(&value, buffer, length); return buffer; } + case ResultType::Bool: { + const float value = float(result.get_single_value()); + CPPType::get().fill_assign_n(&value, buffer, length); + return buffer; + } } BLI_assert_unreachable(); @@ -782,6 +789,7 @@ class FileOutputOperation : public NodeOperation { case ResultType::Float2: case ResultType::Int2: case ResultType::Int: + case ResultType::Bool: /* Not supported. */ BLI_assert_unreachable(); break; diff --git a/source/blender/nodes/composite/nodes/node_composite_image.cc b/source/blender/nodes/composite/nodes/node_composite_image.cc index 99ae0ba31b6..9d30e16f5a6 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.cc +++ b/source/blender/nodes/composite/nodes/node_composite_image.cc @@ -797,6 +797,7 @@ class RenderLayerOperation : public NodeOperation { case ResultType::Int: case ResultType::Int2: case ResultType::Float2: + case ResultType::Bool: /* Not supported. */ break; } diff --git a/tests/python/bl_node_group_interface.py b/tests/python/bl_node_group_interface.py index d9e9d49df28..cd8f45d7c56 100644 --- a/tests/python/bl_node_group_interface.py +++ b/tests/python/bl_node_group_interface.py @@ -440,7 +440,7 @@ class CompositorNodeGroupInterfaceTest(AbstractNodeGroupInterfaceTest, NodeGroup self.do_test_sockets_in_out("NodeSocketFloat") def test_all_socket_types(self): - self.do_test_invalid_socket_type("NodeSocketBool") + self.do_test_socket_type("NodeSocketBool") self.do_test_invalid_socket_type("NodeSocketCollection") self.do_test_socket_type("NodeSocketColor") self.do_test_socket_type("NodeSocketFloat")