diff options
Diffstat (limited to 'intern/cycles/render/light.cpp')
-rw-r--r-- | intern/cycles/render/light.cpp | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 72450e2c546..5290d68e75a 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); @@ -158,6 +159,7 @@ NODE_DEFINE(Light) Light::Light() : Node(get_node_type()) { + dereference_all_used_nodes(); } void Light::tag_update(Scene *scene) @@ -858,6 +860,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 = 0 to pi/2 - a. */ + 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 +888,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; |