Refactor: Compositor: Reduplicate type conversion code
This commit is contained in:
@@ -137,6 +137,7 @@ set(SRC
|
||||
cached_resources/COM_van_vliet_gaussian_coefficients.hh
|
||||
|
||||
utilities/COM_utilities_diagonals.hh
|
||||
utilities/COM_utilities_type_conversion.hh
|
||||
)
|
||||
|
||||
set(LIB
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GPU_shader.hh"
|
||||
|
||||
#include "COM_context.hh"
|
||||
#include "COM_input_descriptor.hh"
|
||||
#include "COM_result.hh"
|
||||
@@ -20,7 +18,9 @@ namespace blender::compositor {
|
||||
* classes for more details. */
|
||||
class ConversionOperation : public SimpleOperation {
|
||||
public:
|
||||
using SimpleOperation::SimpleOperation;
|
||||
ConversionOperation(Context &context,
|
||||
const ResultType input_type,
|
||||
const ResultType expected_type);
|
||||
|
||||
/* If the input result is a single value, execute_single is called. Otherwise, the shader
|
||||
* provided by get_conversion_shader is dispatched for GPU contexts or execute_cpu is called for
|
||||
@@ -34,111 +34,15 @@ class ConversionOperation : public SimpleOperation {
|
||||
const Result &input_result,
|
||||
const InputDescriptor &input_descriptor);
|
||||
|
||||
protected:
|
||||
private:
|
||||
/* Convert the input single value result to the output single value result. */
|
||||
virtual void execute_single(const Result &input, Result &output) = 0;
|
||||
void execute_single(const Result &input, Result &output);
|
||||
|
||||
/* Convert the input to the appropriate type and write the result to the output on the CPU. */
|
||||
virtual void execute_cpu(const Result &input, Result &output) = 0;
|
||||
void execute_cpu(const Result &input, Result &output);
|
||||
|
||||
/* Get the shader the will be used for conversion. */
|
||||
virtual GPUShader *get_conversion_shader() const = 0;
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Convert Float to Vector Operation
|
||||
*
|
||||
* Takes a float result and outputs a vector result. The first three components of the output are
|
||||
* filled with the input float, while the fourth component is set to 1. */
|
||||
class ConvertFloatToVectorOperation : public ConversionOperation {
|
||||
public:
|
||||
ConvertFloatToVectorOperation(Context &context);
|
||||
|
||||
void execute_single(const Result &input, Result &output) override;
|
||||
|
||||
void execute_cpu(const Result &input, Result &output) override;
|
||||
|
||||
GPUShader *get_conversion_shader() const override;
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Convert Float to Color Operation
|
||||
*
|
||||
* Takes a float result and outputs a color result. All three color channels of the output are
|
||||
* filled with the input float and the alpha channel is set to 1. */
|
||||
class ConvertFloatToColorOperation : public ConversionOperation {
|
||||
public:
|
||||
ConvertFloatToColorOperation(Context &context);
|
||||
|
||||
void execute_single(const Result &input, Result &output) override;
|
||||
|
||||
void execute_cpu(const Result &input, Result &output) override;
|
||||
|
||||
GPUShader *get_conversion_shader() const override;
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Convert Color to Float Operation
|
||||
*
|
||||
* Takes a color result and outputs a float result. The output is the average of the three color
|
||||
* channels, the alpha channel is ignored. */
|
||||
class ConvertColorToFloatOperation : public ConversionOperation {
|
||||
public:
|
||||
ConvertColorToFloatOperation(Context &context);
|
||||
|
||||
void execute_single(const Result &input, Result &output) override;
|
||||
|
||||
void execute_cpu(const Result &input, Result &output) override;
|
||||
|
||||
GPUShader *get_conversion_shader() const override;
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Convert Color to Vector Operation
|
||||
*
|
||||
* Takes a color result and outputs a vector result. The output is an exact copy of the input since
|
||||
* vectors are 4D. */
|
||||
class ConvertColorToVectorOperation : public ConversionOperation {
|
||||
public:
|
||||
ConvertColorToVectorOperation(Context &context);
|
||||
|
||||
void execute_single(const Result &input, Result &output) override;
|
||||
|
||||
void execute_cpu(const Result &input, Result &output) override;
|
||||
|
||||
GPUShader *get_conversion_shader() const override;
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Convert Vector to Float Operation
|
||||
*
|
||||
* Takes a vector result and outputs a float result. The output is the average of the three
|
||||
*components. */
|
||||
class ConvertVectorToFloatOperation : public ConversionOperation {
|
||||
public:
|
||||
ConvertVectorToFloatOperation(Context &context);
|
||||
|
||||
void execute_single(const Result &input, Result &output) override;
|
||||
|
||||
void execute_cpu(const Result &input, Result &output) override;
|
||||
|
||||
GPUShader *get_conversion_shader() const override;
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Convert Vector to Color Operation
|
||||
*
|
||||
* Takes a vector result and outputs a color result. The output is a copy of the three vector
|
||||
* components to the three color channels with the alpha channel set to 1. */
|
||||
class ConvertVectorToColorOperation : public ConversionOperation {
|
||||
public:
|
||||
ConvertVectorToColorOperation(Context &context);
|
||||
|
||||
void execute_single(const Result &input, Result &output) override;
|
||||
|
||||
void execute_cpu(const Result &input, Result &output) override;
|
||||
|
||||
GPUShader *get_conversion_shader() const override;
|
||||
/* Get the name of the shader the will be used for conversion. */
|
||||
const char *get_conversion_shader_name();
|
||||
};
|
||||
|
||||
} // namespace blender::compositor
|
||||
|
||||
@@ -11,17 +11,23 @@
|
||||
#include "COM_input_descriptor.hh"
|
||||
#include "COM_result.hh"
|
||||
#include "COM_utilities.hh"
|
||||
#include "COM_utilities_type_conversion.hh"
|
||||
|
||||
namespace blender::compositor {
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Conversion Operation
|
||||
*/
|
||||
ConversionOperation::ConversionOperation(Context &context,
|
||||
const ResultType input_type,
|
||||
const ResultType expected_type)
|
||||
: SimpleOperation(context)
|
||||
{
|
||||
this->declare_input_descriptor(InputDescriptor{input_type});
|
||||
this->populate_result(context.create_result(expected_type));
|
||||
}
|
||||
|
||||
void ConversionOperation::execute()
|
||||
{
|
||||
Result &result = get_result();
|
||||
const Result &input = get_input();
|
||||
Result &result = this->get_result();
|
||||
const Result &input = this->get_input();
|
||||
|
||||
if (input.is_single_value()) {
|
||||
result.allocate_single_value();
|
||||
@@ -30,8 +36,8 @@ void ConversionOperation::execute()
|
||||
}
|
||||
|
||||
result.allocate_texture(input.domain());
|
||||
if (context().use_gpu()) {
|
||||
GPUShader *shader = get_conversion_shader();
|
||||
if (this->context().use_gpu()) {
|
||||
GPUShader *shader = this->context().get_shader(this->get_conversion_shader_name());
|
||||
GPU_shader_bind(shader);
|
||||
|
||||
input.bind_as_texture(shader, "input_tx");
|
||||
@@ -52,222 +58,211 @@ SimpleOperation *ConversionOperation::construct_if_needed(Context &context,
|
||||
const Result &input_result,
|
||||
const InputDescriptor &input_descriptor)
|
||||
{
|
||||
ResultType result_type = input_result.type();
|
||||
ResultType expected_type = input_descriptor.type;
|
||||
|
||||
/* If the result type differs from the expected type, return an instance of an appropriate
|
||||
* conversion operation. Otherwise, return a null pointer. */
|
||||
|
||||
if (result_type == ResultType::Float && expected_type == ResultType::Vector) {
|
||||
return new ConvertFloatToVectorOperation(context);
|
||||
const ResultType result_type = input_result.type();
|
||||
const ResultType expected_type = input_descriptor.type;
|
||||
if (result_type != expected_type) {
|
||||
return new ConversionOperation(context, result_type, expected_type);
|
||||
}
|
||||
|
||||
if (result_type == ResultType::Float && expected_type == ResultType::Color) {
|
||||
return new ConvertFloatToColorOperation(context);
|
||||
}
|
||||
|
||||
if (result_type == ResultType::Color && expected_type == ResultType::Float) {
|
||||
return new ConvertColorToFloatOperation(context);
|
||||
}
|
||||
|
||||
if (result_type == ResultType::Color && expected_type == ResultType::Vector) {
|
||||
return new ConvertColorToVectorOperation(context);
|
||||
}
|
||||
|
||||
if (result_type == ResultType::Vector && expected_type == ResultType::Float) {
|
||||
return new ConvertVectorToFloatOperation(context);
|
||||
}
|
||||
|
||||
if (result_type == ResultType::Vector && expected_type == ResultType::Color) {
|
||||
return new ConvertVectorToColorOperation(context);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Convert Float to Vector Operation
|
||||
*/
|
||||
|
||||
ConvertFloatToVectorOperation::ConvertFloatToVectorOperation(Context &context)
|
||||
: ConversionOperation(context)
|
||||
const char *ConversionOperation::get_conversion_shader_name()
|
||||
{
|
||||
InputDescriptor input_descriptor;
|
||||
input_descriptor.type = ResultType::Float;
|
||||
declare_input_descriptor(input_descriptor);
|
||||
populate_result(context.create_result(ResultType::Vector));
|
||||
switch (this->get_input().type()) {
|
||||
case ResultType::Float:
|
||||
switch (this->get_result().type()) {
|
||||
case ResultType::Vector:
|
||||
return "compositor_convert_float_to_vector";
|
||||
case ResultType::Color:
|
||||
return "compositor_convert_float_to_color";
|
||||
case ResultType::Float:
|
||||
/* Same type, no conversion needed. */
|
||||
break;
|
||||
case ResultType::Float2:
|
||||
case ResultType::Float3:
|
||||
case ResultType::Int2:
|
||||
/* Types are not user facing, so we needn't implement them. */
|
||||
break;
|
||||
}
|
||||
case ResultType::Vector:
|
||||
switch (this->get_result().type()) {
|
||||
case ResultType::Float:
|
||||
return "compositor_convert_vector_to_float";
|
||||
case ResultType::Color:
|
||||
return "compositor_convert_vector_to_color";
|
||||
case ResultType::Vector:
|
||||
/* Same type, no conversion needed. */
|
||||
break;
|
||||
case ResultType::Float2:
|
||||
case ResultType::Float3:
|
||||
case ResultType::Int2:
|
||||
/* Types are not user facing, so we needn't implement them. */
|
||||
break;
|
||||
}
|
||||
case ResultType::Color:
|
||||
switch (this->get_result().type()) {
|
||||
case ResultType::Float:
|
||||
return "compositor_convert_color_to_float";
|
||||
case ResultType::Vector:
|
||||
return "compositor_convert_color_to_vector";
|
||||
case ResultType::Color:
|
||||
/* Same type, no conversion needed. */
|
||||
break;
|
||||
case ResultType::Float2:
|
||||
case ResultType::Float3:
|
||||
case ResultType::Int2:
|
||||
/* Types are not user facing, so we needn't implement them. */
|
||||
break;
|
||||
}
|
||||
case ResultType::Float2:
|
||||
case ResultType::Float3:
|
||||
case ResultType::Int2:
|
||||
/* Types are not user facing, so we needn't implement them. */
|
||||
break;
|
||||
}
|
||||
|
||||
BLI_assert_unreachable();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ConvertFloatToVectorOperation::execute_single(const Result &input, Result &output)
|
||||
void ConversionOperation::execute_single(const Result &input, Result &output)
|
||||
{
|
||||
output.set_single_value(float4(float3(input.get_single_value<float>()), 1.0f));
|
||||
switch (this->get_input().type()) {
|
||||
case ResultType::Float:
|
||||
switch (this->get_result().type()) {
|
||||
case ResultType::Vector:
|
||||
output.set_single_value(float_to_vector(input.get_single_value<float>()));
|
||||
return;
|
||||
case ResultType::Color:
|
||||
output.set_single_value(float_to_color(input.get_single_value<float>()));
|
||||
return;
|
||||
case ResultType::Float:
|
||||
/* Same type, no conversion needed. */
|
||||
break;
|
||||
case ResultType::Float2:
|
||||
case ResultType::Float3:
|
||||
case ResultType::Int2:
|
||||
/* Types are not user facing, so we needn't implement them. */
|
||||
break;
|
||||
}
|
||||
case ResultType::Vector:
|
||||
switch (this->get_result().type()) {
|
||||
case ResultType::Float:
|
||||
output.set_single_value(vector_to_float(input.get_single_value<float4>()));
|
||||
return;
|
||||
case ResultType::Color:
|
||||
output.set_single_value(vector_to_color(input.get_single_value<float4>()));
|
||||
return;
|
||||
case ResultType::Vector:
|
||||
/* Same type, no conversion needed. */
|
||||
break;
|
||||
case ResultType::Float2:
|
||||
case ResultType::Float3:
|
||||
case ResultType::Int2:
|
||||
/* Types are not user facing, so we needn't implement them. */
|
||||
break;
|
||||
}
|
||||
case ResultType::Color:
|
||||
switch (this->get_result().type()) {
|
||||
case ResultType::Float:
|
||||
output.set_single_value(color_to_float(input.get_single_value<float4>()));
|
||||
return;
|
||||
case ResultType::Vector:
|
||||
output.set_single_value(color_to_vector(input.get_single_value<float4>()));
|
||||
return;
|
||||
case ResultType::Color:
|
||||
/* Same type, no conversion needed. */
|
||||
break;
|
||||
case ResultType::Float2:
|
||||
case ResultType::Float3:
|
||||
case ResultType::Int2:
|
||||
/* Types are not user facing, so we needn't implement them. */
|
||||
break;
|
||||
}
|
||||
case ResultType::Float2:
|
||||
case ResultType::Float3:
|
||||
case ResultType::Int2:
|
||||
/* Types are not user facing, so we needn't implement them. */
|
||||
break;
|
||||
}
|
||||
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
|
||||
void ConvertFloatToVectorOperation::execute_cpu(const Result &input, Result &output)
|
||||
void ConversionOperation::execute_cpu(const Result &input, Result &output)
|
||||
{
|
||||
parallel_for(input.domain().size, [&](const int2 texel) {
|
||||
output.store_pixel(texel, float4(float3(input.load_pixel<float>(texel)), 1.0f));
|
||||
});
|
||||
}
|
||||
switch (this->get_input().type()) {
|
||||
case ResultType::Float:
|
||||
switch (this->get_result().type()) {
|
||||
case ResultType::Vector:
|
||||
parallel_for(input.domain().size, [&](const int2 texel) {
|
||||
output.store_pixel(texel, float_to_vector(input.load_pixel<float>(texel)));
|
||||
});
|
||||
return;
|
||||
case ResultType::Color:
|
||||
parallel_for(input.domain().size, [&](const int2 texel) {
|
||||
output.store_pixel(texel, float_to_color(input.load_pixel<float>(texel)));
|
||||
});
|
||||
return;
|
||||
case ResultType::Float:
|
||||
/* Same type, no conversion needed. */
|
||||
break;
|
||||
case ResultType::Float2:
|
||||
case ResultType::Float3:
|
||||
case ResultType::Int2:
|
||||
/* Types are not user facing, so we needn't implement them. */
|
||||
break;
|
||||
}
|
||||
case ResultType::Vector:
|
||||
switch (this->get_result().type()) {
|
||||
case ResultType::Float:
|
||||
parallel_for(input.domain().size, [&](const int2 texel) {
|
||||
output.store_pixel(texel, vector_to_float(input.load_pixel<float4>(texel)));
|
||||
});
|
||||
return;
|
||||
case ResultType::Color:
|
||||
parallel_for(input.domain().size, [&](const int2 texel) {
|
||||
output.store_pixel(texel, vector_to_color(input.load_pixel<float4>(texel)));
|
||||
});
|
||||
return;
|
||||
case ResultType::Vector:
|
||||
/* Same type, no conversion needed. */
|
||||
break;
|
||||
case ResultType::Float2:
|
||||
case ResultType::Float3:
|
||||
case ResultType::Int2:
|
||||
/* Types are not user facing, so we needn't implement them. */
|
||||
break;
|
||||
}
|
||||
case ResultType::Color:
|
||||
switch (this->get_result().type()) {
|
||||
case ResultType::Float:
|
||||
parallel_for(input.domain().size, [&](const int2 texel) {
|
||||
output.store_pixel(texel, color_to_float(input.load_pixel<float4>(texel)));
|
||||
});
|
||||
return;
|
||||
case ResultType::Vector:
|
||||
parallel_for(input.domain().size, [&](const int2 texel) {
|
||||
output.store_pixel(texel, color_to_vector(input.load_pixel<float4>(texel)));
|
||||
});
|
||||
return;
|
||||
case ResultType::Color:
|
||||
/* Same type, no conversion needed. */
|
||||
break;
|
||||
case ResultType::Float2:
|
||||
case ResultType::Float3:
|
||||
case ResultType::Int2:
|
||||
/* Types are not user facing, so we needn't implement them. */
|
||||
break;
|
||||
}
|
||||
case ResultType::Float2:
|
||||
case ResultType::Float3:
|
||||
case ResultType::Int2:
|
||||
/* Types are not user facing, so we needn't implement them. */
|
||||
break;
|
||||
}
|
||||
|
||||
GPUShader *ConvertFloatToVectorOperation::get_conversion_shader() const
|
||||
{
|
||||
return context().get_shader("compositor_convert_float_to_vector");
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Convert Float to Color Operation
|
||||
*/
|
||||
|
||||
ConvertFloatToColorOperation::ConvertFloatToColorOperation(Context &context)
|
||||
: ConversionOperation(context)
|
||||
{
|
||||
InputDescriptor input_descriptor;
|
||||
input_descriptor.type = ResultType::Float;
|
||||
declare_input_descriptor(input_descriptor);
|
||||
populate_result(context.create_result(ResultType::Color));
|
||||
}
|
||||
|
||||
void ConvertFloatToColorOperation::execute_single(const Result &input, Result &output)
|
||||
{
|
||||
output.set_single_value(float4(float3(input.get_single_value<float>()), 1.0f));
|
||||
}
|
||||
|
||||
void ConvertFloatToColorOperation::execute_cpu(const Result &input, Result &output)
|
||||
{
|
||||
parallel_for(input.domain().size, [&](const int2 texel) {
|
||||
output.store_pixel(texel, float4(float3(input.load_pixel<float>(texel)), 1.0f));
|
||||
});
|
||||
}
|
||||
|
||||
GPUShader *ConvertFloatToColorOperation::get_conversion_shader() const
|
||||
{
|
||||
return context().get_shader("compositor_convert_float_to_color");
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Convert Color to Float Operation
|
||||
*/
|
||||
|
||||
ConvertColorToFloatOperation::ConvertColorToFloatOperation(Context &context)
|
||||
: ConversionOperation(context)
|
||||
{
|
||||
InputDescriptor input_descriptor;
|
||||
input_descriptor.type = ResultType::Color;
|
||||
declare_input_descriptor(input_descriptor);
|
||||
populate_result(context.create_result(ResultType::Float));
|
||||
}
|
||||
|
||||
void ConvertColorToFloatOperation::execute_single(const Result &input, Result &output)
|
||||
{
|
||||
float4 color = input.get_single_value<float4>();
|
||||
output.set_single_value((color.x + color.y + color.z) / 3.0f);
|
||||
}
|
||||
|
||||
void ConvertColorToFloatOperation::execute_cpu(const Result &input, Result &output)
|
||||
{
|
||||
parallel_for(input.domain().size, [&](const int2 texel) {
|
||||
const float4 color = input.load_pixel<float4>(texel);
|
||||
output.store_pixel(texel, (color.x + color.y + color.z) / 3.0f);
|
||||
});
|
||||
}
|
||||
|
||||
GPUShader *ConvertColorToFloatOperation::get_conversion_shader() const
|
||||
{
|
||||
return context().get_shader("compositor_convert_color_to_float");
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Convert Color to Vector Operation
|
||||
*/
|
||||
|
||||
ConvertColorToVectorOperation::ConvertColorToVectorOperation(Context &context)
|
||||
: ConversionOperation(context)
|
||||
{
|
||||
InputDescriptor input_descriptor;
|
||||
input_descriptor.type = ResultType::Color;
|
||||
declare_input_descriptor(input_descriptor);
|
||||
populate_result(context.create_result(ResultType::Vector));
|
||||
}
|
||||
|
||||
void ConvertColorToVectorOperation::execute_single(const Result &input, Result &output)
|
||||
{
|
||||
float4 color = input.get_single_value<float4>();
|
||||
output.set_single_value(color);
|
||||
}
|
||||
|
||||
void ConvertColorToVectorOperation::execute_cpu(const Result &input, Result &output)
|
||||
{
|
||||
parallel_for(input.domain().size, [&](const int2 texel) {
|
||||
output.store_pixel(texel, input.load_pixel<float4>(texel));
|
||||
});
|
||||
}
|
||||
|
||||
GPUShader *ConvertColorToVectorOperation::get_conversion_shader() const
|
||||
{
|
||||
return context().get_shader("compositor_convert_color_to_vector");
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Convert Vector to Float Operation
|
||||
*/
|
||||
|
||||
ConvertVectorToFloatOperation::ConvertVectorToFloatOperation(Context &context)
|
||||
: ConversionOperation(context)
|
||||
{
|
||||
InputDescriptor input_descriptor;
|
||||
input_descriptor.type = ResultType::Vector;
|
||||
declare_input_descriptor(input_descriptor);
|
||||
populate_result(context.create_result(ResultType::Float));
|
||||
}
|
||||
|
||||
void ConvertVectorToFloatOperation::execute_single(const Result &input, Result &output)
|
||||
{
|
||||
float4 vector = input.get_single_value<float4>();
|
||||
output.set_single_value((vector[0] + vector[1] + vector[2]) / 3.0f);
|
||||
}
|
||||
|
||||
void ConvertVectorToFloatOperation::execute_cpu(const Result &input, Result &output)
|
||||
{
|
||||
parallel_for(input.domain().size, [&](const int2 texel) {
|
||||
const float4 vector = input.load_pixel<float4>(texel);
|
||||
output.store_pixel(texel, (vector.x + vector.y + vector.z) / 3.0f);
|
||||
});
|
||||
}
|
||||
|
||||
GPUShader *ConvertVectorToFloatOperation::get_conversion_shader() const
|
||||
{
|
||||
return context().get_shader("compositor_convert_vector_to_float");
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Convert Vector to Color Operation
|
||||
*/
|
||||
|
||||
ConvertVectorToColorOperation::ConvertVectorToColorOperation(Context &context)
|
||||
: ConversionOperation(context)
|
||||
{
|
||||
InputDescriptor input_descriptor;
|
||||
input_descriptor.type = ResultType::Vector;
|
||||
declare_input_descriptor(input_descriptor);
|
||||
populate_result(context.create_result(ResultType::Color));
|
||||
}
|
||||
|
||||
void ConvertVectorToColorOperation::execute_single(const Result &input, Result &output)
|
||||
{
|
||||
output.set_single_value(float4(float3(input.get_single_value<float4>()), 1.0f));
|
||||
}
|
||||
|
||||
void ConvertVectorToColorOperation::execute_cpu(const Result &input, Result &output)
|
||||
{
|
||||
parallel_for(input.domain().size, [&](const int2 texel) {
|
||||
output.store_pixel(texel, float4(input.load_pixel<float4>(texel).xyz(), 1.0f));
|
||||
});
|
||||
}
|
||||
|
||||
GPUShader *ConvertVectorToColorOperation::get_conversion_shader() const
|
||||
{
|
||||
return context().get_shader("compositor_convert_vector_to_color");
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
|
||||
} // namespace blender::compositor
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "COM_result.hh"
|
||||
#include "COM_scheduler.hh"
|
||||
#include "COM_utilities.hh"
|
||||
#include "COM_utilities_type_conversion.hh"
|
||||
|
||||
namespace blender::compositor {
|
||||
|
||||
@@ -290,54 +291,70 @@ mf::Variable *MultiFunctionProcedureOperation::get_multi_function_input_variable
|
||||
static mf::MultiFunction *get_conversion_function(const ResultType variable_type,
|
||||
const ResultType expected_type)
|
||||
{
|
||||
/* No conversion needed. */
|
||||
if (expected_type == variable_type) {
|
||||
return nullptr;
|
||||
}
|
||||
static auto float_to_vector_function = mf::build::SI1_SO<float, float4>(
|
||||
"Float To Vector", float_to_vector, mf::build::exec_presets::AllSpanOrSingle());
|
||||
static auto float_to_color_function = mf::build::SI1_SO<float, float4>(
|
||||
"Float To Color", float_to_color, mf::build::exec_presets::AllSpanOrSingle());
|
||||
static auto vector_to_float_function = mf::build::SI1_SO<float4, float>(
|
||||
"Vector To Float", vector_to_float, mf::build::exec_presets::AllSpanOrSingle());
|
||||
static auto vector_to_color_function = mf::build::SI1_SO<float4, float4>(
|
||||
"Vector To Color", vector_to_color, mf::build::exec_presets::AllSpanOrSingle());
|
||||
static auto color_to_float_function = mf::build::SI1_SO<float4, float>(
|
||||
"Color To Float", color_to_float, mf::build::exec_presets::AllSpanOrSingle());
|
||||
static auto color_to_vector_function = mf::build::SI1_SO<float4, float4>(
|
||||
"Color To Vector", color_to_vector, mf::build::exec_presets::AllSpanOrSingle());
|
||||
|
||||
if (variable_type == ResultType::Float && expected_type == ResultType::Vector) {
|
||||
static auto float_to_vector_function = mf::build::SI1_SO<float, float4>(
|
||||
"Float To Vector",
|
||||
[](const float &input) -> float4 { return float4(float3(input), 1.0f); },
|
||||
mf::build::exec_presets::AllSpanOrSingle());
|
||||
return &float_to_vector_function;
|
||||
}
|
||||
|
||||
if (variable_type == ResultType::Float && expected_type == ResultType::Color) {
|
||||
static auto float_to_color_function = mf::build::SI1_SO<float, float4>(
|
||||
"Float To Color",
|
||||
[](const float &input) -> float4 { return float4(float3(input), 1.0f); },
|
||||
mf::build::exec_presets::AllSpanOrSingle());
|
||||
return &float_to_color_function;
|
||||
}
|
||||
|
||||
if (variable_type == ResultType::Vector && expected_type == ResultType::Float) {
|
||||
static auto vector_to_float_function = mf::build::SI1_SO<float4, float>(
|
||||
"Vector To Float",
|
||||
[](const float4 &input) -> float { return (input.x + input.y + input.z) / 3.0f; },
|
||||
mf::build::exec_presets::AllSpanOrSingle());
|
||||
return &vector_to_float_function;
|
||||
}
|
||||
|
||||
if (variable_type == ResultType::Vector && expected_type == ResultType::Color) {
|
||||
static auto vector_to_color_function = mf::build::SI1_SO<float4, float4>(
|
||||
"Vector To Color",
|
||||
[](const float4 &input) -> float4 { return float4(input.xyz(), 1.0f); },
|
||||
mf::build::exec_presets::AllSpanOrSingle());
|
||||
return &vector_to_color_function;
|
||||
}
|
||||
|
||||
if (variable_type == ResultType::Color && expected_type == ResultType::Float) {
|
||||
static auto color_to_float_function = mf::build::SI1_SO<float4, float>(
|
||||
"Color To Float",
|
||||
[](const float4 &input) -> float { return (input.x + input.y + input.z) / 3.0f; },
|
||||
mf::build::exec_presets::AllSpanOrSingle());
|
||||
return &color_to_float_function;
|
||||
}
|
||||
|
||||
if (variable_type == ResultType::Color && expected_type == ResultType::Vector) {
|
||||
/* No conversion needed. */
|
||||
return nullptr;
|
||||
switch (variable_type) {
|
||||
case ResultType::Float:
|
||||
switch (expected_type) {
|
||||
case ResultType::Vector:
|
||||
return &float_to_vector_function;
|
||||
case ResultType::Color:
|
||||
return &float_to_color_function;
|
||||
case ResultType::Float:
|
||||
/* Same type, no conversion needed. */
|
||||
return nullptr;
|
||||
case ResultType::Float2:
|
||||
case ResultType::Float3:
|
||||
case ResultType::Int2:
|
||||
/* Types are not user facing, so we needn't implement them. */
|
||||
break;
|
||||
}
|
||||
case ResultType::Vector:
|
||||
switch (expected_type) {
|
||||
case ResultType::Float:
|
||||
return &vector_to_float_function;
|
||||
case ResultType::Color:
|
||||
return &vector_to_color_function;
|
||||
case ResultType::Vector:
|
||||
/* Same type, no conversion needed. */
|
||||
return nullptr;
|
||||
case ResultType::Float2:
|
||||
case ResultType::Float3:
|
||||
case ResultType::Int2:
|
||||
/* Types are not user facing, so we needn't implement them. */
|
||||
break;
|
||||
}
|
||||
case ResultType::Color:
|
||||
switch (expected_type) {
|
||||
case ResultType::Float:
|
||||
return &color_to_float_function;
|
||||
case ResultType::Vector:
|
||||
return &color_to_vector_function;
|
||||
case ResultType::Color:
|
||||
/* Same type, no conversion needed. */
|
||||
return nullptr;
|
||||
case ResultType::Float2:
|
||||
case ResultType::Float3:
|
||||
case ResultType::Int2:
|
||||
/* Types are not user facing, so we needn't implement them. */
|
||||
break;
|
||||
}
|
||||
case ResultType::Float2:
|
||||
case ResultType::Float3:
|
||||
case ResultType::Int2:
|
||||
/* Types are not user facing, so we needn't implement them. */
|
||||
break;
|
||||
}
|
||||
|
||||
BLI_assert_unreachable();
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/* SPDX-FileCopyrightText: 2024 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_math_vector.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
|
||||
namespace blender::compositor {
|
||||
|
||||
inline float4 float_to_vector(const float &input)
|
||||
{
|
||||
return float4(float3(input), 1.0f);
|
||||
}
|
||||
|
||||
inline float4 float_to_color(const float &input)
|
||||
{
|
||||
return float4(float3(input), 1.0f);
|
||||
}
|
||||
|
||||
inline float vector_to_float(const float4 &input)
|
||||
{
|
||||
return math::reduce_add(input.xyz()) / 3.0f;
|
||||
}
|
||||
|
||||
inline float4 vector_to_color(const float4 &input)
|
||||
{
|
||||
return float4(input.xyz(), 1.0f);
|
||||
}
|
||||
|
||||
inline float color_to_float(const float4 &input)
|
||||
{
|
||||
return math::reduce_add(input.xyz()) / 3.0f;
|
||||
}
|
||||
|
||||
inline float4 color_to_vector(const float4 &input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
} // namespace blender::compositor
|
||||
Reference in New Issue
Block a user