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. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs