The spotlight is now treated as a sphere instead of a view-aligned disk. The implementation remains almost identical to that of a point light, except for the spotlight attenuation and spot blend. There is no attenuation inside the sphere. Ref #108505 Other changes include: ## Sampling Instead of sampling the disk area, the new implementation samples either the cone of the visible portion on the sphere or the spread cone, based on which cone has a smaller solid angle. This reduces noise when the spotlight has a large radius and a small spread angle. | Before | After | | -- | -- | || ## Texture Spot light can now project texture using UV coordinates. <video src="/attachments/6db989d2-7a3c-4b41-9340-f5690d48c4fb" title="spot_light_texture.mp4" controls></video> ## Normalization Previously, the normalization factor for the spotlight was \(\pi r^2\), the area of a disk. This factor has been adjusted to \(4\pi r^2\) to account for the surface area of a sphere. This change also affects point light since they share the same kernel type. ## Versioning Some pipeline uses the `Normal` socket of the Texture Coordinate node for projection, because `ls->Ng` was set to the incoming direction at the current shading point. Now that `ls->Ng` corresponds to the normal direction of a point on the sphere (except when the radius is zero), we replace these nodes with a combination of the Geometry shader node and the Vector Transform node, which gives the same result as before.  Example file see https://archive.blender.org/developer/T93676 Pull Request: https://projects.blender.org/blender/blender/pulls/109329
171 lines
4.4 KiB
C++
171 lines
4.4 KiB
C++
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 */
|
|
|
|
#ifndef __LIGHT_H__
|
|
#define __LIGHT_H__
|
|
|
|
#include "kernel/types.h"
|
|
|
|
#include "graph/node.h"
|
|
|
|
/* included as Light::set_shader defined through NODE_SOCKET_API does not select
|
|
* the right Node::set overload as it does not know that Shader is a Node */
|
|
#include "scene/shader.h"
|
|
|
|
#include "util/ies.h"
|
|
#include "util/thread.h"
|
|
#include "util/types.h"
|
|
#include "util/vector.h"
|
|
|
|
CCL_NAMESPACE_BEGIN
|
|
|
|
class Device;
|
|
class DeviceScene;
|
|
class Progress;
|
|
class Scene;
|
|
class Shader;
|
|
|
|
class Light : public Node {
|
|
public:
|
|
NODE_DECLARE;
|
|
|
|
Light();
|
|
|
|
NODE_SOCKET_API(LightType, light_type)
|
|
NODE_SOCKET_API(float3, strength)
|
|
NODE_SOCKET_API(float3, co)
|
|
|
|
NODE_SOCKET_API(float3, dir)
|
|
NODE_SOCKET_API(float, size)
|
|
NODE_SOCKET_API(float, angle)
|
|
|
|
NODE_SOCKET_API(float3, axisu)
|
|
NODE_SOCKET_API(float, sizeu)
|
|
NODE_SOCKET_API(float3, axisv)
|
|
NODE_SOCKET_API(float, sizev)
|
|
NODE_SOCKET_API(bool, ellipse)
|
|
NODE_SOCKET_API(float, spread)
|
|
|
|
NODE_SOCKET_API(Transform, tfm)
|
|
|
|
NODE_SOCKET_API(int, map_resolution)
|
|
NODE_SOCKET_API(float, average_radiance)
|
|
|
|
NODE_SOCKET_API(float, spot_angle)
|
|
NODE_SOCKET_API(float, spot_smooth)
|
|
|
|
NODE_SOCKET_API(bool, cast_shadow)
|
|
NODE_SOCKET_API(bool, use_mis)
|
|
NODE_SOCKET_API(bool, use_camera)
|
|
NODE_SOCKET_API(bool, use_diffuse)
|
|
NODE_SOCKET_API(bool, use_glossy)
|
|
NODE_SOCKET_API(bool, use_transmission)
|
|
NODE_SOCKET_API(bool, use_scatter)
|
|
NODE_SOCKET_API(bool, use_caustics)
|
|
|
|
NODE_SOCKET_API(bool, is_shadow_catcher)
|
|
NODE_SOCKET_API(bool, is_portal)
|
|
NODE_SOCKET_API(bool, is_enabled)
|
|
|
|
NODE_SOCKET_API(Shader *, shader)
|
|
NODE_SOCKET_API(int, max_bounces)
|
|
NODE_SOCKET_API(uint, random_id)
|
|
|
|
NODE_SOCKET_API(ustring, lightgroup)
|
|
NODE_SOCKET_API(uint64_t, light_set_membership);
|
|
NODE_SOCKET_API(uint64_t, shadow_set_membership);
|
|
|
|
/* Normalize power by the surface area of the light. */
|
|
NODE_SOCKET_API(bool, normalize)
|
|
|
|
void tag_update(Scene *scene);
|
|
|
|
/* Check whether the light has contribution the scene. */
|
|
bool has_contribution(Scene *scene);
|
|
|
|
/* Check whether this light participates in light or shadow linking. */
|
|
bool has_light_linking() const;
|
|
bool has_shadow_linking() const;
|
|
|
|
friend class LightManager;
|
|
friend class LightTree;
|
|
};
|
|
|
|
class LightManager {
|
|
public:
|
|
enum : uint32_t {
|
|
MESH_NEED_REBUILD = (1 << 0),
|
|
EMISSIVE_MESH_MODIFIED = (1 << 1),
|
|
LIGHT_MODIFIED = (1 << 2),
|
|
LIGHT_ADDED = (1 << 3),
|
|
LIGHT_REMOVED = (1 << 4),
|
|
OBJECT_MANAGER = (1 << 5),
|
|
SHADER_COMPILED = (1 << 6),
|
|
SHADER_MODIFIED = (1 << 7),
|
|
|
|
/* tag everything in the manager for an update */
|
|
UPDATE_ALL = ~0u,
|
|
|
|
UPDATE_NONE = 0u,
|
|
};
|
|
|
|
/* Need to update background (including multiple importance map) */
|
|
bool need_update_background;
|
|
|
|
LightManager();
|
|
~LightManager();
|
|
|
|
/* IES texture management */
|
|
int add_ies(const string &ies);
|
|
int add_ies_from_file(const string &filename);
|
|
void remove_ies(int slot);
|
|
|
|
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
|
|
void device_free(Device *device, DeviceScene *dscene, const bool free_background = true);
|
|
|
|
void tag_update(Scene *scene, uint32_t flag);
|
|
|
|
bool need_update() const;
|
|
|
|
/* Check whether there is a background light. */
|
|
bool has_background_light(Scene *scene);
|
|
|
|
protected:
|
|
/* Optimization: disable light which is either unsupported or
|
|
* which doesn't contribute to the scene or which is only used for MIS
|
|
* and scene doesn't need MIS.
|
|
*/
|
|
void test_enabled_lights(Scene *scene);
|
|
|
|
void device_update_lights(Device *device, DeviceScene *dscene, Scene *scene);
|
|
void device_update_distribution(Device *device,
|
|
DeviceScene *dscene,
|
|
Scene *scene,
|
|
Progress &progress);
|
|
void device_update_tree(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
|
|
void device_update_background(Device *device,
|
|
DeviceScene *dscene,
|
|
Scene *scene,
|
|
Progress &progress);
|
|
void device_update_ies(DeviceScene *dscene);
|
|
|
|
struct IESSlot {
|
|
IESFile ies;
|
|
uint hash;
|
|
int users;
|
|
};
|
|
|
|
vector<IESSlot *> ies_slots;
|
|
thread_mutex ies_mutex;
|
|
|
|
bool last_background_enabled;
|
|
int last_background_resolution;
|
|
|
|
uint32_t update_flags;
|
|
};
|
|
|
|
CCL_NAMESPACE_END
|
|
|
|
#endif /* __LIGHT_H__ */
|