GOOENGINE: Add light info node
Patches originally written by Joseph and Thorn. Thank you! Adds a light info node
This commit is contained in:
@@ -343,6 +343,7 @@ class NODE_MT_category_goo_engine(Menu):
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeShaderInfo")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeScreenspaceInfo")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeCurvature")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeLightInfo")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeSetDepth")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeSdfPrimitive")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeSdfOp")
|
||||
|
||||
@@ -562,6 +562,7 @@ set(GLSL_SRC
|
||||
shaders/material/gpu_shader_material_combine_rgb.glsl
|
||||
shaders/material/gpu_shader_material_combine_xyz.glsl
|
||||
shaders/material/gpu_shader_material_curvature.glsl
|
||||
shaders/material/gpu_shader_material_light_info.glsl
|
||||
shaders/material/gpu_shader_material_diffuse.glsl
|
||||
shaders/material/gpu_shader_material_displacement.glsl
|
||||
shaders/material/gpu_shader_material_eevee_specular.glsl
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
float sRGBtoLin(float colorChannel)
|
||||
{
|
||||
if (colorChannel <= 0.04045) {
|
||||
return colorChannel / 12.92;
|
||||
}
|
||||
else {
|
||||
return pow((colorChannel + 0.055) / 1.055, 2.4);
|
||||
}
|
||||
}
|
||||
|
||||
float YtoLstar(float Y)
|
||||
{
|
||||
if (Y <= (216.0 / 24389.0)) {
|
||||
return Y * (24389.0 / 27.0);
|
||||
}
|
||||
else {
|
||||
return pow(Y, 1.0 / 3.0) * 116.0 - 16.0;
|
||||
}
|
||||
}
|
||||
|
||||
void node_light_info_simple(vec4 light_color,
|
||||
float light_power,
|
||||
out vec4 out_light_color,
|
||||
out float out_light_power,
|
||||
out float out_perceptual_power)
|
||||
{
|
||||
out_light_color = light_color;
|
||||
out_light_power = light_power;
|
||||
|
||||
// Linearize sRGB channels
|
||||
float vR = sRGBtoLin(light_color.r);
|
||||
float vG = sRGBtoLin(light_color.g);
|
||||
float vB = sRGBtoLin(light_color.b);
|
||||
|
||||
// Calculate luminance
|
||||
float Y = 0.2126 * vR + 0.7152 * vG + 0.0722 * vB;
|
||||
|
||||
// Calculate perceptual lightness (L*)
|
||||
float Lstar = YtoLstar(Y);
|
||||
|
||||
// Output perceptual lightness * light power
|
||||
out_perceptual_power = ((Lstar * light_power) / 255.0) * (2.489645);
|
||||
// normalize, then use the computed white constant
|
||||
}
|
||||
@@ -1565,6 +1565,12 @@ 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];
|
||||
|
||||
|
||||
@@ -3139,6 +3139,11 @@ static void rna_NodeGroup_node_tree_set(PointerRNA *ptr,
|
||||
}
|
||||
}
|
||||
|
||||
static bool rna_NodeShaderLightInfo_light_object_poll(PointerRNA * /*ptr*/, const PointerRNA value)
|
||||
{
|
||||
return (static_cast<Object *>(value.data))->type == OB_LAMP;
|
||||
}
|
||||
|
||||
static bool rna_NodeGroup_node_tree_poll(PointerRNA *ptr, const PointerRNA value)
|
||||
{
|
||||
bNodeTree *ntree = reinterpret_cast<bNodeTree *>(ptr->owner_id);
|
||||
@@ -5869,6 +5874,20 @@ static void def_sh_tex_hexagon(StructRNA *srna)
|
||||
RNA_def_property_update(prop, 0, "rna_Node_update");
|
||||
}
|
||||
|
||||
static void def_sh_light_info(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "NodeShaderLightInfo", "storage");
|
||||
|
||||
prop = RNA_def_property(srna, "light_object", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "light_object");
|
||||
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);
|
||||
RNA_def_property_ui_text(prop, "Light Object", "Light object to get information from");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
}
|
||||
|
||||
static void def_sh_tex_magic(StructRNA *srna)
|
||||
{
|
||||
|
||||
@@ -133,6 +133,7 @@ DefNode(ShaderNode, SH_NODE_SHADER_INFO, def_sh_shader_info, "SHA
|
||||
DefNode(ShaderNode, SH_NODE_TEX_HEXAGON, def_sh_tex_hexagon, "TEX_HEXAGON", TexHexagon, "Hex Grid Texture", "" )
|
||||
DefNode(ShaderNode, SH_NODE_TWIRL, def_sh_twirl, "TWIRL", Twirl, "Twirl", "Twirl the input vector around a center point by a specified amount")
|
||||
DefNode(ShaderNode, SH_NODE_WATER_RIPPLES, def_sh_water_ripples, "WATER_RIPPLES", WaterRipples, "Water Ripples", "Generate concentric ripples simulating water surface disturbances")
|
||||
DefNode(ShaderNode, SH_NODE_LIGHT_INFO, def_sh_light_info, "LIGHT_INFO", LightInfo, "Light Info", "Get information from a selected light object")
|
||||
DefNode(ShaderNode, SH_NODE_SCREENSPACE_INFO, 0, "SCREENSPACEINFO", ScreenspaceInfo, "Screenspace Info", "Sample internal colour and depth buffers")
|
||||
DefNode(ShaderNode, SH_NODE_SET_DEPTH, 0, "SET_DEPTH", SetDepth, "Set Depth", "Pixel depth offset")
|
||||
DefNode(ShaderNode, SH_NODE_CURVATURE, 0, "CURVATURE", Curvature, "Curvature", "" )
|
||||
|
||||
@@ -51,6 +51,7 @@ set(SRC
|
||||
nodes/node_shader_tex_hexagon.cc
|
||||
nodes/node_shader_twirl.cc
|
||||
nodes/node_shader_water_ripples.cc
|
||||
nodes/node_shader_light_info.cc
|
||||
nodes/node_shader_common.cc
|
||||
nodes/node_shader_curvature.cc
|
||||
nodes/node_shader_curves.cc
|
||||
|
||||
@@ -42,6 +42,7 @@ void register_shader_nodes()
|
||||
register_node_type_sh_tex_hexagon();
|
||||
register_node_type_sh_twirl();
|
||||
register_node_type_sh_water_ripples();
|
||||
register_node_type_sh_light_info();
|
||||
register_node_type_sh_curvature();
|
||||
register_node_type_sh_curve_float();
|
||||
register_node_type_sh_curve_rgb();
|
||||
|
||||
@@ -38,6 +38,7 @@ void register_node_type_sh_combxyz();
|
||||
void register_node_type_sh_tex_hexagon();
|
||||
void register_node_type_sh_twirl();
|
||||
void register_node_type_sh_water_ripples();
|
||||
void register_node_type_sh_light_info();
|
||||
void register_node_type_sh_curvature();
|
||||
void register_node_type_sh_curve_float();
|
||||
void register_node_type_sh_curve_rgb();
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/* SPDX-FileCopyrightText: 2025 Goo Engine Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup shdnodes
|
||||
*/
|
||||
|
||||
#include "DNA_light_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BKE_context.hh"
|
||||
#include "BKE_node.hh"
|
||||
#include "BKE_object.hh"
|
||||
|
||||
#include "GPU_material.hh"
|
||||
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_math_matrix.h"
|
||||
#include "BLI_math_rotation.h"
|
||||
|
||||
#include "DEG_depsgraph_query.hh"
|
||||
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.hh"
|
||||
|
||||
#include "node_shader_util.hh"
|
||||
#include "../../intern/node_util.hh"
|
||||
|
||||
namespace blender::nodes::node_shader_light_info_cc {
|
||||
|
||||
static void sh_node_light_info_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.add_output<decl::Color>("Light Color");
|
||||
b.add_output<decl::Float>("Light Power");
|
||||
b.add_output<decl::Float>("Perceptual Power");
|
||||
// b.add_output<decl::Float>("Light Distance"); // Temporarily removed - causes crash
|
||||
}
|
||||
|
||||
static void node_shader_init_light_info(bNodeTree * /*ntree*/, bNode *node)
|
||||
{
|
||||
NodeShaderLightInfo *data = MEM_cnew<NodeShaderLightInfo>(__func__);
|
||||
|
||||
/* Node starts with no light object selected */
|
||||
data->light_object = nullptr;
|
||||
|
||||
node->storage = data;
|
||||
}
|
||||
|
||||
static void node_shader_draw_light_info(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
|
||||
{
|
||||
/* Show light object selector */
|
||||
uiItemR(layout, ptr, "light_object", UI_ITEM_R_SPLIT_EMPTY_NAME, "Light", ICON_LIGHT);
|
||||
}
|
||||
|
||||
static int node_shader_gpu_light_info(GPUMaterial *mat,
|
||||
bNode *node,
|
||||
bNodeExecData * /*execdata*/,
|
||||
GPUNodeStack *in,
|
||||
GPUNodeStack *out)
|
||||
{
|
||||
NodeShaderLightInfo *data = (NodeShaderLightInfo *)node->storage;
|
||||
|
||||
/* 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 (data && data->light_object != nullptr &&
|
||||
data->light_object->type == OB_LAMP &&
|
||||
data->light_object->data != nullptr) {
|
||||
|
||||
Object *light_ob = data->light_object;
|
||||
Light *light = (Light *)light_ob->data;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* Return shader call with just color and power - no distance */
|
||||
return GPU_stack_link(mat, node, "node_light_info_simple", in, out,
|
||||
GPU_constant(light_color), /* Light Color */
|
||||
GPU_constant(&light_power)); /* Light Power */
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::node_shader_light_info_cc
|
||||
|
||||
/* node type definition */
|
||||
void register_node_type_sh_light_info(void)
|
||||
{
|
||||
namespace file_ns = blender::nodes::node_shader_light_info_cc;
|
||||
|
||||
static blender::bke::bNodeType ntype;
|
||||
|
||||
sh_node_type_base(&ntype, SH_NODE_LIGHT_INFO, "Light Info", NODE_CLASS_INPUT);
|
||||
ntype.declare = file_ns::sh_node_light_info_declare;
|
||||
node_type_storage(&ntype, "NodeShaderLightInfo", node_free_standard_storage, node_copy_standard_storage);
|
||||
ntype.gpu_fn = file_ns::node_shader_gpu_light_info;
|
||||
ntype.initfunc = file_ns::node_shader_init_light_info;
|
||||
ntype.draw_buttons = file_ns::node_shader_draw_light_info;
|
||||
|
||||
node_register_type(&ntype);
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/* SPDX-FileCopyrightText: 2025 Goo Engine Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup shdnodes
|
||||
*/
|
||||
|
||||
#include "DNA_light_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BKE_context.hh"
|
||||
#include "BKE_node.hh"
|
||||
|
||||
#include "GPU_material.hh"
|
||||
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_math_matrix.h"
|
||||
#include "BLI_math_rotation.h"
|
||||
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.hh"
|
||||
|
||||
#include "node_shader_util.hh"
|
||||
#include "../../intern/node_util.hh"
|
||||
|
||||
namespace blender::nodes::node_shader_light_info_cc {
|
||||
|
||||
static void sh_node_light_info_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_output<decl::Color>("Light Color");
|
||||
b.add_output<decl::Float>("Light Power");
|
||||
b.add_output<decl::Vector>("Light Position");
|
||||
b.add_output<decl::Vector>("Light Rotation");
|
||||
b.add_output<decl::Float>("Light Distance");
|
||||
}
|
||||
|
||||
static void node_shader_init_light_info(bNodeTree * /*ntree*/, bNode *node)
|
||||
{
|
||||
NodeShaderLightInfo *data = MEM_cnew<NodeShaderLightInfo>(__func__);
|
||||
|
||||
/* Node starts with no light object selected */
|
||||
data->light_object = nullptr;
|
||||
|
||||
node->storage = data;
|
||||
}
|
||||
|
||||
static void node_shader_draw_light_info(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
|
||||
{
|
||||
/* Show light object selector */
|
||||
uiItemR(layout, ptr, "light_object", UI_ITEM_NONE, "Light", ICON_LIGHT);
|
||||
}
|
||||
|
||||
static int node_shader_gpu_light_info(GPUMaterial *mat,
|
||||
bNode *node,
|
||||
bNodeExecData * /*execdata*/,
|
||||
GPUNodeStack *in,
|
||||
GPUNodeStack *out)
|
||||
{
|
||||
NodeShaderLightInfo *data = (NodeShaderLightInfo *)node->storage;
|
||||
|
||||
if (data->light_object != nullptr && data->light_object->type == OB_LAMP) {
|
||||
Object *light_ob = data->light_object;
|
||||
Light *light = (Light *)light_ob->data;
|
||||
|
||||
/* Get light color */
|
||||
float light_color[4] = {light->r, light->g, light->b, 1.0f};
|
||||
|
||||
/* Get light power/energy */
|
||||
float light_power = light->energy;
|
||||
|
||||
/* Get light position (world space) - use location directly */
|
||||
float light_position[3];
|
||||
copy_v3_v3(light_position, light_ob->loc);
|
||||
|
||||
/* For rotation, use object's rotation directly */
|
||||
float light_rotation[3];
|
||||
copy_v3_v3(light_rotation, light_ob->rot);
|
||||
|
||||
/* For now, return simplified version without distance calculation */
|
||||
return GPU_stack_link(mat, node, "node_light_info_simple", in, out,
|
||||
GPU_constant(light_color), /* Light Color */
|
||||
GPU_constant(&light_power), /* Light Power */
|
||||
GPU_constant(light_position), /* Light Position */
|
||||
GPU_constant(light_rotation)); /* Light Rotation */
|
||||
}
|
||||
else {
|
||||
/* No light selected - output defaults */
|
||||
float default_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
float default_power = 1.0f;
|
||||
float default_position[3] = {0.0f, 0.0f, 0.0f};
|
||||
float default_rotation[3] = {0.0f, 0.0f, 0.0f};
|
||||
|
||||
return GPU_stack_link(mat, node, "node_light_info_default", in, out,
|
||||
GPU_constant(default_color),
|
||||
GPU_constant(&default_power),
|
||||
GPU_constant(default_position),
|
||||
GPU_constant(default_rotation));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::node_shader_light_info_cc
|
||||
|
||||
/* node type definition */
|
||||
void register_node_type_sh_light_info(void)
|
||||
{
|
||||
namespace file_ns = blender::nodes::node_shader_light_info_cc;
|
||||
|
||||
static blender::bke::bNodeType ntype;
|
||||
|
||||
sh_node_type_base(&ntype, SH_NODE_LIGHT_INFO, "Light Info", NODE_CLASS_INPUT);
|
||||
ntype.declare = file_ns::sh_node_light_info_declare;
|
||||
node_type_storage(&ntype, "NodeShaderLightInfo", node_free_standard_storage, node_copy_standard_storage);
|
||||
ntype.gpu_fn = file_ns::node_shader_gpu_light_info;
|
||||
ntype.initfunc = file_ns::node_shader_init_light_info;
|
||||
ntype.draw_buttons = file_ns::node_shader_draw_light_info;
|
||||
|
||||
node_register_type(&ntype);
|
||||
}
|
||||
Reference in New Issue
Block a user