Files
test2/intern/cycles/kernel/light/point.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

194 lines
6.3 KiB
C
Raw Normal View History

/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#pragma once
#include "kernel/light/common.h"
CCL_NAMESPACE_BEGIN
ccl_device_inline bool point_light_sample(const ccl_global KernelLight *klight,
const float2 rand,
const float3 P,
Cycles/EEVEE: change point light to double-sided sphere light for energy preservation and better compatibility with other renderes. Ref: #108505 Point light now behaves the same as a spherical mesh light with the same overall energy (scaling from emission strength to power is \(4\pi^2R^2\)). # Cycles ## Comparison | Mesh Light | This patch | Previous behavior | | -------- | -------- | -------- | | ![mesh_1024](attachments/2900954c-57f8-49c2-b6f3-8fb559b820ac) | ![sphere_1024](attachments/148241ca-9350-48b6-be04-3933e015424c) | ![point_1024](attachments/d9b19d54-2b00-4986-ba8c-c4b28f687f09) | The behavior stays the same when `radius = 0`. | This patch | Previous behavior | | -------- | -------- | | ![sphere_64](attachments/aa05d59a-146a-4f69-b257-5d09a7f41d4e) | ![point_64](attachments/69a743be-bc15-454b-92d8-af02f4e8ab07) | No obvious performance change observed. ## Sampling When shading point lies outside the sphere, sample the spanned solid angle uniformly. When shading point lies inside the sphere, sample spherical direction uniformly when inside volume or the surface is transmissive, otherwise sample cosine-weighted upper hemisphere. ## Light Tree When shading point lies outside the sphere, treat as a disk light spanning the same solid angle. When shading point lies inside the sphere, it behaves like a background light, with estimated outgoing radiance \[L_o=\int f_aL_i\cos\theta_i\mathrm{d}\omega_i=\int f_a\frac{E}{\pi r^2}\cos\theta_i\mathrm{d}\omega_i\approx f_a \frac{E}{r^2}\], with \(f_a\) being the BSDF and \(E\) `measure.energy` in `light_tree.cpp`. The importance calculation for `LIGHT_POINT` is \[L_o=f_a E\cos\theta_i\frac{\cos\theta}{d^2}\]. Consider `min_importance = 0` because maximal incidence angle is \(\pi\), we could substitute \(d^2\) with \(\frac{r^2}{2}\) so the averaged outgoing radiance is \(f_a \frac{E}{r^2}\). This only holds for non-transmissive surface, but should be fine to use in volume. # EEVEE When shading point lies outside the sphere, the sphere light is equivalent to a disk light spanning the same solid angle. The sine of the new half-angle is the tangent of the previous half-angle. When shading point lies inside the sphere, integrating over the cosine-weighted hemisphere gives 1.0. ## Comparison with Cycles The plane is diffuse, the blue sphere has specular component. | Before | |After || |---|--|--|--| |Cycles|EEVEE|Cycles|EEVEE| |![](attachments/5824c494-0645-461a-b193-d74e02f353b8)|![](attachments/d2e85b53-3c2a-4a9f-a3b2-6e11c6083ce0)|![](attachments/a8dcdd8b-c13c-4fdc-808c-2563624549be)|![](attachments/8c3618ef-1ab4-4210-9535-c85e873f1e45)| Pull Request: https://projects.blender.org/blender/blender/pulls/108506
2023-06-20 12:23:05 +02:00
const float3 N,
const int shader_flags,
ccl_private LightSample *ls)
{
Cycles/EEVEE: change point light to double-sided sphere light for energy preservation and better compatibility with other renderes. Ref: #108505 Point light now behaves the same as a spherical mesh light with the same overall energy (scaling from emission strength to power is \(4\pi^2R^2\)). # Cycles ## Comparison | Mesh Light | This patch | Previous behavior | | -------- | -------- | -------- | | ![mesh_1024](attachments/2900954c-57f8-49c2-b6f3-8fb559b820ac) | ![sphere_1024](attachments/148241ca-9350-48b6-be04-3933e015424c) | ![point_1024](attachments/d9b19d54-2b00-4986-ba8c-c4b28f687f09) | The behavior stays the same when `radius = 0`. | This patch | Previous behavior | | -------- | -------- | | ![sphere_64](attachments/aa05d59a-146a-4f69-b257-5d09a7f41d4e) | ![point_64](attachments/69a743be-bc15-454b-92d8-af02f4e8ab07) | No obvious performance change observed. ## Sampling When shading point lies outside the sphere, sample the spanned solid angle uniformly. When shading point lies inside the sphere, sample spherical direction uniformly when inside volume or the surface is transmissive, otherwise sample cosine-weighted upper hemisphere. ## Light Tree When shading point lies outside the sphere, treat as a disk light spanning the same solid angle. When shading point lies inside the sphere, it behaves like a background light, with estimated outgoing radiance \[L_o=\int f_aL_i\cos\theta_i\mathrm{d}\omega_i=\int f_a\frac{E}{\pi r^2}\cos\theta_i\mathrm{d}\omega_i\approx f_a \frac{E}{r^2}\], with \(f_a\) being the BSDF and \(E\) `measure.energy` in `light_tree.cpp`. The importance calculation for `LIGHT_POINT` is \[L_o=f_a E\cos\theta_i\frac{\cos\theta}{d^2}\]. Consider `min_importance = 0` because maximal incidence angle is \(\pi\), we could substitute \(d^2\) with \(\frac{r^2}{2}\) so the averaged outgoing radiance is \(f_a \frac{E}{r^2}\). This only holds for non-transmissive surface, but should be fine to use in volume. # EEVEE When shading point lies outside the sphere, the sphere light is equivalent to a disk light spanning the same solid angle. The sine of the new half-angle is the tangent of the previous half-angle. When shading point lies inside the sphere, integrating over the cosine-weighted hemisphere gives 1.0. ## Comparison with Cycles The plane is diffuse, the blue sphere has specular component. | Before | |After || |---|--|--|--| |Cycles|EEVEE|Cycles|EEVEE| |![](attachments/5824c494-0645-461a-b193-d74e02f353b8)|![](attachments/d2e85b53-3c2a-4a9f-a3b2-6e11c6083ce0)|![](attachments/a8dcdd8b-c13c-4fdc-808c-2563624549be)|![](attachments/8c3618ef-1ab4-4210-9535-c85e873f1e45)| Pull Request: https://projects.blender.org/blender/blender/pulls/108506
2023-06-20 12:23:05 +02:00
float3 lightN = P - klight->co;
const float d_sq = len_squared(lightN);
const float d = sqrtf(d_sq);
lightN /= d;
const float r_sq = sqr(klight->spot.radius);
float cos_theta;
if (d_sq > r_sq) {
const float one_minus_cos = sin_sqr_to_one_minus_cos(r_sq / d_sq);
ls->D = sample_uniform_cone(-lightN, one_minus_cos, rand, &cos_theta, &ls->pdf);
Cycles/EEVEE: change point light to double-sided sphere light for energy preservation and better compatibility with other renderes. Ref: #108505 Point light now behaves the same as a spherical mesh light with the same overall energy (scaling from emission strength to power is \(4\pi^2R^2\)). # Cycles ## Comparison | Mesh Light | This patch | Previous behavior | | -------- | -------- | -------- | | ![mesh_1024](attachments/2900954c-57f8-49c2-b6f3-8fb559b820ac) | ![sphere_1024](attachments/148241ca-9350-48b6-be04-3933e015424c) | ![point_1024](attachments/d9b19d54-2b00-4986-ba8c-c4b28f687f09) | The behavior stays the same when `radius = 0`. | This patch | Previous behavior | | -------- | -------- | | ![sphere_64](attachments/aa05d59a-146a-4f69-b257-5d09a7f41d4e) | ![point_64](attachments/69a743be-bc15-454b-92d8-af02f4e8ab07) | No obvious performance change observed. ## Sampling When shading point lies outside the sphere, sample the spanned solid angle uniformly. When shading point lies inside the sphere, sample spherical direction uniformly when inside volume or the surface is transmissive, otherwise sample cosine-weighted upper hemisphere. ## Light Tree When shading point lies outside the sphere, treat as a disk light spanning the same solid angle. When shading point lies inside the sphere, it behaves like a background light, with estimated outgoing radiance \[L_o=\int f_aL_i\cos\theta_i\mathrm{d}\omega_i=\int f_a\frac{E}{\pi r^2}\cos\theta_i\mathrm{d}\omega_i\approx f_a \frac{E}{r^2}\], with \(f_a\) being the BSDF and \(E\) `measure.energy` in `light_tree.cpp`. The importance calculation for `LIGHT_POINT` is \[L_o=f_a E\cos\theta_i\frac{\cos\theta}{d^2}\]. Consider `min_importance = 0` because maximal incidence angle is \(\pi\), we could substitute \(d^2\) with \(\frac{r^2}{2}\) so the averaged outgoing radiance is \(f_a \frac{E}{r^2}\). This only holds for non-transmissive surface, but should be fine to use in volume. # EEVEE When shading point lies outside the sphere, the sphere light is equivalent to a disk light spanning the same solid angle. The sine of the new half-angle is the tangent of the previous half-angle. When shading point lies inside the sphere, integrating over the cosine-weighted hemisphere gives 1.0. ## Comparison with Cycles The plane is diffuse, the blue sphere has specular component. | Before | |After || |---|--|--|--| |Cycles|EEVEE|Cycles|EEVEE| |![](attachments/5824c494-0645-461a-b193-d74e02f353b8)|![](attachments/d2e85b53-3c2a-4a9f-a3b2-6e11c6083ce0)|![](attachments/a8dcdd8b-c13c-4fdc-808c-2563624549be)|![](attachments/8c3618ef-1ab4-4210-9535-c85e873f1e45)| Pull Request: https://projects.blender.org/blender/blender/pulls/108506
2023-06-20 12:23:05 +02:00
}
else {
const bool has_transmission = (shader_flags & SD_BSDF_HAS_TRANSMISSION);
if (has_transmission) {
ls->D = sample_uniform_sphere(rand);
ls->pdf = M_1_2PI_F * 0.5f;
}
else {
sample_cos_hemisphere(N, rand, &ls->D, &ls->pdf);
}
cos_theta = -dot(ls->D, lightN);
}
Cycles/EEVEE: change point light to double-sided sphere light for energy preservation and better compatibility with other renderes. Ref: #108505 Point light now behaves the same as a spherical mesh light with the same overall energy (scaling from emission strength to power is \(4\pi^2R^2\)). # Cycles ## Comparison | Mesh Light | This patch | Previous behavior | | -------- | -------- | -------- | | ![mesh_1024](attachments/2900954c-57f8-49c2-b6f3-8fb559b820ac) | ![sphere_1024](attachments/148241ca-9350-48b6-be04-3933e015424c) | ![point_1024](attachments/d9b19d54-2b00-4986-ba8c-c4b28f687f09) | The behavior stays the same when `radius = 0`. | This patch | Previous behavior | | -------- | -------- | | ![sphere_64](attachments/aa05d59a-146a-4f69-b257-5d09a7f41d4e) | ![point_64](attachments/69a743be-bc15-454b-92d8-af02f4e8ab07) | No obvious performance change observed. ## Sampling When shading point lies outside the sphere, sample the spanned solid angle uniformly. When shading point lies inside the sphere, sample spherical direction uniformly when inside volume or the surface is transmissive, otherwise sample cosine-weighted upper hemisphere. ## Light Tree When shading point lies outside the sphere, treat as a disk light spanning the same solid angle. When shading point lies inside the sphere, it behaves like a background light, with estimated outgoing radiance \[L_o=\int f_aL_i\cos\theta_i\mathrm{d}\omega_i=\int f_a\frac{E}{\pi r^2}\cos\theta_i\mathrm{d}\omega_i\approx f_a \frac{E}{r^2}\], with \(f_a\) being the BSDF and \(E\) `measure.energy` in `light_tree.cpp`. The importance calculation for `LIGHT_POINT` is \[L_o=f_a E\cos\theta_i\frac{\cos\theta}{d^2}\]. Consider `min_importance = 0` because maximal incidence angle is \(\pi\), we could substitute \(d^2\) with \(\frac{r^2}{2}\) so the averaged outgoing radiance is \(f_a \frac{E}{r^2}\). This only holds for non-transmissive surface, but should be fine to use in volume. # EEVEE When shading point lies outside the sphere, the sphere light is equivalent to a disk light spanning the same solid angle. The sine of the new half-angle is the tangent of the previous half-angle. When shading point lies inside the sphere, integrating over the cosine-weighted hemisphere gives 1.0. ## Comparison with Cycles The plane is diffuse, the blue sphere has specular component. | Before | |After || |---|--|--|--| |Cycles|EEVEE|Cycles|EEVEE| |![](attachments/5824c494-0645-461a-b193-d74e02f353b8)|![](attachments/d2e85b53-3c2a-4a9f-a3b2-6e11c6083ce0)|![](attachments/a8dcdd8b-c13c-4fdc-808c-2563624549be)|![](attachments/8c3618ef-1ab4-4210-9535-c85e873f1e45)| Pull Request: https://projects.blender.org/blender/blender/pulls/108506
2023-06-20 12:23:05 +02:00
/* Law of cosines. */
ls->t = d * cos_theta - copysignf(safe_sqrtf(r_sq - d_sq + d_sq * sqr(cos_theta)), d_sq - r_sq);
ls->P = P + ls->D * ls->t;
Cycles: replace spot light disk sampling with sphere sampling 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 | | -- | -- | |![spot_size_before.png](/attachments/04ea864a-6bf9-40fe-b11b-61c838ae70cf)|![spot_size_after.png](/attachments/7077eaf9-b7a8-41b1-a8b6-aabf1eadb4f4) ## 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. ![versioning.png](/attachments/5bbfcacc-26c5-4f7f-8360-c42bcd851f68) Example file see https://archive.blender.org/developer/T93676 Pull Request: https://projects.blender.org/blender/blender/pulls/109329
2023-07-07 17:15:18 +02:00
ls->eval_fac = klight->spot.eval_fac;
Cycles/EEVEE: change point light to double-sided sphere light for energy preservation and better compatibility with other renderes. Ref: #108505 Point light now behaves the same as a spherical mesh light with the same overall energy (scaling from emission strength to power is \(4\pi^2R^2\)). # Cycles ## Comparison | Mesh Light | This patch | Previous behavior | | -------- | -------- | -------- | | ![mesh_1024](attachments/2900954c-57f8-49c2-b6f3-8fb559b820ac) | ![sphere_1024](attachments/148241ca-9350-48b6-be04-3933e015424c) | ![point_1024](attachments/d9b19d54-2b00-4986-ba8c-c4b28f687f09) | The behavior stays the same when `radius = 0`. | This patch | Previous behavior | | -------- | -------- | | ![sphere_64](attachments/aa05d59a-146a-4f69-b257-5d09a7f41d4e) | ![point_64](attachments/69a743be-bc15-454b-92d8-af02f4e8ab07) | No obvious performance change observed. ## Sampling When shading point lies outside the sphere, sample the spanned solid angle uniformly. When shading point lies inside the sphere, sample spherical direction uniformly when inside volume or the surface is transmissive, otherwise sample cosine-weighted upper hemisphere. ## Light Tree When shading point lies outside the sphere, treat as a disk light spanning the same solid angle. When shading point lies inside the sphere, it behaves like a background light, with estimated outgoing radiance \[L_o=\int f_aL_i\cos\theta_i\mathrm{d}\omega_i=\int f_a\frac{E}{\pi r^2}\cos\theta_i\mathrm{d}\omega_i\approx f_a \frac{E}{r^2}\], with \(f_a\) being the BSDF and \(E\) `measure.energy` in `light_tree.cpp`. The importance calculation for `LIGHT_POINT` is \[L_o=f_a E\cos\theta_i\frac{\cos\theta}{d^2}\]. Consider `min_importance = 0` because maximal incidence angle is \(\pi\), we could substitute \(d^2\) with \(\frac{r^2}{2}\) so the averaged outgoing radiance is \(f_a \frac{E}{r^2}\). This only holds for non-transmissive surface, but should be fine to use in volume. # EEVEE When shading point lies outside the sphere, the sphere light is equivalent to a disk light spanning the same solid angle. The sine of the new half-angle is the tangent of the previous half-angle. When shading point lies inside the sphere, integrating over the cosine-weighted hemisphere gives 1.0. ## Comparison with Cycles The plane is diffuse, the blue sphere has specular component. | Before | |After || |---|--|--|--| |Cycles|EEVEE|Cycles|EEVEE| |![](attachments/5824c494-0645-461a-b193-d74e02f353b8)|![](attachments/d2e85b53-3c2a-4a9f-a3b2-6e11c6083ce0)|![](attachments/a8dcdd8b-c13c-4fdc-808c-2563624549be)|![](attachments/8c3618ef-1ab4-4210-9535-c85e873f1e45)| Pull Request: https://projects.blender.org/blender/blender/pulls/108506
2023-06-20 12:23:05 +02:00
if (r_sq == 0) {
/* Use intensity instead of radiance for point light. */
ls->eval_fac /= sqr(ls->t);
2023-07-15 15:45:06 +10:00
/* `ls->Ng` is not well-defined for point light, so use the incoming direction instead. */
Cycles/EEVEE: change point light to double-sided sphere light for energy preservation and better compatibility with other renderes. Ref: #108505 Point light now behaves the same as a spherical mesh light with the same overall energy (scaling from emission strength to power is \(4\pi^2R^2\)). # Cycles ## Comparison | Mesh Light | This patch | Previous behavior | | -------- | -------- | -------- | | ![mesh_1024](attachments/2900954c-57f8-49c2-b6f3-8fb559b820ac) | ![sphere_1024](attachments/148241ca-9350-48b6-be04-3933e015424c) | ![point_1024](attachments/d9b19d54-2b00-4986-ba8c-c4b28f687f09) | The behavior stays the same when `radius = 0`. | This patch | Previous behavior | | -------- | -------- | | ![sphere_64](attachments/aa05d59a-146a-4f69-b257-5d09a7f41d4e) | ![point_64](attachments/69a743be-bc15-454b-92d8-af02f4e8ab07) | No obvious performance change observed. ## Sampling When shading point lies outside the sphere, sample the spanned solid angle uniformly. When shading point lies inside the sphere, sample spherical direction uniformly when inside volume or the surface is transmissive, otherwise sample cosine-weighted upper hemisphere. ## Light Tree When shading point lies outside the sphere, treat as a disk light spanning the same solid angle. When shading point lies inside the sphere, it behaves like a background light, with estimated outgoing radiance \[L_o=\int f_aL_i\cos\theta_i\mathrm{d}\omega_i=\int f_a\frac{E}{\pi r^2}\cos\theta_i\mathrm{d}\omega_i\approx f_a \frac{E}{r^2}\], with \(f_a\) being the BSDF and \(E\) `measure.energy` in `light_tree.cpp`. The importance calculation for `LIGHT_POINT` is \[L_o=f_a E\cos\theta_i\frac{\cos\theta}{d^2}\]. Consider `min_importance = 0` because maximal incidence angle is \(\pi\), we could substitute \(d^2\) with \(\frac{r^2}{2}\) so the averaged outgoing radiance is \(f_a \frac{E}{r^2}\). This only holds for non-transmissive surface, but should be fine to use in volume. # EEVEE When shading point lies outside the sphere, the sphere light is equivalent to a disk light spanning the same solid angle. The sine of the new half-angle is the tangent of the previous half-angle. When shading point lies inside the sphere, integrating over the cosine-weighted hemisphere gives 1.0. ## Comparison with Cycles The plane is diffuse, the blue sphere has specular component. | Before | |After || |---|--|--|--| |Cycles|EEVEE|Cycles|EEVEE| |![](attachments/5824c494-0645-461a-b193-d74e02f353b8)|![](attachments/d2e85b53-3c2a-4a9f-a3b2-6e11c6083ce0)|![](attachments/a8dcdd8b-c13c-4fdc-808c-2563624549be)|![](attachments/8c3618ef-1ab4-4210-9535-c85e873f1e45)| Pull Request: https://projects.blender.org/blender/blender/pulls/108506
2023-06-20 12:23:05 +02:00
ls->Ng = -ls->D;
}
else {
ls->Ng = normalize(ls->P - klight->co);
/* Remap sampled point onto the sphere to prevent precision issues with small radius. */
ls->P = ls->Ng * klight->spot.radius + klight->co;
}
const Transform itfm = klight->itfm;
const float2 uv = map_to_sphere(transform_direction(&itfm, ls->Ng));
/* NOTE: Return barycentric coordinates in the same notation as Embree and OptiX. */
ls->u = uv.y;
ls->v = 1.0f - uv.x - uv.y;
return true;
}
Cycles/EEVEE: change point light to double-sided sphere light for energy preservation and better compatibility with other renderes. Ref: #108505 Point light now behaves the same as a spherical mesh light with the same overall energy (scaling from emission strength to power is \(4\pi^2R^2\)). # Cycles ## Comparison | Mesh Light | This patch | Previous behavior | | -------- | -------- | -------- | | ![mesh_1024](attachments/2900954c-57f8-49c2-b6f3-8fb559b820ac) | ![sphere_1024](attachments/148241ca-9350-48b6-be04-3933e015424c) | ![point_1024](attachments/d9b19d54-2b00-4986-ba8c-c4b28f687f09) | The behavior stays the same when `radius = 0`. | This patch | Previous behavior | | -------- | -------- | | ![sphere_64](attachments/aa05d59a-146a-4f69-b257-5d09a7f41d4e) | ![point_64](attachments/69a743be-bc15-454b-92d8-af02f4e8ab07) | No obvious performance change observed. ## Sampling When shading point lies outside the sphere, sample the spanned solid angle uniformly. When shading point lies inside the sphere, sample spherical direction uniformly when inside volume or the surface is transmissive, otherwise sample cosine-weighted upper hemisphere. ## Light Tree When shading point lies outside the sphere, treat as a disk light spanning the same solid angle. When shading point lies inside the sphere, it behaves like a background light, with estimated outgoing radiance \[L_o=\int f_aL_i\cos\theta_i\mathrm{d}\omega_i=\int f_a\frac{E}{\pi r^2}\cos\theta_i\mathrm{d}\omega_i\approx f_a \frac{E}{r^2}\], with \(f_a\) being the BSDF and \(E\) `measure.energy` in `light_tree.cpp`. The importance calculation for `LIGHT_POINT` is \[L_o=f_a E\cos\theta_i\frac{\cos\theta}{d^2}\]. Consider `min_importance = 0` because maximal incidence angle is \(\pi\), we could substitute \(d^2\) with \(\frac{r^2}{2}\) so the averaged outgoing radiance is \(f_a \frac{E}{r^2}\). This only holds for non-transmissive surface, but should be fine to use in volume. # EEVEE When shading point lies outside the sphere, the sphere light is equivalent to a disk light spanning the same solid angle. The sine of the new half-angle is the tangent of the previous half-angle. When shading point lies inside the sphere, integrating over the cosine-weighted hemisphere gives 1.0. ## Comparison with Cycles The plane is diffuse, the blue sphere has specular component. | Before | |After || |---|--|--|--| |Cycles|EEVEE|Cycles|EEVEE| |![](attachments/5824c494-0645-461a-b193-d74e02f353b8)|![](attachments/d2e85b53-3c2a-4a9f-a3b2-6e11c6083ce0)|![](attachments/a8dcdd8b-c13c-4fdc-808c-2563624549be)|![](attachments/8c3618ef-1ab4-4210-9535-c85e873f1e45)| Pull Request: https://projects.blender.org/blender/blender/pulls/108506
2023-06-20 12:23:05 +02:00
ccl_device_forceinline float point_light_pdf(
const float d_sq, const float r_sq, const float3 N, const float3 D, const uint32_t path_flag)
{
if (d_sq > r_sq) {
return M_1_2PI_F / sin_sqr_to_one_minus_cos(r_sq / d_sq);
}
const bool has_transmission = (path_flag & PATH_RAY_MIS_HAD_TRANSMISSION);
return has_transmission ? M_1_2PI_F * 0.5f : pdf_cos_hemisphere(N, D);
}
ccl_device_forceinline void point_light_mnee_sample_update(const ccl_global KernelLight *klight,
ccl_private LightSample *ls,
Cycles/EEVEE: change point light to double-sided sphere light for energy preservation and better compatibility with other renderes. Ref: #108505 Point light now behaves the same as a spherical mesh light with the same overall energy (scaling from emission strength to power is \(4\pi^2R^2\)). # Cycles ## Comparison | Mesh Light | This patch | Previous behavior | | -------- | -------- | -------- | | ![mesh_1024](attachments/2900954c-57f8-49c2-b6f3-8fb559b820ac) | ![sphere_1024](attachments/148241ca-9350-48b6-be04-3933e015424c) | ![point_1024](attachments/d9b19d54-2b00-4986-ba8c-c4b28f687f09) | The behavior stays the same when `radius = 0`. | This patch | Previous behavior | | -------- | -------- | | ![sphere_64](attachments/aa05d59a-146a-4f69-b257-5d09a7f41d4e) | ![point_64](attachments/69a743be-bc15-454b-92d8-af02f4e8ab07) | No obvious performance change observed. ## Sampling When shading point lies outside the sphere, sample the spanned solid angle uniformly. When shading point lies inside the sphere, sample spherical direction uniformly when inside volume or the surface is transmissive, otherwise sample cosine-weighted upper hemisphere. ## Light Tree When shading point lies outside the sphere, treat as a disk light spanning the same solid angle. When shading point lies inside the sphere, it behaves like a background light, with estimated outgoing radiance \[L_o=\int f_aL_i\cos\theta_i\mathrm{d}\omega_i=\int f_a\frac{E}{\pi r^2}\cos\theta_i\mathrm{d}\omega_i\approx f_a \frac{E}{r^2}\], with \(f_a\) being the BSDF and \(E\) `measure.energy` in `light_tree.cpp`. The importance calculation for `LIGHT_POINT` is \[L_o=f_a E\cos\theta_i\frac{\cos\theta}{d^2}\]. Consider `min_importance = 0` because maximal incidence angle is \(\pi\), we could substitute \(d^2\) with \(\frac{r^2}{2}\) so the averaged outgoing radiance is \(f_a \frac{E}{r^2}\). This only holds for non-transmissive surface, but should be fine to use in volume. # EEVEE When shading point lies outside the sphere, the sphere light is equivalent to a disk light spanning the same solid angle. The sine of the new half-angle is the tangent of the previous half-angle. When shading point lies inside the sphere, integrating over the cosine-weighted hemisphere gives 1.0. ## Comparison with Cycles The plane is diffuse, the blue sphere has specular component. | Before | |After || |---|--|--|--| |Cycles|EEVEE|Cycles|EEVEE| |![](attachments/5824c494-0645-461a-b193-d74e02f353b8)|![](attachments/d2e85b53-3c2a-4a9f-a3b2-6e11c6083ce0)|![](attachments/a8dcdd8b-c13c-4fdc-808c-2563624549be)|![](attachments/8c3618ef-1ab4-4210-9535-c85e873f1e45)| Pull Request: https://projects.blender.org/blender/blender/pulls/108506
2023-06-20 12:23:05 +02:00
const float3 P,
const float3 N,
const uint32_t path_flag)
{
ls->D = normalize_len(ls->P - P, &ls->t);
Cycles/EEVEE: change point light to double-sided sphere light for energy preservation and better compatibility with other renderes. Ref: #108505 Point light now behaves the same as a spherical mesh light with the same overall energy (scaling from emission strength to power is \(4\pi^2R^2\)). # Cycles ## Comparison | Mesh Light | This patch | Previous behavior | | -------- | -------- | -------- | | ![mesh_1024](attachments/2900954c-57f8-49c2-b6f3-8fb559b820ac) | ![sphere_1024](attachments/148241ca-9350-48b6-be04-3933e015424c) | ![point_1024](attachments/d9b19d54-2b00-4986-ba8c-c4b28f687f09) | The behavior stays the same when `radius = 0`. | This patch | Previous behavior | | -------- | -------- | | ![sphere_64](attachments/aa05d59a-146a-4f69-b257-5d09a7f41d4e) | ![point_64](attachments/69a743be-bc15-454b-92d8-af02f4e8ab07) | No obvious performance change observed. ## Sampling When shading point lies outside the sphere, sample the spanned solid angle uniformly. When shading point lies inside the sphere, sample spherical direction uniformly when inside volume or the surface is transmissive, otherwise sample cosine-weighted upper hemisphere. ## Light Tree When shading point lies outside the sphere, treat as a disk light spanning the same solid angle. When shading point lies inside the sphere, it behaves like a background light, with estimated outgoing radiance \[L_o=\int f_aL_i\cos\theta_i\mathrm{d}\omega_i=\int f_a\frac{E}{\pi r^2}\cos\theta_i\mathrm{d}\omega_i\approx f_a \frac{E}{r^2}\], with \(f_a\) being the BSDF and \(E\) `measure.energy` in `light_tree.cpp`. The importance calculation for `LIGHT_POINT` is \[L_o=f_a E\cos\theta_i\frac{\cos\theta}{d^2}\]. Consider `min_importance = 0` because maximal incidence angle is \(\pi\), we could substitute \(d^2\) with \(\frac{r^2}{2}\) so the averaged outgoing radiance is \(f_a \frac{E}{r^2}\). This only holds for non-transmissive surface, but should be fine to use in volume. # EEVEE When shading point lies outside the sphere, the sphere light is equivalent to a disk light spanning the same solid angle. The sine of the new half-angle is the tangent of the previous half-angle. When shading point lies inside the sphere, integrating over the cosine-weighted hemisphere gives 1.0. ## Comparison with Cycles The plane is diffuse, the blue sphere has specular component. | Before | |After || |---|--|--|--| |Cycles|EEVEE|Cycles|EEVEE| |![](attachments/5824c494-0645-461a-b193-d74e02f353b8)|![](attachments/d2e85b53-3c2a-4a9f-a3b2-6e11c6083ce0)|![](attachments/a8dcdd8b-c13c-4fdc-808c-2563624549be)|![](attachments/8c3618ef-1ab4-4210-9535-c85e873f1e45)| Pull Request: https://projects.blender.org/blender/blender/pulls/108506
2023-06-20 12:23:05 +02:00
const float radius = klight->spot.radius;
Cycles/EEVEE: change point light to double-sided sphere light for energy preservation and better compatibility with other renderes. Ref: #108505 Point light now behaves the same as a spherical mesh light with the same overall energy (scaling from emission strength to power is \(4\pi^2R^2\)). # Cycles ## Comparison | Mesh Light | This patch | Previous behavior | | -------- | -------- | -------- | | ![mesh_1024](attachments/2900954c-57f8-49c2-b6f3-8fb559b820ac) | ![sphere_1024](attachments/148241ca-9350-48b6-be04-3933e015424c) | ![point_1024](attachments/d9b19d54-2b00-4986-ba8c-c4b28f687f09) | The behavior stays the same when `radius = 0`. | This patch | Previous behavior | | -------- | -------- | | ![sphere_64](attachments/aa05d59a-146a-4f69-b257-5d09a7f41d4e) | ![point_64](attachments/69a743be-bc15-454b-92d8-af02f4e8ab07) | No obvious performance change observed. ## Sampling When shading point lies outside the sphere, sample the spanned solid angle uniformly. When shading point lies inside the sphere, sample spherical direction uniformly when inside volume or the surface is transmissive, otherwise sample cosine-weighted upper hemisphere. ## Light Tree When shading point lies outside the sphere, treat as a disk light spanning the same solid angle. When shading point lies inside the sphere, it behaves like a background light, with estimated outgoing radiance \[L_o=\int f_aL_i\cos\theta_i\mathrm{d}\omega_i=\int f_a\frac{E}{\pi r^2}\cos\theta_i\mathrm{d}\omega_i\approx f_a \frac{E}{r^2}\], with \(f_a\) being the BSDF and \(E\) `measure.energy` in `light_tree.cpp`. The importance calculation for `LIGHT_POINT` is \[L_o=f_a E\cos\theta_i\frac{\cos\theta}{d^2}\]. Consider `min_importance = 0` because maximal incidence angle is \(\pi\), we could substitute \(d^2\) with \(\frac{r^2}{2}\) so the averaged outgoing radiance is \(f_a \frac{E}{r^2}\). This only holds for non-transmissive surface, but should be fine to use in volume. # EEVEE When shading point lies outside the sphere, the sphere light is equivalent to a disk light spanning the same solid angle. The sine of the new half-angle is the tangent of the previous half-angle. When shading point lies inside the sphere, integrating over the cosine-weighted hemisphere gives 1.0. ## Comparison with Cycles The plane is diffuse, the blue sphere has specular component. | Before | |After || |---|--|--|--| |Cycles|EEVEE|Cycles|EEVEE| |![](attachments/5824c494-0645-461a-b193-d74e02f353b8)|![](attachments/d2e85b53-3c2a-4a9f-a3b2-6e11c6083ce0)|![](attachments/a8dcdd8b-c13c-4fdc-808c-2563624549be)|![](attachments/8c3618ef-1ab4-4210-9535-c85e873f1e45)| Pull Request: https://projects.blender.org/blender/blender/pulls/108506
2023-06-20 12:23:05 +02:00
if (radius > 0) {
const float d_sq = len_squared(P - klight->co);
const float r_sq = sqr(radius);
const float t_sq = sqr(ls->t);
ls->pdf = point_light_pdf(d_sq, r_sq, N, ls->D, path_flag);
/* NOTE : preserve pdf in area measure. */
ls->pdf *= 0.5f * fabsf(d_sq - r_sq - t_sq) / (radius * ls->t * t_sq);
ls->Ng = normalize(ls->P - klight->co);
}
else {
Cycles: replace spot light disk sampling with sphere sampling 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 | | -- | -- | |![spot_size_before.png](/attachments/04ea864a-6bf9-40fe-b11b-61c838ae70cf)|![spot_size_after.png](/attachments/7077eaf9-b7a8-41b1-a8b6-aabf1eadb4f4) ## 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. ![versioning.png](/attachments/5bbfcacc-26c5-4f7f-8360-c42bcd851f68) Example file see https://archive.blender.org/developer/T93676 Pull Request: https://projects.blender.org/blender/blender/pulls/109329
2023-07-07 17:15:18 +02:00
ls->eval_fac = klight->spot.eval_fac;
Cycles/EEVEE: change point light to double-sided sphere light for energy preservation and better compatibility with other renderes. Ref: #108505 Point light now behaves the same as a spherical mesh light with the same overall energy (scaling from emission strength to power is \(4\pi^2R^2\)). # Cycles ## Comparison | Mesh Light | This patch | Previous behavior | | -------- | -------- | -------- | | ![mesh_1024](attachments/2900954c-57f8-49c2-b6f3-8fb559b820ac) | ![sphere_1024](attachments/148241ca-9350-48b6-be04-3933e015424c) | ![point_1024](attachments/d9b19d54-2b00-4986-ba8c-c4b28f687f09) | The behavior stays the same when `radius = 0`. | This patch | Previous behavior | | -------- | -------- | | ![sphere_64](attachments/aa05d59a-146a-4f69-b257-5d09a7f41d4e) | ![point_64](attachments/69a743be-bc15-454b-92d8-af02f4e8ab07) | No obvious performance change observed. ## Sampling When shading point lies outside the sphere, sample the spanned solid angle uniformly. When shading point lies inside the sphere, sample spherical direction uniformly when inside volume or the surface is transmissive, otherwise sample cosine-weighted upper hemisphere. ## Light Tree When shading point lies outside the sphere, treat as a disk light spanning the same solid angle. When shading point lies inside the sphere, it behaves like a background light, with estimated outgoing radiance \[L_o=\int f_aL_i\cos\theta_i\mathrm{d}\omega_i=\int f_a\frac{E}{\pi r^2}\cos\theta_i\mathrm{d}\omega_i\approx f_a \frac{E}{r^2}\], with \(f_a\) being the BSDF and \(E\) `measure.energy` in `light_tree.cpp`. The importance calculation for `LIGHT_POINT` is \[L_o=f_a E\cos\theta_i\frac{\cos\theta}{d^2}\]. Consider `min_importance = 0` because maximal incidence angle is \(\pi\), we could substitute \(d^2\) with \(\frac{r^2}{2}\) so the averaged outgoing radiance is \(f_a \frac{E}{r^2}\). This only holds for non-transmissive surface, but should be fine to use in volume. # EEVEE When shading point lies outside the sphere, the sphere light is equivalent to a disk light spanning the same solid angle. The sine of the new half-angle is the tangent of the previous half-angle. When shading point lies inside the sphere, integrating over the cosine-weighted hemisphere gives 1.0. ## Comparison with Cycles The plane is diffuse, the blue sphere has specular component. | Before | |After || |---|--|--|--| |Cycles|EEVEE|Cycles|EEVEE| |![](attachments/5824c494-0645-461a-b193-d74e02f353b8)|![](attachments/d2e85b53-3c2a-4a9f-a3b2-6e11c6083ce0)|![](attachments/a8dcdd8b-c13c-4fdc-808c-2563624549be)|![](attachments/8c3618ef-1ab4-4210-9535-c85e873f1e45)| Pull Request: https://projects.blender.org/blender/blender/pulls/108506
2023-06-20 12:23:05 +02:00
ls->Ng = -ls->D;
/* PDF does not change. */
}
const Transform itfm = klight->itfm;
const float2 uv = map_to_sphere(transform_direction(&itfm, ls->Ng));
/* NOTE: Return barycentric coordinates in the same notation as Embree and OptiX. */
ls->u = uv.y;
ls->v = 1.0f - uv.x - uv.y;
}
ccl_device_inline bool point_light_intersect(const ccl_global KernelLight *klight,
const ccl_private Ray *ccl_restrict ray,
ccl_private float *t)
{
const float radius = klight->spot.radius;
if (radius == 0.0f) {
return false;
}
float3 P;
Cycles/EEVEE: change point light to double-sided sphere light for energy preservation and better compatibility with other renderes. Ref: #108505 Point light now behaves the same as a spherical mesh light with the same overall energy (scaling from emission strength to power is \(4\pi^2R^2\)). # Cycles ## Comparison | Mesh Light | This patch | Previous behavior | | -------- | -------- | -------- | | ![mesh_1024](attachments/2900954c-57f8-49c2-b6f3-8fb559b820ac) | ![sphere_1024](attachments/148241ca-9350-48b6-be04-3933e015424c) | ![point_1024](attachments/d9b19d54-2b00-4986-ba8c-c4b28f687f09) | The behavior stays the same when `radius = 0`. | This patch | Previous behavior | | -------- | -------- | | ![sphere_64](attachments/aa05d59a-146a-4f69-b257-5d09a7f41d4e) | ![point_64](attachments/69a743be-bc15-454b-92d8-af02f4e8ab07) | No obvious performance change observed. ## Sampling When shading point lies outside the sphere, sample the spanned solid angle uniformly. When shading point lies inside the sphere, sample spherical direction uniformly when inside volume or the surface is transmissive, otherwise sample cosine-weighted upper hemisphere. ## Light Tree When shading point lies outside the sphere, treat as a disk light spanning the same solid angle. When shading point lies inside the sphere, it behaves like a background light, with estimated outgoing radiance \[L_o=\int f_aL_i\cos\theta_i\mathrm{d}\omega_i=\int f_a\frac{E}{\pi r^2}\cos\theta_i\mathrm{d}\omega_i\approx f_a \frac{E}{r^2}\], with \(f_a\) being the BSDF and \(E\) `measure.energy` in `light_tree.cpp`. The importance calculation for `LIGHT_POINT` is \[L_o=f_a E\cos\theta_i\frac{\cos\theta}{d^2}\]. Consider `min_importance = 0` because maximal incidence angle is \(\pi\), we could substitute \(d^2\) with \(\frac{r^2}{2}\) so the averaged outgoing radiance is \(f_a \frac{E}{r^2}\). This only holds for non-transmissive surface, but should be fine to use in volume. # EEVEE When shading point lies outside the sphere, the sphere light is equivalent to a disk light spanning the same solid angle. The sine of the new half-angle is the tangent of the previous half-angle. When shading point lies inside the sphere, integrating over the cosine-weighted hemisphere gives 1.0. ## Comparison with Cycles The plane is diffuse, the blue sphere has specular component. | Before | |After || |---|--|--|--| |Cycles|EEVEE|Cycles|EEVEE| |![](attachments/5824c494-0645-461a-b193-d74e02f353b8)|![](attachments/d2e85b53-3c2a-4a9f-a3b2-6e11c6083ce0)|![](attachments/a8dcdd8b-c13c-4fdc-808c-2563624549be)|![](attachments/8c3618ef-1ab4-4210-9535-c85e873f1e45)| Pull Request: https://projects.blender.org/blender/blender/pulls/108506
2023-06-20 12:23:05 +02:00
return ray_sphere_intersect(ray->P, ray->D, ray->tmin, ray->tmax, klight->co, radius, &P, t);
}
ccl_device_inline bool point_light_sample_from_intersection(
const ccl_global KernelLight *klight,
ccl_private const Intersection *ccl_restrict isect,
const float3 ray_P,
const float3 ray_D,
Cycles/EEVEE: change point light to double-sided sphere light for energy preservation and better compatibility with other renderes. Ref: #108505 Point light now behaves the same as a spherical mesh light with the same overall energy (scaling from emission strength to power is \(4\pi^2R^2\)). # Cycles ## Comparison | Mesh Light | This patch | Previous behavior | | -------- | -------- | -------- | | ![mesh_1024](attachments/2900954c-57f8-49c2-b6f3-8fb559b820ac) | ![sphere_1024](attachments/148241ca-9350-48b6-be04-3933e015424c) | ![point_1024](attachments/d9b19d54-2b00-4986-ba8c-c4b28f687f09) | The behavior stays the same when `radius = 0`. | This patch | Previous behavior | | -------- | -------- | | ![sphere_64](attachments/aa05d59a-146a-4f69-b257-5d09a7f41d4e) | ![point_64](attachments/69a743be-bc15-454b-92d8-af02f4e8ab07) | No obvious performance change observed. ## Sampling When shading point lies outside the sphere, sample the spanned solid angle uniformly. When shading point lies inside the sphere, sample spherical direction uniformly when inside volume or the surface is transmissive, otherwise sample cosine-weighted upper hemisphere. ## Light Tree When shading point lies outside the sphere, treat as a disk light spanning the same solid angle. When shading point lies inside the sphere, it behaves like a background light, with estimated outgoing radiance \[L_o=\int f_aL_i\cos\theta_i\mathrm{d}\omega_i=\int f_a\frac{E}{\pi r^2}\cos\theta_i\mathrm{d}\omega_i\approx f_a \frac{E}{r^2}\], with \(f_a\) being the BSDF and \(E\) `measure.energy` in `light_tree.cpp`. The importance calculation for `LIGHT_POINT` is \[L_o=f_a E\cos\theta_i\frac{\cos\theta}{d^2}\]. Consider `min_importance = 0` because maximal incidence angle is \(\pi\), we could substitute \(d^2\) with \(\frac{r^2}{2}\) so the averaged outgoing radiance is \(f_a \frac{E}{r^2}\). This only holds for non-transmissive surface, but should be fine to use in volume. # EEVEE When shading point lies outside the sphere, the sphere light is equivalent to a disk light spanning the same solid angle. The sine of the new half-angle is the tangent of the previous half-angle. When shading point lies inside the sphere, integrating over the cosine-weighted hemisphere gives 1.0. ## Comparison with Cycles The plane is diffuse, the blue sphere has specular component. | Before | |After || |---|--|--|--| |Cycles|EEVEE|Cycles|EEVEE| |![](attachments/5824c494-0645-461a-b193-d74e02f353b8)|![](attachments/d2e85b53-3c2a-4a9f-a3b2-6e11c6083ce0)|![](attachments/a8dcdd8b-c13c-4fdc-808c-2563624549be)|![](attachments/8c3618ef-1ab4-4210-9535-c85e873f1e45)| Pull Request: https://projects.blender.org/blender/blender/pulls/108506
2023-06-20 12:23:05 +02:00
const float3 N,
const uint32_t path_flag,
ccl_private LightSample *ccl_restrict ls)
{
Cycles: replace spot light disk sampling with sphere sampling 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 | | -- | -- | |![spot_size_before.png](/attachments/04ea864a-6bf9-40fe-b11b-61c838ae70cf)|![spot_size_after.png](/attachments/7077eaf9-b7a8-41b1-a8b6-aabf1eadb4f4) ## 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. ![versioning.png](/attachments/5bbfcacc-26c5-4f7f-8360-c42bcd851f68) Example file see https://archive.blender.org/developer/T93676 Pull Request: https://projects.blender.org/blender/blender/pulls/109329
2023-07-07 17:15:18 +02:00
ls->eval_fac = klight->spot.eval_fac;
Cycles/EEVEE: change point light to double-sided sphere light for energy preservation and better compatibility with other renderes. Ref: #108505 Point light now behaves the same as a spherical mesh light with the same overall energy (scaling from emission strength to power is \(4\pi^2R^2\)). # Cycles ## Comparison | Mesh Light | This patch | Previous behavior | | -------- | -------- | -------- | | ![mesh_1024](attachments/2900954c-57f8-49c2-b6f3-8fb559b820ac) | ![sphere_1024](attachments/148241ca-9350-48b6-be04-3933e015424c) | ![point_1024](attachments/d9b19d54-2b00-4986-ba8c-c4b28f687f09) | The behavior stays the same when `radius = 0`. | This patch | Previous behavior | | -------- | -------- | | ![sphere_64](attachments/aa05d59a-146a-4f69-b257-5d09a7f41d4e) | ![point_64](attachments/69a743be-bc15-454b-92d8-af02f4e8ab07) | No obvious performance change observed. ## Sampling When shading point lies outside the sphere, sample the spanned solid angle uniformly. When shading point lies inside the sphere, sample spherical direction uniformly when inside volume or the surface is transmissive, otherwise sample cosine-weighted upper hemisphere. ## Light Tree When shading point lies outside the sphere, treat as a disk light spanning the same solid angle. When shading point lies inside the sphere, it behaves like a background light, with estimated outgoing radiance \[L_o=\int f_aL_i\cos\theta_i\mathrm{d}\omega_i=\int f_a\frac{E}{\pi r^2}\cos\theta_i\mathrm{d}\omega_i\approx f_a \frac{E}{r^2}\], with \(f_a\) being the BSDF and \(E\) `measure.energy` in `light_tree.cpp`. The importance calculation for `LIGHT_POINT` is \[L_o=f_a E\cos\theta_i\frac{\cos\theta}{d^2}\]. Consider `min_importance = 0` because maximal incidence angle is \(\pi\), we could substitute \(d^2\) with \(\frac{r^2}{2}\) so the averaged outgoing radiance is \(f_a \frac{E}{r^2}\). This only holds for non-transmissive surface, but should be fine to use in volume. # EEVEE When shading point lies outside the sphere, the sphere light is equivalent to a disk light spanning the same solid angle. The sine of the new half-angle is the tangent of the previous half-angle. When shading point lies inside the sphere, integrating over the cosine-weighted hemisphere gives 1.0. ## Comparison with Cycles The plane is diffuse, the blue sphere has specular component. | Before | |After || |---|--|--|--| |Cycles|EEVEE|Cycles|EEVEE| |![](attachments/5824c494-0645-461a-b193-d74e02f353b8)|![](attachments/d2e85b53-3c2a-4a9f-a3b2-6e11c6083ce0)|![](attachments/a8dcdd8b-c13c-4fdc-808c-2563624549be)|![](attachments/8c3618ef-1ab4-4210-9535-c85e873f1e45)| Pull Request: https://projects.blender.org/blender/blender/pulls/108506
2023-06-20 12:23:05 +02:00
const float radius = klight->spot.radius;
Cycles/EEVEE: change point light to double-sided sphere light for energy preservation and better compatibility with other renderes. Ref: #108505 Point light now behaves the same as a spherical mesh light with the same overall energy (scaling from emission strength to power is \(4\pi^2R^2\)). # Cycles ## Comparison | Mesh Light | This patch | Previous behavior | | -------- | -------- | -------- | | ![mesh_1024](attachments/2900954c-57f8-49c2-b6f3-8fb559b820ac) | ![sphere_1024](attachments/148241ca-9350-48b6-be04-3933e015424c) | ![point_1024](attachments/d9b19d54-2b00-4986-ba8c-c4b28f687f09) | The behavior stays the same when `radius = 0`. | This patch | Previous behavior | | -------- | -------- | | ![sphere_64](attachments/aa05d59a-146a-4f69-b257-5d09a7f41d4e) | ![point_64](attachments/69a743be-bc15-454b-92d8-af02f4e8ab07) | No obvious performance change observed. ## Sampling When shading point lies outside the sphere, sample the spanned solid angle uniformly. When shading point lies inside the sphere, sample spherical direction uniformly when inside volume or the surface is transmissive, otherwise sample cosine-weighted upper hemisphere. ## Light Tree When shading point lies outside the sphere, treat as a disk light spanning the same solid angle. When shading point lies inside the sphere, it behaves like a background light, with estimated outgoing radiance \[L_o=\int f_aL_i\cos\theta_i\mathrm{d}\omega_i=\int f_a\frac{E}{\pi r^2}\cos\theta_i\mathrm{d}\omega_i\approx f_a \frac{E}{r^2}\], with \(f_a\) being the BSDF and \(E\) `measure.energy` in `light_tree.cpp`. The importance calculation for `LIGHT_POINT` is \[L_o=f_a E\cos\theta_i\frac{\cos\theta}{d^2}\]. Consider `min_importance = 0` because maximal incidence angle is \(\pi\), we could substitute \(d^2\) with \(\frac{r^2}{2}\) so the averaged outgoing radiance is \(f_a \frac{E}{r^2}\). This only holds for non-transmissive surface, but should be fine to use in volume. # EEVEE When shading point lies outside the sphere, the sphere light is equivalent to a disk light spanning the same solid angle. The sine of the new half-angle is the tangent of the previous half-angle. When shading point lies inside the sphere, integrating over the cosine-weighted hemisphere gives 1.0. ## Comparison with Cycles The plane is diffuse, the blue sphere has specular component. | Before | |After || |---|--|--|--| |Cycles|EEVEE|Cycles|EEVEE| |![](attachments/5824c494-0645-461a-b193-d74e02f353b8)|![](attachments/d2e85b53-3c2a-4a9f-a3b2-6e11c6083ce0)|![](attachments/a8dcdd8b-c13c-4fdc-808c-2563624549be)|![](attachments/8c3618ef-1ab4-4210-9535-c85e873f1e45)| Pull Request: https://projects.blender.org/blender/blender/pulls/108506
2023-06-20 12:23:05 +02:00
ls->Ng = radius > 0 ? normalize(ls->P - klight->co) : -ray_D;
Cycles/EEVEE: change point light to double-sided sphere light for energy preservation and better compatibility with other renderes. Ref: #108505 Point light now behaves the same as a spherical mesh light with the same overall energy (scaling from emission strength to power is \(4\pi^2R^2\)). # Cycles ## Comparison | Mesh Light | This patch | Previous behavior | | -------- | -------- | -------- | | ![mesh_1024](attachments/2900954c-57f8-49c2-b6f3-8fb559b820ac) | ![sphere_1024](attachments/148241ca-9350-48b6-be04-3933e015424c) | ![point_1024](attachments/d9b19d54-2b00-4986-ba8c-c4b28f687f09) | The behavior stays the same when `radius = 0`. | This patch | Previous behavior | | -------- | -------- | | ![sphere_64](attachments/aa05d59a-146a-4f69-b257-5d09a7f41d4e) | ![point_64](attachments/69a743be-bc15-454b-92d8-af02f4e8ab07) | No obvious performance change observed. ## Sampling When shading point lies outside the sphere, sample the spanned solid angle uniformly. When shading point lies inside the sphere, sample spherical direction uniformly when inside volume or the surface is transmissive, otherwise sample cosine-weighted upper hemisphere. ## Light Tree When shading point lies outside the sphere, treat as a disk light spanning the same solid angle. When shading point lies inside the sphere, it behaves like a background light, with estimated outgoing radiance \[L_o=\int f_aL_i\cos\theta_i\mathrm{d}\omega_i=\int f_a\frac{E}{\pi r^2}\cos\theta_i\mathrm{d}\omega_i\approx f_a \frac{E}{r^2}\], with \(f_a\) being the BSDF and \(E\) `measure.energy` in `light_tree.cpp`. The importance calculation for `LIGHT_POINT` is \[L_o=f_a E\cos\theta_i\frac{\cos\theta}{d^2}\]. Consider `min_importance = 0` because maximal incidence angle is \(\pi\), we could substitute \(d^2\) with \(\frac{r^2}{2}\) so the averaged outgoing radiance is \(f_a \frac{E}{r^2}\). This only holds for non-transmissive surface, but should be fine to use in volume. # EEVEE When shading point lies outside the sphere, the sphere light is equivalent to a disk light spanning the same solid angle. The sine of the new half-angle is the tangent of the previous half-angle. When shading point lies inside the sphere, integrating over the cosine-weighted hemisphere gives 1.0. ## Comparison with Cycles The plane is diffuse, the blue sphere has specular component. | Before | |After || |---|--|--|--| |Cycles|EEVEE|Cycles|EEVEE| |![](attachments/5824c494-0645-461a-b193-d74e02f353b8)|![](attachments/d2e85b53-3c2a-4a9f-a3b2-6e11c6083ce0)|![](attachments/a8dcdd8b-c13c-4fdc-808c-2563624549be)|![](attachments/8c3618ef-1ab4-4210-9535-c85e873f1e45)| Pull Request: https://projects.blender.org/blender/blender/pulls/108506
2023-06-20 12:23:05 +02:00
const Transform itfm = klight->itfm;
const float2 uv = map_to_sphere(transform_direction(&itfm, ls->Ng));
/* NOTE: Return barycentric coordinates in the same notation as Embree and OptiX. */
ls->u = uv.y;
ls->v = 1.0f - uv.x - uv.y;
Cycles/EEVEE: change point light to double-sided sphere light for energy preservation and better compatibility with other renderes. Ref: #108505 Point light now behaves the same as a spherical mesh light with the same overall energy (scaling from emission strength to power is \(4\pi^2R^2\)). # Cycles ## Comparison | Mesh Light | This patch | Previous behavior | | -------- | -------- | -------- | | ![mesh_1024](attachments/2900954c-57f8-49c2-b6f3-8fb559b820ac) | ![sphere_1024](attachments/148241ca-9350-48b6-be04-3933e015424c) | ![point_1024](attachments/d9b19d54-2b00-4986-ba8c-c4b28f687f09) | The behavior stays the same when `radius = 0`. | This patch | Previous behavior | | -------- | -------- | | ![sphere_64](attachments/aa05d59a-146a-4f69-b257-5d09a7f41d4e) | ![point_64](attachments/69a743be-bc15-454b-92d8-af02f4e8ab07) | No obvious performance change observed. ## Sampling When shading point lies outside the sphere, sample the spanned solid angle uniformly. When shading point lies inside the sphere, sample spherical direction uniformly when inside volume or the surface is transmissive, otherwise sample cosine-weighted upper hemisphere. ## Light Tree When shading point lies outside the sphere, treat as a disk light spanning the same solid angle. When shading point lies inside the sphere, it behaves like a background light, with estimated outgoing radiance \[L_o=\int f_aL_i\cos\theta_i\mathrm{d}\omega_i=\int f_a\frac{E}{\pi r^2}\cos\theta_i\mathrm{d}\omega_i\approx f_a \frac{E}{r^2}\], with \(f_a\) being the BSDF and \(E\) `measure.energy` in `light_tree.cpp`. The importance calculation for `LIGHT_POINT` is \[L_o=f_a E\cos\theta_i\frac{\cos\theta}{d^2}\]. Consider `min_importance = 0` because maximal incidence angle is \(\pi\), we could substitute \(d^2\) with \(\frac{r^2}{2}\) so the averaged outgoing radiance is \(f_a \frac{E}{r^2}\). This only holds for non-transmissive surface, but should be fine to use in volume. # EEVEE When shading point lies outside the sphere, the sphere light is equivalent to a disk light spanning the same solid angle. The sine of the new half-angle is the tangent of the previous half-angle. When shading point lies inside the sphere, integrating over the cosine-weighted hemisphere gives 1.0. ## Comparison with Cycles The plane is diffuse, the blue sphere has specular component. | Before | |After || |---|--|--|--| |Cycles|EEVEE|Cycles|EEVEE| |![](attachments/5824c494-0645-461a-b193-d74e02f353b8)|![](attachments/d2e85b53-3c2a-4a9f-a3b2-6e11c6083ce0)|![](attachments/a8dcdd8b-c13c-4fdc-808c-2563624549be)|![](attachments/8c3618ef-1ab4-4210-9535-c85e873f1e45)| Pull Request: https://projects.blender.org/blender/blender/pulls/108506
2023-06-20 12:23:05 +02:00
if (ls->t == FLT_MAX) {
ls->pdf = 0.0f;
}
else {
Cycles/EEVEE: change point light to double-sided sphere light for energy preservation and better compatibility with other renderes. Ref: #108505 Point light now behaves the same as a spherical mesh light with the same overall energy (scaling from emission strength to power is \(4\pi^2R^2\)). # Cycles ## Comparison | Mesh Light | This patch | Previous behavior | | -------- | -------- | -------- | | ![mesh_1024](attachments/2900954c-57f8-49c2-b6f3-8fb559b820ac) | ![sphere_1024](attachments/148241ca-9350-48b6-be04-3933e015424c) | ![point_1024](attachments/d9b19d54-2b00-4986-ba8c-c4b28f687f09) | The behavior stays the same when `radius = 0`. | This patch | Previous behavior | | -------- | -------- | | ![sphere_64](attachments/aa05d59a-146a-4f69-b257-5d09a7f41d4e) | ![point_64](attachments/69a743be-bc15-454b-92d8-af02f4e8ab07) | No obvious performance change observed. ## Sampling When shading point lies outside the sphere, sample the spanned solid angle uniformly. When shading point lies inside the sphere, sample spherical direction uniformly when inside volume or the surface is transmissive, otherwise sample cosine-weighted upper hemisphere. ## Light Tree When shading point lies outside the sphere, treat as a disk light spanning the same solid angle. When shading point lies inside the sphere, it behaves like a background light, with estimated outgoing radiance \[L_o=\int f_aL_i\cos\theta_i\mathrm{d}\omega_i=\int f_a\frac{E}{\pi r^2}\cos\theta_i\mathrm{d}\omega_i\approx f_a \frac{E}{r^2}\], with \(f_a\) being the BSDF and \(E\) `measure.energy` in `light_tree.cpp`. The importance calculation for `LIGHT_POINT` is \[L_o=f_a E\cos\theta_i\frac{\cos\theta}{d^2}\]. Consider `min_importance = 0` because maximal incidence angle is \(\pi\), we could substitute \(d^2\) with \(\frac{r^2}{2}\) so the averaged outgoing radiance is \(f_a \frac{E}{r^2}\). This only holds for non-transmissive surface, but should be fine to use in volume. # EEVEE When shading point lies outside the sphere, the sphere light is equivalent to a disk light spanning the same solid angle. The sine of the new half-angle is the tangent of the previous half-angle. When shading point lies inside the sphere, integrating over the cosine-weighted hemisphere gives 1.0. ## Comparison with Cycles The plane is diffuse, the blue sphere has specular component. | Before | |After || |---|--|--|--| |Cycles|EEVEE|Cycles|EEVEE| |![](attachments/5824c494-0645-461a-b193-d74e02f353b8)|![](attachments/d2e85b53-3c2a-4a9f-a3b2-6e11c6083ce0)|![](attachments/a8dcdd8b-c13c-4fdc-808c-2563624549be)|![](attachments/8c3618ef-1ab4-4210-9535-c85e873f1e45)| Pull Request: https://projects.blender.org/blender/blender/pulls/108506
2023-06-20 12:23:05 +02:00
ls->pdf = point_light_pdf(len_squared(ray_P - klight->co), sqr(radius), N, ray_D, path_flag);
}
return true;
}
template<bool in_volume_segment>
ccl_device_forceinline bool point_light_tree_parameters(const ccl_global KernelLight *klight,
const float3 centroid,
const float3 P,
ccl_private float &cos_theta_u,
ccl_private float2 &distance,
ccl_private float3 &point_to_centroid)
{
if (in_volume_segment) {
cos_theta_u = 1.0f; /* Any value in [-1, 1], irrelevant since theta = 0 */
return true;
}
Cycles/EEVEE: change point light to double-sided sphere light for energy preservation and better compatibility with other renderes. Ref: #108505 Point light now behaves the same as a spherical mesh light with the same overall energy (scaling from emission strength to power is \(4\pi^2R^2\)). # Cycles ## Comparison | Mesh Light | This patch | Previous behavior | | -------- | -------- | -------- | | ![mesh_1024](attachments/2900954c-57f8-49c2-b6f3-8fb559b820ac) | ![sphere_1024](attachments/148241ca-9350-48b6-be04-3933e015424c) | ![point_1024](attachments/d9b19d54-2b00-4986-ba8c-c4b28f687f09) | The behavior stays the same when `radius = 0`. | This patch | Previous behavior | | -------- | -------- | | ![sphere_64](attachments/aa05d59a-146a-4f69-b257-5d09a7f41d4e) | ![point_64](attachments/69a743be-bc15-454b-92d8-af02f4e8ab07) | No obvious performance change observed. ## Sampling When shading point lies outside the sphere, sample the spanned solid angle uniformly. When shading point lies inside the sphere, sample spherical direction uniformly when inside volume or the surface is transmissive, otherwise sample cosine-weighted upper hemisphere. ## Light Tree When shading point lies outside the sphere, treat as a disk light spanning the same solid angle. When shading point lies inside the sphere, it behaves like a background light, with estimated outgoing radiance \[L_o=\int f_aL_i\cos\theta_i\mathrm{d}\omega_i=\int f_a\frac{E}{\pi r^2}\cos\theta_i\mathrm{d}\omega_i\approx f_a \frac{E}{r^2}\], with \(f_a\) being the BSDF and \(E\) `measure.energy` in `light_tree.cpp`. The importance calculation for `LIGHT_POINT` is \[L_o=f_a E\cos\theta_i\frac{\cos\theta}{d^2}\]. Consider `min_importance = 0` because maximal incidence angle is \(\pi\), we could substitute \(d^2\) with \(\frac{r^2}{2}\) so the averaged outgoing radiance is \(f_a \frac{E}{r^2}\). This only holds for non-transmissive surface, but should be fine to use in volume. # EEVEE When shading point lies outside the sphere, the sphere light is equivalent to a disk light spanning the same solid angle. The sine of the new half-angle is the tangent of the previous half-angle. When shading point lies inside the sphere, integrating over the cosine-weighted hemisphere gives 1.0. ## Comparison with Cycles The plane is diffuse, the blue sphere has specular component. | Before | |After || |---|--|--|--| |Cycles|EEVEE|Cycles|EEVEE| |![](attachments/5824c494-0645-461a-b193-d74e02f353b8)|![](attachments/d2e85b53-3c2a-4a9f-a3b2-6e11c6083ce0)|![](attachments/a8dcdd8b-c13c-4fdc-808c-2563624549be)|![](attachments/8c3618ef-1ab4-4210-9535-c85e873f1e45)| Pull Request: https://projects.blender.org/blender/blender/pulls/108506
2023-06-20 12:23:05 +02:00
float dist_point_to_centroid;
point_to_centroid = safe_normalize_len(centroid - P, &dist_point_to_centroid);
Cycles/EEVEE: change point light to double-sided sphere light for energy preservation and better compatibility with other renderes. Ref: #108505 Point light now behaves the same as a spherical mesh light with the same overall energy (scaling from emission strength to power is \(4\pi^2R^2\)). # Cycles ## Comparison | Mesh Light | This patch | Previous behavior | | -------- | -------- | -------- | | ![mesh_1024](attachments/2900954c-57f8-49c2-b6f3-8fb559b820ac) | ![sphere_1024](attachments/148241ca-9350-48b6-be04-3933e015424c) | ![point_1024](attachments/d9b19d54-2b00-4986-ba8c-c4b28f687f09) | The behavior stays the same when `radius = 0`. | This patch | Previous behavior | | -------- | -------- | | ![sphere_64](attachments/aa05d59a-146a-4f69-b257-5d09a7f41d4e) | ![point_64](attachments/69a743be-bc15-454b-92d8-af02f4e8ab07) | No obvious performance change observed. ## Sampling When shading point lies outside the sphere, sample the spanned solid angle uniformly. When shading point lies inside the sphere, sample spherical direction uniformly when inside volume or the surface is transmissive, otherwise sample cosine-weighted upper hemisphere. ## Light Tree When shading point lies outside the sphere, treat as a disk light spanning the same solid angle. When shading point lies inside the sphere, it behaves like a background light, with estimated outgoing radiance \[L_o=\int f_aL_i\cos\theta_i\mathrm{d}\omega_i=\int f_a\frac{E}{\pi r^2}\cos\theta_i\mathrm{d}\omega_i\approx f_a \frac{E}{r^2}\], with \(f_a\) being the BSDF and \(E\) `measure.energy` in `light_tree.cpp`. The importance calculation for `LIGHT_POINT` is \[L_o=f_a E\cos\theta_i\frac{\cos\theta}{d^2}\]. Consider `min_importance = 0` because maximal incidence angle is \(\pi\), we could substitute \(d^2\) with \(\frac{r^2}{2}\) so the averaged outgoing radiance is \(f_a \frac{E}{r^2}\). This only holds for non-transmissive surface, but should be fine to use in volume. # EEVEE When shading point lies outside the sphere, the sphere light is equivalent to a disk light spanning the same solid angle. The sine of the new half-angle is the tangent of the previous half-angle. When shading point lies inside the sphere, integrating over the cosine-weighted hemisphere gives 1.0. ## Comparison with Cycles The plane is diffuse, the blue sphere has specular component. | Before | |After || |---|--|--|--| |Cycles|EEVEE|Cycles|EEVEE| |![](attachments/5824c494-0645-461a-b193-d74e02f353b8)|![](attachments/d2e85b53-3c2a-4a9f-a3b2-6e11c6083ce0)|![](attachments/a8dcdd8b-c13c-4fdc-808c-2563624549be)|![](attachments/8c3618ef-1ab4-4210-9535-c85e873f1e45)| Pull Request: https://projects.blender.org/blender/blender/pulls/108506
2023-06-20 12:23:05 +02:00
const float radius = klight->spot.radius;
if (dist_point_to_centroid > radius) {
/* Equivalent to a disk light with the same angular span. */
cos_theta_u = cos_from_sin(radius / dist_point_to_centroid);
distance = dist_point_to_centroid * make_float2(1.0f / cos_theta_u, 1.0f);
}
else {
/* Similar to background light. */
cos_theta_u = -1.0f;
/* HACK: pack radiance scaling in the distance. */
distance = one_float2() * radius / M_SQRT2_F;
}
return true;
}
CCL_NAMESPACE_END