From 482211b7e0bf85a34e57f7ef9df8eebf1f2d1b9c Mon Sep 17 00:00:00 2001 From: Weizhen Huang Date: Fri, 7 Jul 2023 17:03:02 +0200 Subject: [PATCH] Fix wrong conversion from power to radiance of area lights The correct conversion factor should be 1 / (pi * area), see #108505 Co-authored-by: Brecht Van Lommel Pull Request: https://projects.blender.org/blender/blender/pulls/109153 --- intern/cycles/kernel/light/area.h | 3 ++- intern/cycles/scene/light_tree.cpp | 3 ++- source/blender/blenkernel/BKE_blender_version.h | 2 +- source/blender/blenkernel/intern/light.c | 6 ++++++ .../blender/blenloader/intern/versioning_280.cc | 8 ++++---- .../blender/blenloader/intern/versioning_400.cc | 16 ++++++++++++++-- source/blender/draw/engines/eevee/eevee_lights.c | 9 +++------ .../draw/engines/eevee_next/eevee_light.cc | 9 +++------ source/blender/makesdna/DNA_light_defaults.h | 1 + source/blender/makesdna/DNA_light_types.h | 2 ++ source/blender/makesdna/intern/dna_rename_defs.h | 2 ++ 11 files changed, 40 insertions(+), 21 deletions(-) diff --git a/intern/cycles/kernel/light/area.h b/intern/cycles/kernel/light/area.h index 2c331e4c2cb..a52e1079bba 100644 --- a/intern/cycles/kernel/light/area.h +++ b/intern/cycles/kernel/light/area.h @@ -290,7 +290,8 @@ ccl_device_inline bool area_light_eval(const ccl_global KernelLight *klight, ls->D = normalize_len(*light_P - ray_P, &ls->t); } - ls->eval_fac = 0.25f * invarea; + /* Convert radiant flux to radiance. */ + ls->eval_fac = M_1_PI_F * invarea; if (klight->area.normalize_spread > 0) { /* Area Light spread angle attenuation */ diff --git a/intern/cycles/scene/light_tree.cpp b/intern/cycles/scene/light_tree.cpp index 7c4c2738b9d..23b323f69b0 100644 --- a/intern/cycles/scene/light_tree.cpp +++ b/intern/cycles/scene/light_tree.cpp @@ -167,7 +167,8 @@ LightTreeEmitter::LightTreeEmitter(Scene *scene, measure.bbox.grow(centroid - half_extentu + half_extentv); measure.bbox.grow(centroid - half_extentu - half_extentv); - strength *= 0.25f; /* eval_fac scaling in `area.h` */ + /* Convert irradiance to radiance. */ + strength *= M_1_PI_F; } else if (type == LIGHT_POINT) { measure.bcone.theta_o = M_PI_F; diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 96edba09c31..f590cc3158a 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -27,7 +27,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 8 +#define BLENDER_FILE_SUBVERSION 9 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenkernel/intern/light.c b/source/blender/blenkernel/intern/light.c index f95c500431a..68f46273460 100644 --- a/source/blender/blenkernel/intern/light.c +++ b/source/blender/blenkernel/intern/light.c @@ -117,6 +117,12 @@ static void light_blend_write(BlendWriter *writer, ID *id, const void *id_addres { Light *la = (Light *)id; + /* Forward compatibility for energy. */ + la->energy_deprecated = la->energy; + if (la->type == LA_AREA) { + la->energy_deprecated /= M_PI_4; + } + /* write LibData */ BLO_write_id_struct(writer, Light, id_address, &la->id); BKE_id_blend_write(writer, &la->id); diff --git a/source/blender/blenloader/intern/versioning_280.cc b/source/blender/blenloader/intern/versioning_280.cc index cb6c961617b..885f4d78792 100644 --- a/source/blender/blenloader/intern/versioning_280.cc +++ b/source/blender/blenloader/intern/versioning_280.cc @@ -1434,7 +1434,7 @@ static void light_emission_node_to_energy(Light *light, float *energy, float col static void light_emission_unify(Light *light, const char *engine) { if (light->type != LA_SUN) { - light->energy *= 100.0f; + light->energy_deprecated *= 100.0f; } /* Attempt to extract constant energy and color from nodes. */ @@ -1445,16 +1445,16 @@ static void light_emission_unify(Light *light, const char *engine) if (STREQ(engine, "CYCLES")) { if (use_nodes) { /* Energy extracted from nodes */ - light->energy = energy; + light->energy_deprecated = energy; copy_v3_v3(&light->r, color); } else { /* Default cycles multipliers if there are no nodes */ if (light->type == LA_SUN) { - light->energy = 1.0f; + light->energy_deprecated = 1.0f; } else { - light->energy = 100.0f; + light->energy_deprecated = 100.0f; } } } diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index 623cc87e347..0eb01476592 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -10,6 +10,7 @@ #include "CLG_log.h" +#include "DNA_light_types.h" #include "DNA_lightprobe_types.h" #include "DNA_modifier_types.h" #include "DNA_movieclip_types.h" @@ -38,8 +39,18 @@ // static CLG_LogRef LOG = {"blo.readfile.doversion"}; -void do_versions_after_linking_400(FileData * /*fd*/, Main * /*bmain*/) +void do_versions_after_linking_400(FileData * /*fd*/, Main *bmain) { + if (!MAIN_VERSION_ATLEAST(bmain, 400, 9)) { + /* Fix area light scaling. */ + LISTBASE_FOREACH (Light *, light, &bmain->lights) { + light->energy = light->energy_deprecated; + if (light->type == LA_AREA) { + light->energy *= M_PI_4; + } + } + } + /** * Versioning code until next subversion bump goes here. * @@ -133,7 +144,8 @@ static void version_mesh_crease_generic(Main &bmain) LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (STR_ELEM(node->idname, "GeometryNodeStoreNamedAttribute", - "GeometryNodeInputNamedAttribute")) { + "GeometryNodeInputNamedAttribute")) + { bNodeSocket *socket = nodeFindSocket(node, SOCK_IN, "Name"); if (STREQ(socket->default_value_typed()->value, "crease")) { STRNCPY(socket->default_value_typed()->value, "crease_edge"); diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c index 15f194927a5..00a812f5ad5 100644 --- a/source/blender/draw/engines/eevee/eevee_lights.c +++ b/source/blender/draw/engines/eevee/eevee_lights.c @@ -78,9 +78,8 @@ static float light_shape_radiance_get(const Light *la, const EEVEE_Light *evli) if (ELEM(la->area_shape, LA_AREA_DISK, LA_AREA_ELLIPSE)) { area *= M_PI / 4.0f; } - /* NOTE: The 4 factor is from Cycles definition of power. */ - /* NOTE: Missing a factor of PI here to match Cycles. */ - return 1.0f / (4.0f * area); + /* Convert radiant flux to radiance. */ + return (float)M_1_PI / area; } case LA_SPOT: case LA_LOCAL: { @@ -120,9 +119,7 @@ static float light_volume_radiance_factor_get(const Light *la, float tmp = M_PI_2 / (M_PI_2 + sqrtf(area)); /* Lerp between 1.0 and the limit (1 / pi). */ float mrp_scaling = tmp + (1.0f - tmp) * M_1_PI; - /* NOTE: The 4 factor is from Cycles definition of power. */ - /* NOTE: Missing a factor of PI here to match Cycles. */ - power *= mrp_scaling / 4.0f; + power *= (float)M_1_PI * mrp_scaling; break; } case LA_SPOT: diff --git a/source/blender/draw/engines/eevee_next/eevee_light.cc b/source/blender/draw/engines/eevee_next/eevee_light.cc index b85e35a2171..5f1f470bf3c 100644 --- a/source/blender/draw/engines/eevee_next/eevee_light.cc +++ b/source/blender/draw/engines/eevee_next/eevee_light.cc @@ -178,9 +178,8 @@ float Light::shape_radiance_get(const ::Light *la) if (ELEM(la->area_shape, LA_AREA_DISK, LA_AREA_ELLIPSE)) { area *= M_PI / 4.0f; } - /* NOTE: The 4 factor is from Cycles definition of power. */ - /* NOTE: Missing a factor of PI here to match Cycles. */ - return 1.0f / (4.0f * area); + /* Convert radiant flux to radiance. */ + return float(M_1_PI) / area; } case LA_SPOT: case LA_LOCAL: { @@ -214,9 +213,7 @@ float Light::point_radiance_get(const ::Light *la) float tmp = M_PI_2 / (M_PI_2 + sqrtf(area)); /* Lerp between 1.0 and the limit (1 / pi). */ float mrp_scaling = tmp + (1.0f - tmp) * M_1_PI; - /* NOTE: The 4 factor is from Cycles definition of power. */ - /* NOTE: Missing a factor of PI here to match Cycles. */ - return mrp_scaling / 4.0f; + return float(M_1_PI) * mrp_scaling; } case LA_SPOT: case LA_LOCAL: { diff --git a/source/blender/makesdna/DNA_light_defaults.h b/source/blender/makesdna/DNA_light_defaults.h index c1d9e9acd13..f1d5eddcca1 100644 --- a/source/blender/makesdna/DNA_light_defaults.h +++ b/source/blender/makesdna/DNA_light_defaults.h @@ -21,6 +21,7 @@ .g = 1.0f, \ .b = 1.0f, \ .energy = 10.0f, \ + .energy_deprecated = 10.0f, \ .spotsize = DEG2RADF(45.0f), \ .spotblend = 0.15f, \ .mode = LA_SHADOW, \ diff --git a/source/blender/makesdna/DNA_light_types.h b/source/blender/makesdna/DNA_light_types.h index 41b0b915eaf..dd1e88c8b1b 100644 --- a/source/blender/makesdna/DNA_light_types.h +++ b/source/blender/makesdna/DNA_light_types.h @@ -89,6 +89,8 @@ typedef struct Light { /* Deprecated. */ struct Ipo *ipo DNA_DEPRECATED; /* Old animation system. */ + float energy_deprecated DNA_DEPRECATED; + float _pad2; } Light; /* **************** LIGHT ********************* */ diff --git a/source/blender/makesdna/intern/dna_rename_defs.h b/source/blender/makesdna/intern/dna_rename_defs.h index 461237619e2..b53741b08ee 100644 --- a/source/blender/makesdna/intern/dna_rename_defs.h +++ b/source/blender/makesdna/intern/dna_rename_defs.h @@ -85,6 +85,8 @@ DNA_STRUCT_RENAME_ELEM(GreasePencil, material_array_size, material_array_num) DNA_STRUCT_RENAME_ELEM(GreasePencilLayerFramesMapStorage, size, num) DNA_STRUCT_RENAME_ELEM(HookModifierData, totindex, indexar_num) DNA_STRUCT_RENAME_ELEM(Image, name, filepath) +DNA_STRUCT_RENAME_ELEM(Light, energy_new, energy) +DNA_STRUCT_RENAME_ELEM(Light, energy, energy_deprecated) DNA_STRUCT_RENAME_ELEM(LaplacianDeformModifierData, total_verts, verts_num) DNA_STRUCT_RENAME_ELEM(Library, name, filepath) DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, line_types, edge_types)