Cycles: replace spot light disk sampling with sphere sampling #109329
|
@ -44,7 +44,7 @@ ccl_device_inline bool point_light_sample(const ccl_global KernelLight *klight,
|
|||
|
||||
ls->P = P + ls->D * ls->t;
|
||||
|
||||
ls->eval_fac = M_1_PI_F * 0.25f * klight->spot.invarea;
|
||||
ls->eval_fac = klight->spot.eval_fac;
|
||||
if (r_sq == 0) {
|
||||
/* Use intensity instead of radiance for point light. */
|
||||
ls->eval_fac /= sqr(ls->t);
|
||||
|
@ -100,7 +100,7 @@ ccl_device_forceinline void point_light_mnee_sample_update(const ccl_global Kern
|
|||
ls->Ng = normalize(ls->P - klight->co);
|
||||
}
|
||||
else {
|
||||
ls->eval_fac = M_1_PI_F * 0.25f * klight->spot.invarea;
|
||||
ls->eval_fac = klight->spot.eval_fac;
|
||||
|
||||
ls->Ng = -ls->D;
|
||||
|
||||
|
@ -136,7 +136,7 @@ ccl_device_inline bool point_light_sample_from_intersection(
|
|||
const uint32_t path_flag,
|
||||
ccl_private LightSample *ccl_restrict ls)
|
||||
{
|
||||
ls->eval_fac = M_1_PI_F * 0.25f * klight->spot.invarea;
|
||||
ls->eval_fac = klight->spot.eval_fac;
|
||||
|
||||
const float radius = klight->spot.radius;
|
||||
|
||||
|
|
|
@ -1353,7 +1353,7 @@ typedef struct KernelSpotLight {
|
|||
packed_float3 scaled_axis_u;
|
||||
float radius;
|
||||
packed_float3 scaled_axis_v;
|
||||
float invarea;
|
||||
float eval_fac;
|
||||
packed_float3 dir;
|
||||
float cos_half_spot_angle;
|
||||
float inv_len_z;
|
||||
|
@ -1361,6 +1361,7 @@ typedef struct KernelSpotLight {
|
|||
float pad[2];
|
||||
} KernelSpotLight;
|
||||
|
||||
/* TODO: maybe rename spot to sphere */
|
||||
/* PointLight is SpotLight with only radius and invarea being used. */
|
||||
|
||||
typedef struct KernelAreaLight {
|
||||
|
|
|
@ -1210,22 +1210,22 @@ void LightManager::device_update_lights(Device *device, DeviceScene *dscene, Sce
|
|||
klights[light_index].strength[1] = light->strength.y;
|
||||
klights[light_index].strength[2] = light->strength.z;
|
||||
|
||||
if (light->light_type == LIGHT_POINT) {
|
||||
if (light->light_type == LIGHT_POINT || light->light_type == LIGHT_SPOT) {
|
||||
shader_id &= ~SHADER_AREA_LIGHT;
|
||||
|
||||
float radius = light->size;
|
||||
/* TODO: `invarea` was used for disk sampling, with the current solid angle sampling this
|
||||
* becomes unnecessary. We could store `eval_fac` instead, but currently it shares the same
|
||||
* #KernelSpotLight type with #LIGHT_SPOT, so keep it know until refactor for spot light. */
|
||||
float invarea = (light->normalize && radius > 0.0f) ? 1.0f / (M_PI_F * radius * radius) :
|
||||
|
||||
float invarea = (light->normalize && radius > 0.0f) ? 1.0f / (M_4PI_F * radius * radius) :
|
||||
1.0f;
|
||||
/* Convert radiant flux to radiance or radiant intensity. */
|
||||
float eval_fac = (radius > 0) ? invarea * M_1_PI_F : 0.25f * M_1_PI_F;
|
||||
|
||||
if (light->use_mis && radius > 0.0f)
|
||||
shader_id |= SHADER_USE_MIS;
|
||||
|
||||
klights[light_index].co = co;
|
||||
klights[light_index].spot.radius = radius;
|
||||
klights[light_index].spot.invarea = invarea;
|
||||
klights[light_index].spot.eval_fac = eval_fac;
|
||||
}
|
||||
else if (light->light_type == LIGHT_DISTANT) {
|
||||
shader_id &= ~SHADER_AREA_LIGHT;
|
||||
|
@ -1306,9 +1306,7 @@ void LightManager::device_update_lights(Device *device, DeviceScene *dscene, Sce
|
|||
klights[light_index].area.tan_half_spread = tan_half_spread;
|
||||
klights[light_index].area.normalize_spread = normalize_spread;
|
||||
}
|
||||
else if (light->light_type == LIGHT_SPOT) {
|
||||
shader_id &= ~SHADER_AREA_LIGHT;
|
||||
|
||||
if (light->light_type == LIGHT_SPOT) {
|
||||
/* Scale axes to accommodate non-uniform scaling. */
|
||||
float3 scaled_axis_u = light->axisu / len_squared(light->axisu);
|
||||
float3 scaled_axis_v = light->axisv / len_squared(light->axisv);
|
||||
|
@ -1316,20 +1314,11 @@ void LightManager::device_update_lights(Device *device, DeviceScene *dscene, Sce
|
|||
/* Keep direction normalized. */
|
||||
float3 dir = safe_normalize_len(light->dir, &len_z);
|
||||
|
||||
float radius = light->size;
|
||||
float invarea = (light->normalize && radius > 0.0f) ? 1.0f / (M_PI_F * radius * radius) :
|
||||
1.0f;
|
||||
float cos_half_spot_angle = cosf(light->spot_angle * 0.5f);
|
||||
float spot_smooth = 1.0f / ((1.0f - cos_half_spot_angle) * light->spot_smooth);
|
||||
|
||||
if (light->use_mis && radius > 0.0f)
|
||||
shader_id |= SHADER_USE_MIS;
|
||||
|
||||
klights[light_index].co = co;
|
||||
klights[light_index].spot.scaled_axis_u = scaled_axis_u;
|
||||
klights[light_index].spot.radius = radius;
|
||||
klights[light_index].spot.scaled_axis_v = scaled_axis_v;
|
||||
klights[light_index].spot.invarea = invarea;
|
||||
klights[light_index].spot.dir = dir;
|
||||
klights[light_index].spot.cos_half_spot_angle = cos_half_spot_angle;
|
||||
klights[light_index].spot.inv_len_z = 1.0f / len_z;
|
||||
|
|
Loading…
Reference in New Issue