[Bf-blender-cvs] [e028662f78b] master: Cycles: store axis and length of an area light instead of their product
Weizhen Huang
noreply at git.blender.org
Fri Dec 2 15:26:20 CET 2022
Commit: e028662f78bbbd642fb636a8d466c182a8e2841c
Author: Weizhen Huang
Date: Fri Dec 2 15:21:57 2022 +0100
Branches: master
https://developer.blender.org/rBe028662f78bbbd642fb636a8d466c182a8e2841c
Cycles: store axis and length of an area light instead of their product
===================================================================
M intern/cycles/kernel/light/area.h
M intern/cycles/kernel/light/background.h
M intern/cycles/kernel/types.h
M intern/cycles/scene/light.cpp
M intern/cycles/util/math_intersect.h
===================================================================
diff --git a/intern/cycles/kernel/light/area.h b/intern/cycles/kernel/light/area.h
index 212631d363d..db8faf6ec10 100644
--- a/intern/cycles/kernel/light/area.h
+++ b/intern/cycles/kernel/light/area.h
@@ -15,18 +15,19 @@ CCL_NAMESPACE_BEGIN
* NOTE: light_p is modified when sample_coord is true. */
ccl_device_inline float area_light_rect_sample(float3 P,
ccl_private float3 *light_p,
- float3 extentu,
- float3 extentv,
+ const float3 axis_u,
+ const float len_u,
+ const float3 axis_v,
+ const float len_v,
float randu,
float randv,
bool sample_coord)
{
/* In our name system we're using P for the center, which is o in the paper. */
- float3 corner = *light_p - extentu * 0.5f - extentv * 0.5f;
- float extentu_len, extentv_len;
+ float3 corner = *light_p - axis_u * len_u * 0.5f - axis_v * len_v * 0.5f;
/* Compute local reference system R. */
- float3 x = normalize_len(extentu, &extentu_len);
- float3 y = normalize_len(extentv, &extentv_len);
+ float3 x = axis_u;
+ float3 y = axis_v;
float3 z = cross(x, y);
/* Compute rectangle coords in local reference system. */
float3 dir = corner - P;
@@ -38,8 +39,8 @@ ccl_device_inline float area_light_rect_sample(float3 P,
}
float x0 = dot(dir, x);
float y0 = dot(dir, y);
- float x1 = x0 + extentu_len;
- float y1 = y0 + extentv_len;
+ float x1 = x0 + len_u;
+ float y1 = y0 + len_v;
/* Compute internal angles (gamma_i). */
float4 diff = make_float4(x0, y1, x1, y0) - make_float4(x1, y0, x0, y1);
float4 nz = make_float4(y0, x1, y1, x0) * diff;
@@ -106,8 +107,10 @@ ccl_device float area_light_spread_attenuation(const float3 D,
ccl_device bool area_light_spread_clamp_area_light(const float3 P,
const float3 lightNg,
ccl_private float3 *lightP,
- ccl_private float3 *extentu,
- ccl_private float3 *extentv,
+ const float3 axis_u,
+ ccl_private float *len_u,
+ const float3 axis_v,
+ ccl_private float *len_v,
const float tan_spread)
{
/* Closest point in area light plane and distance to that plane. */
@@ -117,22 +120,16 @@ ccl_device bool area_light_spread_clamp_area_light(const float3 P,
/* Radius of circle on area light that actually affects the shading point. */
const float radius = t / tan_spread;
- /* TODO: would be faster to store as normalized vector + length, also in area_light_rect_sample.
- */
- float len_u, len_v;
- const float3 u = normalize_len(*extentu, &len_u);
- const float3 v = normalize_len(*extentv, &len_v);
-
/* Local uv coordinates of closest point. */
- const float closest_u = dot(u, closest_P - *lightP);
- const float closest_v = dot(v, closest_P - *lightP);
+ const float closest_u = dot(axis_u, closest_P - *lightP);
+ const float closest_v = dot(axis_v, closest_P - *lightP);
/* Compute rectangle encompassing the circle that affects the shading point,
* clamped to the bounds of the area light. */
- const float min_u = max(closest_u - radius, -len_u * 0.5f);
- const float max_u = min(closest_u + radius, len_u * 0.5f);
- const float min_v = max(closest_v - radius, -len_v * 0.5f);
- const float max_v = min(closest_v + radius, len_v * 0.5f);
+ const float min_u = max(closest_u - radius, -*len_u * 0.5f);
+ const float max_u = min(closest_u + radius, *len_u * 0.5f);
+ const float min_v = max(closest_v - radius, -*len_v * 0.5f);
+ const float max_v = min(closest_v + radius, *len_v * 0.5f);
/* Skip if rectangle is empty. */
if (min_u >= max_u || min_v >= max_v) {
@@ -143,12 +140,10 @@ ccl_device bool area_light_spread_clamp_area_light(const float3 P,
* uv coordinates. */
const float new_center_u = 0.5f * (min_u + max_u);
const float new_center_v = 0.5f * (min_v + max_v);
- const float new_len_u = max_u - min_u;
- const float new_len_v = max_v - min_v;
+ *len_u = max_u - min_u;
+ *len_v = max_v - min_v;
- *lightP = *lightP + new_center_u * u + new_center_v * v;
- *extentu = u * new_len_u;
- *extentv = v * new_len_v;
+ *lightP = *lightP + new_center_u * axis_u + new_center_v * axis_v;
return true;
}
@@ -164,8 +159,10 @@ ccl_device_inline bool area_light_sample(const ccl_global KernelLight *klight,
{
ls->P = klight->co;
- float3 extentu = klight->area.extentu;
- float3 extentv = klight->area.extentv;
+ const float3 axis_u = klight->area.axis_u;
+ const float3 axis_v = klight->area.axis_v;
+ const float len_u = klight->area.len_u;
+ const float len_v = klight->area.len_v;
float3 Ng = klight->area.dir;
float invarea = fabsf(klight->area.invarea);
bool is_round = (klight->area.invarea < 0.0f);
@@ -179,30 +176,36 @@ ccl_device_inline bool area_light_sample(const ccl_global KernelLight *klight,
float3 inplane;
if (is_round || in_volume_segment) {
- inplane = ellipse_sample(extentu * 0.5f, extentv * 0.5f, randu, randv);
+ inplane = ellipse_sample(axis_u * len_u * 0.5f, axis_v * len_v * 0.5f, randu, randv);
ls->P += inplane;
ls->pdf = invarea;
}
else {
inplane = ls->P;
- float3 sample_extentu = extentu;
- float3 sample_extentv = extentv;
+ float sample_len_u = len_u;
+ float sample_len_v = len_v;
if (!in_volume_segment && klight->area.tan_spread > 0.0f) {
- if (!area_light_spread_clamp_area_light(
- P, Ng, &ls->P, &sample_extentu, &sample_extentv, klight->area.tan_spread)) {
+ if (!area_light_spread_clamp_area_light(P,
+ Ng,
+ &ls->P,
+ axis_u,
+ &sample_len_u,
+ axis_v,
+ &sample_len_v,
+ klight->area.tan_spread)) {
return false;
}
}
ls->pdf = area_light_rect_sample(
- P, &ls->P, sample_extentu, sample_extentv, randu, randv, true);
+ P, &ls->P, axis_u, sample_len_u, axis_v, sample_len_v, randu, randv, true);
inplane = ls->P - inplane;
}
- const float light_u = dot(inplane, extentu) * (1.0f / dot(extentu, extentu));
- const float light_v = dot(inplane, extentv) * (1.0f / dot(extentv, extentv));
+ const float light_u = dot(inplane, axis_u) / len_u;
+ const float light_v = dot(inplane, axis_v) / len_v;
/* NOTE: Return barycentric coordinates in the same notation as Embree and OptiX. */
ls->u = light_v + 0.5f;
@@ -254,8 +257,8 @@ ccl_device_inline bool area_light_intersect(const ccl_global KernelLight *klight
return false;
}
- const float3 extentu = klight->area.extentu;
- const float3 extentv = klight->area.extentv;
+ const float3 inv_extent_u = klight->area.axis_u / klight->area.len_u;
+ const float3 inv_extent_v = klight->area.axis_v / klight->area.len_v;
const float3 Ng = klight->area.dir;
/* One sided. */
@@ -266,8 +269,19 @@ ccl_device_inline bool area_light_intersect(const ccl_global KernelLight *klight
const float3 light_P = klight->co;
float3 P;
- return ray_quad_intersect(
- ray->P, ray->D, ray->tmin, ray->tmax, light_P, extentu, extentv, Ng, &P, t, u, v, is_round);
+ return ray_quad_intersect(ray->P,
+ ray->D,
+ ray->tmin,
+ ray->tmax,
+ light_P,
+ inv_extent_u,
+ inv_extent_v,
+ Ng,
+ &P,
+ t,
+ u,
+ v,
+ is_round);
}
ccl_device_inline bool area_light_sample_from_intersection(
@@ -281,8 +295,6 @@ ccl_device_inline bool area_light_sample_from_intersection(
/* area light */
float invarea = fabsf(klight->area.invarea);
- float3 extentu = klight->area.extentu;
- float3 extentv = klight->area.extentv;
float3 Ng = klight->area.dir;
float3 light_P = klight->co;
@@ -296,17 +308,26 @@ ccl_device_inline bool area_light_sample_from_intersection(
ls->pdf = invarea * lamp_light_pdf(Ng, -ray_D, ls->t);
}
else {
- float3 sample_extentu = extentu;
- float3 sample_extentv = extentv;
+ const float3 axis_u = klight->area.axis_u;
+ const float3 axis_v = klight->area.axis_v;
+ float sample_len_u = klight->area.len_u;
+ float sample_len_v = klight->area.len_v;
if (klight->area.tan_spread > 0.0f) {
- if (!area_light_spread_clamp_area_light(
- ray_P, Ng, &light_P, &sample_extentu, &sample_extentv, klight->area.tan_spread)) {
+ if (!area_light_spread_clamp_area_light(ray_P,
+ Ng,
+ &light_P,
+ axis_u,
+ &sample_len_u,
+ axis_v,
+ &sample_len_v,
+ klight->area.tan_spread)) {
return false;
}
}
- ls->pdf = area_light_rect_sample(ray_P, &light_P, sample_extentu, sample_extentv, 0, 0, false);
+ ls->pdf = area_light_rect_sample(
+ ray_P, &light_P, axis_u, sample_l
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list