diff --git a/scripts/startup/bl_ui/node_add_menu_geometry.py b/scripts/startup/bl_ui/node_add_menu_geometry.py index 9b37a018c4d..1647997580b 100644 --- a/scripts/startup/bl_ui/node_add_menu_geometry.py +++ b/scripts/startup/bl_ui/node_add_menu_geometry.py @@ -33,6 +33,7 @@ class NODE_MT_geometry_node_GEO_COLOR(Menu): def draw(self, _context): layout = self.layout + node_add_menu.add_node_type(layout, "ShaderNodeBlackbody") node_add_menu.add_node_type(layout, "ShaderNodeValToRGB") node_add_menu.add_node_type(layout, "ShaderNodeRGBCurve") layout.separator() diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 545b10a9e6e..fba3c653037 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -534,10 +534,12 @@ enum { /** \name Rendering Tables * \{ */ +void IMB_colormanagement_blackbody_temperature_to_rgb(float r_dest[4], float value); void IMB_colormanagement_blackbody_temperature_to_rgb_table(float *r_table, int width, float min, float max); +void IMB_colormanagement_wavelength_to_rgb(float r_dest[4], float value); void IMB_colormanagement_wavelength_to_rgb_table(float *r_table, int width); /** \} */ diff --git a/source/blender/imbuf/intern/colormanagement.cc b/source/blender/imbuf/intern/colormanagement.cc index 12c7e933947..351f0c2b4ba 100644 --- a/source/blender/imbuf/intern/colormanagement.cc +++ b/source/blender/imbuf/intern/colormanagement.cc @@ -4340,6 +4340,19 @@ static void blackbody_temperature_to_rec709(float rec709[3], float t) } } +void IMB_colormanagement_blackbody_temperature_to_rgb(float r_dest[4], float value) +{ + float rec709[3]; + blackbody_temperature_to_rec709(rec709, value); + + float rgb[3]; + IMB_colormanagement_rec709_to_scene_linear(rgb, rec709); + clamp_v3(rgb, 0.0f, FLT_MAX); + + copy_v3_v3(r_dest, rgb); + r_dest[3] = 1.0f; +} + void IMB_colormanagement_blackbody_temperature_to_rgb_table(float *r_table, const int width, const float min, @@ -4347,16 +4360,7 @@ void IMB_colormanagement_blackbody_temperature_to_rgb_table(float *r_table, { for (int i = 0; i < width; i++) { float temperature = min + (max - min) / float(width) * float(i); - - float rec709[3]; - blackbody_temperature_to_rec709(rec709, temperature); - - float rgb[3]; - IMB_colormanagement_rec709_to_scene_linear(rgb, rec709); - clamp_v3(rgb, 0.0f, FLT_MAX); - - copy_v3_v3(&r_table[i * 4], rgb); - r_table[i * 4 + 3] = 0.0f; + IMB_colormanagement_blackbody_temperature_to_rgb(&r_table[i * 4], temperature); } } @@ -4420,20 +4424,24 @@ static void wavelength_to_xyz(float xyz[3], float lambda_nm) } } +void IMB_colormanagement_wavelength_to_rgb(float r_dest[4], float value) +{ + float xyz[3]; + wavelength_to_xyz(xyz, value); + + float rgb[3]; + IMB_colormanagement_xyz_to_scene_linear(rgb, xyz); + clamp_v3(rgb, 0.0f, FLT_MAX); + + copy_v3_v3(r_dest, rgb); + r_dest[3] = 1.0f; +} + void IMB_colormanagement_wavelength_to_rgb_table(float *r_table, const int width) { for (int i = 0; i < width; i++) { - float temperature = 380 + 400 / float(width) * float(i); - - float xyz[3]; - wavelength_to_xyz(xyz, temperature); - - float rgb[3]; - IMB_colormanagement_xyz_to_scene_linear(rgb, xyz); - clamp_v3(rgb, 0.0f, FLT_MAX); - - copy_v3_v3(&r_table[i * 4], rgb); - r_table[i * 4 + 3] = 0.0f; + float wavelength = 380 + 400 / float(width) * float(i); + IMB_colormanagement_wavelength_to_rgb(&r_table[i * 4], wavelength); } } diff --git a/source/blender/nodes/shader/nodes/node_shader_blackbody.cc b/source/blender/nodes/shader/nodes/node_shader_blackbody.cc index 915ee52d310..251b55979af 100644 --- a/source/blender/nodes/shader/nodes/node_shader_blackbody.cc +++ b/source/blender/nodes/shader/nodes/node_shader_blackbody.cc @@ -2,14 +2,19 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ +#include "FN_multi_function_builder.hh" +#include "NOD_multi_function.hh" #include "node_shader_util.hh" +#include "node_util.hh" +#include "BLI_color.hh" #include "IMB_colormanagement.h" namespace blender::nodes::node_shader_blackbody_cc { static void node_declare(NodeDeclarationBuilder &b) { + b.is_function_node(); b.add_input("Temperature").default_value(1500.0f).min(800.0f).max(12000.0f); b.add_output("Color"); } @@ -31,6 +36,16 @@ static int node_shader_gpu_blackbody(GPUMaterial *mat, return GPU_stack_link(mat, node, "node_blackbody", in, out, ramp_texture, GPU_constant(&layer)); } +static void sh_node_blackbody_build_multi_function(nodes::NodeMultiFunctionBuilder &builder) +{ + static auto fn = mf::build::SI1_SO("Blackbody", [](float temperature) { + float color[4]; + IMB_colormanagement_blackbody_temperature_to_rgb(color, temperature); + return ColorGeometry4f(color); + }); + builder.set_matching_fn(fn); +} + NODE_SHADER_MATERIALX_BEGIN #ifdef WITH_MATERIALX { @@ -57,10 +72,11 @@ void register_node_type_sh_blackbody() static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_BLACKBODY, "Blackbody", NODE_CLASS_CONVERTER); + sh_fn_node_type_base(&ntype, SH_NODE_BLACKBODY, "Blackbody", NODE_CLASS_CONVERTER); ntype.declare = file_ns::node_declare; blender::bke::node_type_size_preset(&ntype, blender::bke::eNodeSizePreset::MIDDLE); ntype.gpu_fn = file_ns::node_shader_gpu_blackbody; + ntype.build_multi_function = file_ns::sh_node_blackbody_build_multi_function; ntype.materialx_fn = file_ns::node_shader_materialx; nodeRegisterType(&ntype);