Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/kernel/light/area.h
| Show First 20 Lines • Show All 85 Lines • ▼ Show 20 Lines | ccl_device_inline float area_light_rect_sample(float3 P, | ||||
| else | else | ||||
| return 0.0f; | return 0.0f; | ||||
| } | } | ||||
| /* Light spread. */ | /* Light spread. */ | ||||
| ccl_device float area_light_spread_attenuation(const float3 D, | ccl_device float area_light_spread_attenuation(const float3 D, | ||||
| const float3 lightNg, | const float3 lightNg, | ||||
| const float tan_spread, | const float cot_half_spread, | ||||
| const float normalize_spread) | const float normalize_spread) | ||||
| { | { | ||||
| /* Model a soft-box grid, computing the ratio of light not hidden by the | /* Model a soft-box grid, computing the ratio of light not hidden by the | ||||
| * slats of the grid at a given angle. (see D10594). */ | * slats of the grid at a given angle. (see D10594). */ | ||||
| const float cos_a = -dot(D, lightNg); | const float cos_a = -dot(D, lightNg); | ||||
| const float sin_a = safe_sqrtf(1.0f - sqr(cos_a)); | const float sin_a = safe_sqrtf(1.0f - sqr(cos_a)); | ||||
| const float tan_a = sin_a / cos_a; | const float tan_a = sin_a / cos_a; | ||||
| return max((1.0f - (tan_spread * tan_a)) * normalize_spread, 0.0f); | return max((1.0f - (cot_half_spread * tan_a)) * normalize_spread, 0.0f); | ||||
| } | } | ||||
| /* Compute subset of area light that actually has an influence on the shading point, to | /* Compute subset of area light that actually has an influence on the shading point, to | ||||
| * reduce noise with low spread. */ | * reduce noise with low spread. */ | ||||
| ccl_device bool area_light_spread_clamp_area_light(const float3 P, | ccl_device bool area_light_spread_clamp_area_light(const float3 P, | ||||
| const float3 lightNg, | const float3 lightNg, | ||||
| ccl_private float3 *lightP, | ccl_private float3 *lightP, | ||||
| const float3 axis_u, | const float3 axis_u, | ||||
| ccl_private float *len_u, | ccl_private float *len_u, | ||||
| const float3 axis_v, | const float3 axis_v, | ||||
| ccl_private float *len_v, | ccl_private float *len_v, | ||||
| const float tan_spread) | const float cot_half_spread) | ||||
| { | { | ||||
| /* Closest point in area light plane and distance to that plane. */ | /* Closest point in area light plane and distance to that plane. */ | ||||
| const float3 closest_P = P - dot(lightNg, P - *lightP) * lightNg; | const float3 closest_P = P - dot(lightNg, P - *lightP) * lightNg; | ||||
| const float t = len(closest_P - P); | const float t = len(closest_P - P); | ||||
| /* Radius of circle on area light that actually affects the shading point. */ | /* Radius of circle on area light that actually affects the shading point. */ | ||||
| const float radius = t / tan_spread; | const float radius = t / cot_half_spread; | ||||
| /* Local uv coordinates of closest point. */ | /* Local uv coordinates of closest point. */ | ||||
| const float closest_u = dot(axis_u, closest_P - *lightP); | const float closest_u = dot(axis_u, closest_P - *lightP); | ||||
| const float closest_v = dot(axis_v, closest_P - *lightP); | const float closest_v = dot(axis_v, closest_P - *lightP); | ||||
| /* Compute rectangle encompassing the circle that affects the shading point, | /* Compute rectangle encompassing the circle that affects the shading point, | ||||
| * clamped to the bounds of the area light. */ | * clamped to the bounds of the area light. */ | ||||
| const float min_u = max(closest_u - radius, -*len_u * 0.5f); | const float min_u = max(closest_u - radius, -*len_u * 0.5f); | ||||
| ▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | if (is_round || in_volume_segment) { | ||||
| ls->pdf = invarea; | ls->pdf = invarea; | ||||
| } | } | ||||
| else { | else { | ||||
| inplane = ls->P; | inplane = ls->P; | ||||
| float sample_len_u = len_u; | float sample_len_u = len_u; | ||||
| float sample_len_v = len_v; | float sample_len_v = len_v; | ||||
| if (!in_volume_segment && klight->area.tan_spread > 0.0f) { | if (!in_volume_segment && klight->area.cot_half_spread > 0.0f) { | ||||
| if (!area_light_spread_clamp_area_light(P, | if (!area_light_spread_clamp_area_light(P, | ||||
| Ng, | Ng, | ||||
| &ls->P, | &ls->P, | ||||
| axis_u, | axis_u, | ||||
| &sample_len_u, | &sample_len_u, | ||||
| axis_v, | axis_v, | ||||
| &sample_len_v, | &sample_len_v, | ||||
| klight->area.tan_spread)) { | klight->area.cot_half_spread)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| ls->pdf = area_light_rect_sample( | ls->pdf = area_light_rect_sample( | ||||
| P, &ls->P, axis_u, sample_len_u, axis_v, sample_len_v, randu, randv, true); | P, &ls->P, axis_u, sample_len_u, axis_v, sample_len_v, randu, randv, true); | ||||
| inplane = ls->P - inplane; | inplane = ls->P - inplane; | ||||
| } | } | ||||
| const float light_u = dot(inplane, axis_u) / len_u; | const float light_u = dot(inplane, axis_u) / len_u; | ||||
| const float light_v = dot(inplane, axis_v) / len_v; | const float light_v = dot(inplane, axis_v) / len_v; | ||||
| /* NOTE: Return barycentric coordinates in the same notation as Embree and OptiX. */ | /* NOTE: Return barycentric coordinates in the same notation as Embree and OptiX. */ | ||||
| ls->u = light_v + 0.5f; | ls->u = light_v + 0.5f; | ||||
| ls->v = -light_u - light_v; | ls->v = -light_u - light_v; | ||||
| ls->Ng = Ng; | ls->Ng = Ng; | ||||
| ls->D = normalize_len(ls->P - P, &ls->t); | ls->D = normalize_len(ls->P - P, &ls->t); | ||||
| ls->eval_fac = 0.25f * invarea; | ls->eval_fac = 0.25f * invarea; | ||||
| if (klight->area.tan_spread > 0.0f) { | if (klight->area.cot_half_spread > 0.0f) { | ||||
| /* Area Light spread angle attenuation */ | /* Area Light spread angle attenuation */ | ||||
| ls->eval_fac *= area_light_spread_attenuation( | ls->eval_fac *= area_light_spread_attenuation( | ||||
| ls->D, ls->Ng, klight->area.tan_spread, klight->area.normalize_spread); | ls->D, ls->Ng, klight->area.cot_half_spread, klight->area.normalize_spread); | ||||
| } | } | ||||
| if (is_round) { | if (is_round) { | ||||
| ls->pdf *= lamp_light_pdf(Ng, -ls->D, ls->t); | ls->pdf *= lamp_light_pdf(Ng, -ls->D, ls->t); | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| ccl_device_forceinline void area_light_update_position(const ccl_global KernelLight *klight, | ccl_device_forceinline void area_light_update_position(const ccl_global KernelLight *klight, | ||||
| ccl_private LightSample *ls, | ccl_private LightSample *ls, | ||||
| const float3 P) | const float3 P) | ||||
| { | { | ||||
| const float invarea = fabsf(klight->area.invarea); | const float invarea = fabsf(klight->area.invarea); | ||||
| ls->D = normalize_len(ls->P - P, &ls->t); | ls->D = normalize_len(ls->P - P, &ls->t); | ||||
| ls->pdf = invarea; | ls->pdf = invarea; | ||||
| if (klight->area.tan_spread > 0.f) { | if (klight->area.cot_half_spread > 0.f) { | ||||
| ls->eval_fac = 0.25f * invarea; | ls->eval_fac = 0.25f * invarea; | ||||
| ls->eval_fac *= area_light_spread_attenuation( | ls->eval_fac *= area_light_spread_attenuation( | ||||
| ls->D, ls->Ng, klight->area.tan_spread, klight->area.normalize_spread); | ls->D, ls->Ng, klight->area.cot_half_spread, klight->area.normalize_spread); | ||||
| } | } | ||||
| } | } | ||||
| ccl_device_inline bool area_light_intersect(const ccl_global KernelLight *klight, | ccl_device_inline bool area_light_intersect(const ccl_global KernelLight *klight, | ||||
| const ccl_private Ray *ccl_restrict ray, | const ccl_private Ray *ccl_restrict ray, | ||||
| ccl_private float *t, | ccl_private float *t, | ||||
| ccl_private float *u, | ccl_private float *u, | ||||
| ccl_private float *v) | ccl_private float *v) | ||||
| ▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | if (is_round) { | ||||
| ls->pdf = invarea * lamp_light_pdf(Ng, -ray_D, ls->t); | ls->pdf = invarea * lamp_light_pdf(Ng, -ray_D, ls->t); | ||||
| } | } | ||||
| else { | else { | ||||
| const float3 axis_u = klight->area.axis_u; | const float3 axis_u = klight->area.axis_u; | ||||
| const float3 axis_v = klight->area.axis_v; | const float3 axis_v = klight->area.axis_v; | ||||
| float sample_len_u = klight->area.len_u; | float sample_len_u = klight->area.len_u; | ||||
| float sample_len_v = klight->area.len_v; | float sample_len_v = klight->area.len_v; | ||||
| if (klight->area.tan_spread > 0.0f) { | if (klight->area.cot_half_spread > 0.0f) { | ||||
| if (!area_light_spread_clamp_area_light(ray_P, | if (!area_light_spread_clamp_area_light(ray_P, | ||||
| Ng, | Ng, | ||||
| &light_P, | &light_P, | ||||
| axis_u, | axis_u, | ||||
| &sample_len_u, | &sample_len_u, | ||||
| axis_v, | axis_v, | ||||
| &sample_len_v, | &sample_len_v, | ||||
| klight->area.tan_spread)) { | klight->area.cot_half_spread)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| ls->pdf = area_light_rect_sample( | ls->pdf = area_light_rect_sample( | ||||
| ray_P, &light_P, axis_u, sample_len_u, axis_v, sample_len_v, 0, 0, false); | ray_P, &light_P, axis_u, sample_len_u, axis_v, sample_len_v, 0, 0, false); | ||||
| } | } | ||||
| ls->eval_fac = 0.25f * invarea; | ls->eval_fac = 0.25f * invarea; | ||||
| if (klight->area.tan_spread > 0.0f) { | if (klight->area.cot_half_spread > 0.0f) { | ||||
| /* Area Light spread angle attenuation */ | /* Area Light spread angle attenuation */ | ||||
| ls->eval_fac *= area_light_spread_attenuation( | ls->eval_fac *= area_light_spread_attenuation( | ||||
| ls->D, ls->Ng, klight->area.tan_spread, klight->area.normalize_spread); | ls->D, ls->Ng, klight->area.cot_half_spread, klight->area.normalize_spread); | ||||
| if (ls->eval_fac == 0.0f) { | if (ls->eval_fac == 0.0f) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| Show All 40 Lines | |||||