diff options
author | Matteo Falduto <matteolegna> | 2021-04-01 06:35:56 +0300 |
---|---|---|
committer | Brecht Van Lommel <brecht@blender.org> | 2021-04-01 13:31:01 +0300 |
commit | a4260ac21977acd5b9cd792f2a68c3aa78dd91cd (patch) | |
tree | 61bdd5358e5279ddb9c13c53bb3079d1d8f79b65 /intern/cycles/render | |
parent | c859e1afa0dcca1a495c6b25d00bab65bf94be0b (diff) |
Cycles: add a spread setting for area lights
This simulates the effect of a honeycomb or grid placed in front of a softbox.
In practice, it works by attenuating rays coming off-angle as a function of the
provided spread angle parameter.
Setting the parameter to 180 degrees poses no restrictions to the rays, making
the light behave the same way as before this patch.
The total light power is normalized based on the spread angle, so that the
light strength remains the same.
Differential Revision: https://developer.blender.org/D10594
Diffstat (limited to 'intern/cycles/render')
-rw-r--r-- | intern/cycles/render/light.cpp | 12 | ||||
-rw-r--r-- | intern/cycles/render/light.h | 1 |
2 files changed, 13 insertions, 0 deletions
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 72450e2c546..858b177b69c 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -129,6 +129,7 @@ NODE_DEFINE(Light) SOCKET_VECTOR(axisv, "Axis V", zero_float3()); SOCKET_FLOAT(sizev, "Size V", 1.0f); SOCKET_BOOLEAN(round, "Round", false); + SOCKET_FLOAT(spread, "Spread", M_PI_F); SOCKET_INT(map_resolution, "Map Resolution", 0); @@ -858,6 +859,15 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc float invarea = (area != 0.0f) ? 1.0f / area : 1.0f; float3 dir = light->dir; + /* Convert from spread angle 0..180 to 90..0, clamping to a minimum + * angle to avoid excessive noise. */ + const float min_spread_angle = 1.0f * M_PI_F / 180.0f; + const float spread_angle = 0.5f * (M_PI_F - max(light->spread, min_spread_angle)); + /* Normalization computed using: + * integrate cos(x) (1 - tan(x) * tan(a)) * sin(x) from x = a to pi/2. */ + const float tan_spread = tanf(spread_angle); + const float normalize_spread = 2.0f / (2.0f + (2.0f * spread_angle - M_PI_F) * tan_spread); + dir = safe_normalize(dir); if (light->use_mis && area != 0.0f) @@ -877,6 +887,8 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc klights[light_index].area.dir[0] = dir.x; klights[light_index].area.dir[1] = dir.y; klights[light_index].area.dir[2] = dir.z; + klights[light_index].area.tan_spread = tan_spread; + klights[light_index].area.normalize_spread = normalize_spread; } else if (light->light_type == LIGHT_SPOT) { shader_id &= ~SHADER_AREA_LIGHT; diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h index 39014b5d667..fbd709125ff 100644 --- a/intern/cycles/render/light.h +++ b/intern/cycles/render/light.h @@ -58,6 +58,7 @@ class Light : public Node { NODE_SOCKET_API(float3, axisv) NODE_SOCKET_API(float, sizev) NODE_SOCKET_API(bool, round) + NODE_SOCKET_API(float, spread) NODE_SOCKET_API(Transform, tfm) |