blender/intern/cycles/kernel/light/sun.h
Weizhen Huang 615480dbcb Cleanup: Cycles: Make the notation of Sun Light and Distant Light consistent
Now in Cycles, the term "Sun Light" is used to denote the Sun Light in
Blender UI.

The term "Distant Light" refers to both sun light and background light,
or is occasionally used in places where there is only sun light, but we
would like to add support to background light in the future.

Pull Request: https://projects.blender.org/blender/blender/pulls/155133
2026-03-13 11:00:30 +01:00

122 lines
3.7 KiB
C++

/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#pragma once
#include "kernel/geom/object.h"
#include "kernel/light/common.h"
#include "util/math_fast.h"
CCL_NAMESPACE_BEGIN
ccl_device_inline float2 sun_light_uv(KernelGlobals kg,
const ccl_global KernelLight *klight,
const float3 D)
{
/* Map direction (x, y, z) to disk [-0.5, 0.5]^2:
* r^2 = (1 - z) / (1 - cos(klight->sun.angle))
* u_ = 0.5 * x * r / sin_angle(D, -klight->co)
* v_ = 0.5 * y * r / sin_angle(D, -klight->co) */
const float fac = klight->sun.half_inv_sin_half_angle / len(D - klight->co);
/* Get u axis and v axis. */
const Transform itfm = lamp_get_inverse_transform(kg, klight);
const float u_ = dot(D, make_float3(itfm.x)) * fac;
const float v_ = dot(D, make_float3(itfm.y)) * fac;
/* NOTE: Return barycentric coordinates in the same notation as Embree and OptiX. */
return make_float2(v_ + 0.5f, -u_ - v_);
}
ccl_device_inline bool sun_light_sample(const ccl_global KernelLight *klight,
const float2 rand,
ccl_private LightSample *ls)
{
float unused;
ls->Ng = sample_uniform_cone(
klight->co, klight->sun.one_minus_cosangle, rand, &unused, &ls->pdf);
ls->P = ls->Ng;
ls->D = -ls->Ng;
ls->t = FLT_MAX;
ls->eval_fac = klight->sun.eval_fac;
return true;
}
/* Special intersection check.
* Returns true if the sun_light_eval_from_intersection() for this light would return true.
*
* The intersection parameters t, u, v are optimized for the shadow ray towards a dedicated light:
* u = v = 0, t = FLT_MAX.
*/
ccl_device bool sun_light_intersect(const ccl_global KernelLight *klight,
const ccl_private Ray *ccl_restrict ray,
ccl_private float *t)
{
kernel_assert(klight->type == LIGHT_SUN);
if (klight->sun.angle == 0.0f) {
return false;
}
if (vector_angle(-klight->co, ray->D) > klight->sun.angle) {
return false;
}
*t = FLT_MAX;
return true;
}
ccl_device LightEval sun_light_eval_from_intersection(const ccl_global KernelLight *klight,
const float3 ray_D)
{
if (klight->sun.angle == 0.0f) {
return LightEval{};
}
if (vector_angle(-klight->co, ray_D) > klight->sun.angle) {
return LightEval{};
}
return LightEval{klight->sun.eval_fac, klight->sun.pdf};
}
template<bool in_volume_segment>
ccl_device_forceinline bool sun_light_tree_parameters(const float3 centroid,
const float theta_e,
const float t,
ccl_private float &cos_theta_u,
ccl_private float2 &distance,
ccl_private float3 &point_to_centroid,
ccl_private float &theta_d)
{
if (in_volume_segment) {
if (t == FLT_MAX) {
/* In world volumes, distant lights can contribute to the lighting of the volume with
* specific configurations of procedurally generated volumes. Use a ray length of 1.0 in this
* case to give the distant light some weight, but one that isn't too high for a typical
* world volume use case. */
theta_d = 1.0f;
}
else {
theta_d = t;
}
}
/* Treating it as a disk light 1 unit away */
cos_theta_u = fast_cosf(theta_e);
distance = make_float2(1.0f / cos_theta_u, 1.0f);
point_to_centroid = -centroid;
return true;
}
CCL_NAMESPACE_END