From 4321d6f234d4a5a5c47349a9bd9d3f2860ed5b5f Mon Sep 17 00:00:00 2001 From: Cody Winchester Date: Tue, 28 Oct 2025 22:54:01 -0500 Subject: [PATCH] GOOENGINE: Fix light info node data storing Switches the light info node to capture the light properties into GPU uniforms instead of accessing the values from the light data This allows changing the color and energy without recompiling shaders and if the light object is animated the color and energy can be animated and update in the shader Big thanks to Joseph and Thorn for their help with this --- source/blender/makesdna/DNA_node_types.h | 6 -- .../blender/makesrna/intern/rna_nodetree.cc | 8 +-- .../shader/nodes/node_shader_light_info.cc | 56 +++++++++++-------- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 08d51b2404a..1ceaaba3f7d 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1565,12 +1565,6 @@ typedef enum eNodeWaterRipplesMode { NODE_WATER_RIPPLES_CAUSTIC = 3 } eNodeWaterRipplesMode; -typedef struct NodeShaderLightInfo { - /** Pointer to the Light object to get information from. */ - struct Object *light_object; - char _pad[8]; -} NodeShaderLightInfo; - typedef struct NodeSunBeams { float source[2]; diff --git a/source/blender/makesrna/intern/rna_nodetree.cc b/source/blender/makesrna/intern/rna_nodetree.cc index 2a3e61174fa..9830b60c540 100644 --- a/source/blender/makesrna/intern/rna_nodetree.cc +++ b/source/blender/makesrna/intern/rna_nodetree.cc @@ -3139,11 +3139,6 @@ static void rna_NodeGroup_node_tree_set(PointerRNA *ptr, } } -static bool rna_NodeShaderLightInfo_light_object_poll(PointerRNA * /*ptr*/, const PointerRNA value) -{ - return (static_cast(value.data))->type == OB_LAMP; -} - static bool rna_NodeGroup_node_tree_poll(PointerRNA *ptr, const PointerRNA value) { bNodeTree *ntree = reinterpret_cast(ptr->owner_id); @@ -5890,9 +5885,8 @@ static void def_sh_light_info(StructRNA *srna) PropertyRNA *prop; prop = RNA_def_property(srna, "light_object", PROP_POINTER, PROP_NONE); - RNA_def_property_pointer_sdna(prop, NULL, "id"); + RNA_def_property_pointer_sdna(prop, nullptr, "id"); RNA_def_property_struct_type(prop, "Object"); - RNA_def_property_pointer_funcs(prop, nullptr, nullptr, nullptr, "rna_NodeShaderLightInfo_light_object_poll"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Light Object", "Light object to get information from"); diff --git a/source/blender/nodes/shader/nodes/node_shader_light_info.cc b/source/blender/nodes/shader/nodes/node_shader_light_info.cc index ad57cbbed90..2174b39ef98 100644 --- a/source/blender/nodes/shader/nodes/node_shader_light_info.cc +++ b/source/blender/nodes/shader/nodes/node_shader_light_info.cc @@ -25,7 +25,6 @@ #include "UI_resources.hh" #include "node_shader_util.hh" -#include "../../intern/node_util.hh" namespace blender::nodes::node_shader_light_info_cc { @@ -34,7 +33,6 @@ static void sh_node_light_info_declare(NodeDeclarationBuilder &b) b.add_output("Light Color"); b.add_output("Light Power"); b.add_output("Perceptual Power"); - // b.add_output("Light Distance"); // Temporarily removed - causes crash } static void node_shader_draw_light_info(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) @@ -43,39 +41,53 @@ static void node_shader_draw_light_info(uiLayout *layout, bContext * /*C*/, Poin uiItemR(layout, ptr, "light_object", UI_ITEM_R_SPLIT_EMPTY_NAME, "Light", ICON_LIGHT); } +/* This is the function called during GPU node graph building (before compilation). */ static int node_shader_gpu_light_info(GPUMaterial *mat, bNode *node, bNodeExecData * /*execdata*/, GPUNodeStack *in, GPUNodeStack *out) { + /* Capture light properties NOW (during graph building on main thread) + * and store them as GPU uniforms. This avoids accessing the Light object + * from the background compilation thread. */ Object *ob = (Object *)node->id; - - /* Always use safe defaults to avoid crashes during material compilation */ - float light_color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - float light_power = 1.0f; - /* Only try to access object data if everything is valid */ - if (ob && ob != nullptr && - ob->type == OB_LAMP && - ob->data != nullptr) { + /* Always use safe defaults. */ + static float default_color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + static float default_power = 1.0f; + static float default_perceptual_power = 1.0f; + + GPUNodeLink *color_link; + GPUNodeLink *power_link; + GPUNodeLink *perceptual_power_link; + + /* Try to access light properties if object is valid. */ + if (ob && ob->type == OB_LAMP && ob->data != nullptr) { + Light *light = (Light *)ob->data; - Object *light_ob = ob; - Light *light = (Light *)light_ob->data; + /* Capture the light properties as GPU uniforms (thread-safe). */ + float color[4] = {light->r, light->g, light->b, 1.0f}; + float power = light->energy; + float perceptual_power = light->energy; - /* Safely get light properties */ - light_color[0] = light->r; - light_color[1] = light->g; - light_color[2] = light->b; - light_color[3] = 1.0f; - - light_power = light->energy; + /* Use GPU_uniform to capture these values safely for later compilation. */ + color_link = GPU_uniform(color); + power_link = GPU_uniform(&power); + perceptual_power_link = GPU_uniform(&perceptual_power); + } + else { + /* Use default values */ + color_link = GPU_uniform(default_color); + power_link = GPU_uniform(&default_power); + perceptual_power_link = GPU_uniform(&default_perceptual_power); } - /* Return shader call with just color and power - no distance */ + /* Pass the captured uniforms to the GPU stack. */ return GPU_stack_link(mat, node, "node_light_info_simple", in, out, - GPU_constant(light_color), /* Light Color */ - GPU_constant(&light_power)); /* Light Power */ + color_link, /* Light Color */ + power_link, /* Light Power */ + perceptual_power_link); /* Perceptual Power */ } } // namespace blender::nodes::node_shader_light_info_cc