Lights: Option to use old point light falloff #117832
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
You need to account for the spot case here.