Lights: Option to use old point light falloff #117832

Merged
Brecht Van Lommel merged 14 commits from brecht/blender:point-sphere-light into blender-v4.1-release 2024-02-07 19:07:23 +01:00
5 changed files with 26 additions and 15 deletions
Showing only changes of commit 244be1637b - Show all commits

View File

@ -87,12 +87,13 @@ uniform depth2DArrayShadow shadowCascadeTexture;
* \{ */
/* Type. Consistent with DNA `Light::type`, except for `OMNI_DISK`/`SPOT_DISK` and `AREA_ELLIPSE`,
* which are reinterpreted from `light.spot_type` and `light.area_type`. */
#define SUN 1.0
* which are reinterpreted from `light.mode` and `light.area_type`. The decimal numbers are chosen
* so that they can be exactly represented by float, and guarantee an increasing sequence. */
#define OMNI_SPHERE 0.0
#define OMNI_DISK 0.5
#define SUN 1.0
#define SPOT_SPHERE 2.0
#define SPOT_DISK 2.5
@ -315,6 +316,11 @@ float light_visibility(LightData ld, vec3 P, vec4 l_vector)
return light_shadowing(ld, P, l_atten);
}
bool is_sphere_light(float type)
{
return type == OMNI_SPHERE || type == SPOT_SPHERE;
}
float light_diffuse(LightData ld, vec3 N, vec3 V, vec4 l_vector)
{
if (ld.l_type == AREA_RECT) {
@ -334,7 +340,7 @@ float light_diffuse(LightData ld, vec3 N, vec3 V, vec4 l_vector)
return ltc_evaluate_disk(N, V, mat3(1.0), points);
}
else if (ld.l_type == OMNI_SPHERE) {
else if (is_sphere_light(ld.l_type)) {
if (l_vector.w < ld.l_radius) {
/* Inside, treat as hemispherical light. */
return 1.0;
@ -371,7 +377,7 @@ float light_specular(LightData ld, vec4 ltc_mat, vec3 N, vec3 V, vec4 l_vector)
return ltc_evaluate_quad(corners, vec3(0.0, 0.0, 1.0));
}
else if ((ld.l_type == OMNI_SPHERE || ld.l_type == SPOT_SPHERE) && l_vector.w < ld.l_radius) {
else if (is_sphere_light(ld.l_type) && l_vector.w < ld.l_radius) {
/* Inside the sphere light, integrate over the hemisphere. */
return 1.0;
}
@ -380,7 +386,7 @@ float light_specular(LightData ld, vec4 ltc_mat, vec3 N, vec3 V, vec4 l_vector)
float radius_x = is_ellipse ? ld.l_sizex : ld.l_radius;
float radius_y = is_ellipse ? ld.l_sizey : ld.l_radius;
if (ld.l_type == OMNI_SPHERE || ld.l_type == SPOT_SPHERE) {
if (is_sphere_light(ld.l_type)) {
/* The sine of the half-angle spanned by a sphere light is equal to the tangent of the
* half-angle spanned by a disk light with the same radius. */
radius_x *= inversesqrt(1.0 - sqr(radius_x / l_vector.w));

View File

@ -24,16 +24,16 @@ namespace blender::eevee {
static eLightType to_light_type(short blender_light_type,
short blender_area_type,
bool use_falloff)
bool use_soft_falloff)
{
switch (blender_light_type) {
default:
case LA_LOCAL:
return use_falloff ? LIGHT_OMNI_DISK : LIGHT_OMNI_SPHERE;
return use_soft_falloff ? LIGHT_OMNI_DISK : LIGHT_OMNI_SPHERE;
case LA_SUN:
return LIGHT_SUN;
case LA_SPOT:
return use_falloff ? LIGHT_SPOT_DISK : LIGHT_SPOT_SPHERE;
return use_soft_falloff ? LIGHT_SPOT_DISK : LIGHT_SPOT_SPHERE;
case LA_AREA:
return ELEM(blender_area_type, LA_AREA_DISK, LA_AREA_ELLIPSE) ? LIGHT_ELLIPSE : LIGHT_RECT;
}

View File

@ -740,6 +740,11 @@ static inline bool is_spot_light(eLightType type)
return type == LIGHT_SPOT_SPHERE || type == LIGHT_SPOT_DISK;
}
static inline bool is_sphere_light(eLightType type)
{
return type == LIGHT_SPOT_SPHERE || type == LIGHT_OMNI_SPHERE;
}
static inline bool is_sun_light(eLightType type)
{
return type < LIGHT_OMNI_SPHERE;

View File

@ -183,7 +183,7 @@ float light_sphere_disk_radius(float sphere_radius, float distance_to_sphere)
float light_ltc(
sampler2DArray utility_tx, LightData light, vec3 N, vec3 V, LightVector lv, vec4 ltc_mat)
{
if (light.type == LIGHT_OMNI_SPHERE && lv.dist < light._radius) {
if (is_sphere_light(light.type) && lv.dist < light._radius) {
weizhen marked this conversation as resolved Outdated

You need to account for the spot case here.

You need to account for the spot case here.
/* Inside the sphere light, integrate over the hemisphere. */
return 1.0;
}
@ -214,16 +214,16 @@ float light_ltc(
}
vec2 size;
if (light.type == LIGHT_OMNI_SPHERE) {
/* Sphere. */
if (is_sphere_light(light.type)) {
/* Spherical omni or spot light. */
size = vec2(light_sphere_disk_radius(light._radius, lv.dist));
}
else if (light.type == LIGHT_OMNI_DISK) {
else if (light.type == LIGHT_OMNI_DISK || light.type == LIGHT_SPOT_DISK) {
/* View direction-aligned disk. */
size = vec2(light._radius);
}
else {
/* Elliptical area light. */
/* Sun light and elliptical area light. */
size = vec2(light._area_size_x, light._area_size_y);
}

View File

@ -331,7 +331,7 @@ ShadowRayPunctual shadow_ray_generate_punctual(LightData light,
/* Disk rotated towards light vector. */
vec3 right, up;
make_orthonormal_basis(L, right, up);
if (light.type == LIGHT_OMNI_SPHERE || light.type == LIGHT_SPOT_SPHERE) {
if (is_sphere_light(light.type)) {
/* FIXME(weizhen): this is not well-defined when `dist < light._radius`. */
random_2d *= light_sphere_disk_radius(light._radius, dist);
}