Files
test2/source/blender/makesrna/intern/rna_light.cc
Clément Foucault 3a4fc2c94e EEVEE-Next: Shadow Map Tracing Initial Implementation
Shadow Map Ray Tracing is a technique that ray cast against the shadow
depth buffer. The technique is described in "Soft Shadows by
Ray Tracing Multilayer Transparent Shadow Maps".
Note that we only implement the single layer approach since storing
multiple depth is prohibitively expensive.

Pull Request: https://projects.blender.org/blender/blender/pulls/111809
2023-09-26 23:42:40 +02:00

477 lines
19 KiB
C++

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup RNA
*/
#include <cstdlib>
#include "BLI_math_base.h"
#include "BLI_math_rotation.h"
#include "BLI_sys_types.h"
#include "BLT_translation.h"
#include "RNA_define.hh"
#include "RNA_enum_types.hh"
#include "rna_internal.h"
#include "DNA_light_types.h"
#include "DNA_material_types.h"
#include "DNA_texture_types.h"
#ifdef RNA_RUNTIME
# include "MEM_guardedalloc.h"
# include "BKE_context.h"
# include "BKE_main.h"
# include "BKE_texture.h"
# include "DEG_depsgraph.hh"
# include "ED_node.hh"
# include "WM_api.hh"
# include "WM_types.hh"
static StructRNA *rna_Light_refine(PointerRNA *ptr)
{
Light *la = (Light *)ptr->data;
switch (la->type) {
case LA_LOCAL:
return &RNA_PointLight;
case LA_SUN:
return &RNA_SunLight;
case LA_SPOT:
return &RNA_SpotLight;
case LA_AREA:
return &RNA_AreaLight;
default:
return &RNA_Light;
}
}
static void rna_Light_update(Main * /*bmain*/, Scene * /*scene*/, PointerRNA *ptr)
{
Light *la = (Light *)ptr->owner_id;
DEG_id_tag_update(&la->id, 0);
WM_main_add_notifier(NC_LAMP | ND_LIGHTING, la);
}
static void rna_Light_draw_update(Main * /*bmain*/, Scene * /*scene*/, PointerRNA *ptr)
{
Light *la = (Light *)ptr->owner_id;
DEG_id_tag_update(&la->id, 0);
WM_main_add_notifier(NC_LAMP | ND_LIGHTING_DRAW, la);
}
static void rna_Light_use_nodes_update(bContext *C, PointerRNA *ptr)
{
Light *la = (Light *)ptr->data;
if (la->use_nodes && la->nodetree == nullptr) {
ED_node_shader_default(C, &la->id);
}
rna_Light_update(CTX_data_main(C), CTX_data_scene(C), ptr);
}
#else
/* NOTE(@dingto): Don't define icons here,
* so they don't show up in the Light UI (properties editor). */
const EnumPropertyItem rna_enum_light_type_items[] = {
{LA_LOCAL, "POINT", 0, "Point", "Omnidirectional point light source"},
{LA_SUN, "SUN", 0, "Sun", "Constant direction parallel ray light source"},
{LA_SPOT, "SPOT", 0, "Spot", "Directional cone light source"},
{LA_AREA, "AREA", 0, "Area", "Directional area light source"},
{0, nullptr, 0, nullptr, nullptr},
};
static void rna_def_light(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
static const float default_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
srna = RNA_def_struct(brna, "Light", "ID");
RNA_def_struct_sdna(srna, "Light");
RNA_def_struct_refine_func(srna, "rna_Light_refine");
RNA_def_struct_ui_text(srna, "Light", "Light data-block for lighting a scene");
RNA_def_struct_translation_context(srna, BLT_I18NCONTEXT_ID_LIGHT);
RNA_def_struct_ui_icon(srna, ICON_LIGHT_DATA);
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_enum_light_type_items);
RNA_def_property_ui_text(prop, "Type", "Type of light");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_LIGHT);
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, nullptr, "r");
RNA_def_property_array(prop, 3);
RNA_def_property_float_array_default(prop, default_color);
RNA_def_property_ui_text(prop, "Color", "Light color");
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
prop = RNA_def_property(srna, "specular_factor", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, nullptr, "spec_fac");
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.01, 2);
RNA_def_property_ui_text(prop, "Specular Factor", "Specular reflection multiplier");
RNA_def_property_update(prop, 0, "rna_Light_update");
prop = RNA_def_property(srna, "diffuse_factor", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, nullptr, "diff_fac");
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.01, 2);
RNA_def_property_ui_text(prop, "Diffuse Factor", "Diffuse reflection multiplier");
RNA_def_property_update(prop, 0, "rna_Light_update");
prop = RNA_def_property(srna, "volume_factor", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, nullptr, "volume_fac");
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.01, 2);
RNA_def_property_ui_text(prop, "Volume Factor", "Volume light multiplier");
RNA_def_property_update(prop, 0, "rna_Light_update");
prop = RNA_def_property(srna, "use_custom_distance", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "mode", LA_CUSTOM_ATTENUATION);
RNA_def_property_ui_text(prop,
"Custom Attenuation",
"Use custom attenuation distance instead of global light threshold");
RNA_def_property_update(prop, 0, "rna_Light_update");
prop = RNA_def_property(srna, "cutoff_distance", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, nullptr, "att_dist");
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 0.01f, 100.0f, 1.0, 2);
RNA_def_property_ui_text(
prop, "Cutoff Distance", "Distance at which the light influence will be set to 0");
RNA_def_property_update(prop, 0, "rna_Light_update");
/* nodes */
prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, nullptr, "nodetree");
RNA_def_property_clear_flag(prop, PROP_PTR_NO_OWNERSHIP);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Node Tree", "Node tree for node based lights");
prop = RNA_def_property(srna, "use_nodes", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "use_nodes", 1);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Use Nodes", "Use shader nodes to render the light");
RNA_def_property_update(prop, 0, "rna_Light_use_nodes_update");
/* common */
rna_def_animdata_common(srna);
}
static void rna_def_light_energy(StructRNA *srna, const short light_type)
{
PropertyRNA *prop;
switch (light_type) {
case LA_SUN: {
/* Distant light strength has no unit defined,
* it's proportional to 'watt/m^2' and is not sensitive to scene unit scale. */
prop = RNA_def_property(srna, "energy", PROP_FLOAT, PROP_NONE);
RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3);
RNA_def_property_ui_text(
prop, "Strength", "Sunlight strength in watts per meter squared (W/m²)");
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
break;
}
case LA_SPOT: {
/* Lights with a location have power in Watts,
* which is sensitive to scene unit scale. */
prop = RNA_def_property(srna, "energy", PROP_FLOAT, PROP_POWER);
RNA_def_property_ui_range(prop, 0.0f, 1000000.0f, 10, 5);
RNA_def_property_ui_text(prop,
"Power",
"The energy this light would emit over its entire area "
"if it wasn't limited by the spot angle");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_LIGHT);
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
break;
}
default: {
/* Lights with a location have power in Watts,
* which is sensitive to scene unit scale. */
prop = RNA_def_property(srna, "energy", PROP_FLOAT, PROP_POWER);
RNA_def_property_ui_range(prop, 0.0f, 1000000.0f, 10, 5);
RNA_def_property_ui_text(
prop,
"Power",
"Light energy emitted over the entire area of the light in all directions");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_LIGHT);
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
break;
}
}
}
static void rna_def_light_shadow(StructRNA *srna, bool sun)
{
PropertyRNA *prop;
prop = RNA_def_property(srna, "use_shadow", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "mode", LA_SHADOW);
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
prop = RNA_def_property(srna, "shadow_buffer_clip_start", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, nullptr, "clipsta");
RNA_def_property_range(prop, 1e-6f, FLT_MAX);
RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10, 3);
RNA_def_property_ui_text(prop,
"Shadow Buffer Clip Start",
"Shadow map clip start, below which objects will not generate shadows");
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
prop = RNA_def_property(srna, "shadow_buffer_bias", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, nullptr, "bias");
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 0.001f, 5.0f, 1.0, 3);
RNA_def_property_ui_text(prop, "Shadow Buffer Bias", "Bias for reducing self shadowing");
RNA_def_property_update(prop, 0, "rna_Light_update");
prop = RNA_def_property(srna, "shadow_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, nullptr, "shdwr");
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Shadow Color", "Color of shadows cast by the light");
RNA_def_property_update(prop, 0, "rna_Light_update");
prop = RNA_def_property(srna, "shadow_soft_size", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, nullptr, "radius");
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 0, 100, 0.1, 3);
RNA_def_property_ui_text(
prop, "Shadow Soft Size", "Light size for ray shadow sampling (Raytraced shadows)");
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
/* Eevee */
prop = RNA_def_property(srna, "use_contact_shadow", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "mode", LA_SHAD_CONTACT);
RNA_def_property_ui_text(prop,
"Contact Shadow",
"Use screen space ray-tracing to have correct shadowing "
"near occluder, or for small features that does not appear "
"in shadow maps");
RNA_def_property_update(prop, 0, "rna_Light_update");
prop = RNA_def_property(srna, "contact_shadow_distance", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, nullptr, "contact_dist");
RNA_def_property_range(prop, 0.0f, 9999.0f);
RNA_def_property_ui_text(prop,
"Contact Shadow Distance",
"World space distance in which to search for "
"screen space occluder");
RNA_def_property_update(prop, 0, "rna_Light_update");
prop = RNA_def_property(srna, "contact_shadow_bias", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, nullptr, "contact_bias");
RNA_def_property_range(prop, 0.001f, 9999.0f);
RNA_def_property_ui_range(prop, 0.001f, 5.0f, 1.0, 3);
RNA_def_property_ui_text(prop, "Contact Shadow Bias", "Bias to avoid self shadowing");
RNA_def_property_update(prop, 0, "rna_Light_update");
prop = RNA_def_property(srna, "contact_shadow_thickness", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, nullptr, "contact_thickness");
RNA_def_property_range(prop, 0.0f, 9999.0f);
RNA_def_property_ui_range(prop, 0, 100, 0.1, 3);
RNA_def_property_ui_text(
prop, "Contact Shadow Thickness", "Pixel thickness used to detect occlusion");
RNA_def_property_update(prop, 0, "rna_Light_update");
prop = RNA_def_property(srna, "shadow_softness_factor", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(
prop, "Shadow Softness Factor", "Scale light shape for smaller penumbra");
RNA_def_property_update(prop, 0, "rna_Light_update");
if (sun) {
prop = RNA_def_property(srna, "shadow_cascade_max_distance", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, nullptr, "cascade_max_dist");
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_text(prop,
"Cascade Max Distance",
"End distance of the cascaded shadow map (only in perspective view)");
RNA_def_property_update(prop, 0, "rna_Light_update");
prop = RNA_def_property(srna, "shadow_cascade_count", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, nullptr, "cascade_count");
RNA_def_property_range(prop, 1, 4);
RNA_def_property_ui_text(
prop, "Cascade Count", "Number of texture used by the cascaded shadow map");
RNA_def_property_update(prop, 0, "rna_Light_update");
prop = RNA_def_property(srna, "shadow_cascade_exponent", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, nullptr, "cascade_exponent");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop,
"Exponential Distribution",
"Higher value increase resolution towards the viewpoint");
RNA_def_property_update(prop, 0, "rna_Light_update");
prop = RNA_def_property(srna, "shadow_cascade_fade", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, nullptr, "cascade_fade");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(
prop, "Cascade Fade", "How smooth is the transition between each cascade");
RNA_def_property_update(prop, 0, "rna_Light_update");
prop = RNA_def_property(srna, "shadow_trace_distance", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 0, 100, 0.1, 3);
RNA_def_property_ui_text(prop,
"Shadow Tracing Max Distance",
"Maximum distance a shadow map tracing ray can travel");
RNA_def_property_update(prop, 0, "rna_Light_update");
}
}
static void rna_def_point_light(BlenderRNA *brna)
{
StructRNA *srna;
srna = RNA_def_struct(brna, "PointLight", "Light");
RNA_def_struct_sdna(srna, "Light");
RNA_def_struct_ui_text(srna, "Point Light", "Omnidirectional point Light");
RNA_def_struct_ui_icon(srna, ICON_LIGHT_POINT);
rna_def_light_energy(srna, LA_LOCAL);
rna_def_light_shadow(srna, false);
}
static void rna_def_area_light(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
static const EnumPropertyItem prop_areashape_items[] = {
{LA_AREA_SQUARE, "SQUARE", 0, "Square", ""},
{LA_AREA_RECT, "RECTANGLE", 0, "Rectangle", ""},
{LA_AREA_DISK, "DISK", 0, "Disk", ""},
{LA_AREA_ELLIPSE, "ELLIPSE", 0, "Ellipse", ""},
{0, nullptr, 0, nullptr, nullptr},
};
srna = RNA_def_struct(brna, "AreaLight", "Light");
RNA_def_struct_sdna(srna, "Light");
RNA_def_struct_ui_text(srna, "Area Light", "Directional area Light");
RNA_def_struct_ui_icon(srna, ICON_LIGHT_AREA);
rna_def_light_energy(srna, LA_AREA);
rna_def_light_shadow(srna, false);
prop = RNA_def_property(srna, "shape", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, nullptr, "area_shape");
RNA_def_property_enum_items(prop, prop_areashape_items);
RNA_def_property_ui_text(prop, "Shape", "Shape of the area Light");
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
prop = RNA_def_property(srna, "size", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, nullptr, "area_size");
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 0, 100, 0.1, 3);
RNA_def_property_ui_text(
prop, "Size", "Size of the area of the area light, X direction size for rectangle shapes");
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
prop = RNA_def_property(srna, "size_y", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, nullptr, "area_sizey");
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 0, 100, 0.1, 3);
RNA_def_property_ui_text(
prop,
"Size Y",
"Size of the area of the area light in the Y direction for rectangle shapes");
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
prop = RNA_def_property(srna, "spread", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, nullptr, "area_spread");
RNA_def_property_range(prop, DEG2RADF(0.0f), DEG2RADF(180.0f));
RNA_def_property_ui_text(
prop,
"Spread",
"How widely the emitted light fans out, as in the case of a gridded softbox");
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
}
static void rna_def_spot_light(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "SpotLight", "Light");
RNA_def_struct_sdna(srna, "Light");
RNA_def_struct_ui_text(srna, "Spot Light", "Directional cone Light");
RNA_def_struct_ui_icon(srna, ICON_LIGHT_SPOT);
rna_def_light_energy(srna, LA_SPOT);
rna_def_light_shadow(srna, false);
prop = RNA_def_property(srna, "use_square", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "mode", LA_SQUARE);
RNA_def_property_ui_text(prop, "Square", "Cast a square spot light shape");
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
prop = RNA_def_property(srna, "spot_blend", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, nullptr, "spotblend");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Spot Blend", "The softness of the spotlight edge");
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
prop = RNA_def_property(srna, "spot_size", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, nullptr, "spotsize");
RNA_def_property_range(prop, DEG2RADF(1.0f), DEG2RADF(180.0f));
RNA_def_property_ui_text(prop, "Spot Size", "Angle of the spotlight beam");
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
prop = RNA_def_property(srna, "show_cone", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "mode", LA_SHOW_CONE);
RNA_def_property_ui_text(
prop,
"Show Cone",
"Display transparent cone in 3D view to visualize which objects are contained in it");
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
}
static void rna_def_sun_light(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "SunLight", "Light");
RNA_def_struct_sdna(srna, "Light");
RNA_def_struct_ui_text(srna, "Sun Light", "Constant direction parallel ray Light");
RNA_def_struct_ui_icon(srna, ICON_LIGHT_SUN);
prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, nullptr, "sun_angle");
RNA_def_property_range(prop, DEG2RADF(0.0f), DEG2RADF(180.0f));
RNA_def_property_ui_text(prop, "Angle", "Angular diameter of the Sun as seen from the Earth");
RNA_def_property_update(prop, 0, "rna_Light_update");
rna_def_light_energy(srna, LA_SUN);
rna_def_light_shadow(srna, true);
}
void RNA_def_light(BlenderRNA *brna)
{
rna_def_light(brna);
rna_def_point_light(brna);
rna_def_area_light(brna);
rna_def_spot_light(brna);
rna_def_sun_light(brna);
}
#endif