Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/kernel/light/distant.h
- This file was added.
| /* SPDX-License-Identifier: Apache-2.0 | |||||
| * Copyright 2011-2022 Blender Foundation */ | |||||
| #pragma once | |||||
| #include "kernel/geom/geom.h" | |||||
| #include "kernel/light/common.h" | |||||
| CCL_NAMESPACE_BEGIN | |||||
| ccl_device_inline bool distant_light_sample(const ccl_global KernelLight *klight, | |||||
| const float randu, | |||||
| const float randv, | |||||
| ccl_private LightSample *ls) | |||||
| { | |||||
| /* distant light */ | |||||
| float3 lightD = klight->co; | |||||
| float3 D = lightD; | |||||
| float radius = klight->distant.radius; | |||||
| float invarea = klight->distant.invarea; | |||||
| if (radius > 0.0f) { | |||||
| D = normalize(D + disk_light_sample(D, randu, randv) * radius); | |||||
| } | |||||
| ls->P = D; | |||||
| ls->Ng = D; | |||||
| ls->D = -D; | |||||
| ls->t = FLT_MAX; | |||||
| float costheta = dot(lightD, D); | |||||
| ls->pdf = invarea / (costheta * costheta * costheta); | |||||
| ls->eval_fac = ls->pdf; | |||||
| return true; | |||||
| } | |||||
| ccl_device bool distant_light_sample_from_intersection(KernelGlobals kg, | |||||
| const float3 ray_D, | |||||
| const int lamp, | |||||
| ccl_private LightSample *ccl_restrict ls) | |||||
| { | |||||
| ccl_global const KernelLight *klight = &kernel_data_fetch(lights, lamp); | |||||
| const int shader = klight->shader_id; | |||||
| const float radius = klight->distant.radius; | |||||
| const LightType type = (LightType)klight->type; | |||||
| if (type != LIGHT_DISTANT) { | |||||
| return false; | |||||
| } | |||||
| if (!(shader & SHADER_USE_MIS)) { | |||||
| return false; | |||||
| } | |||||
| if (radius == 0.0f) { | |||||
| return false; | |||||
| } | |||||
| /* a distant light is infinitely far away, but equivalent to a disk | |||||
| * shaped light exactly 1 unit away from the current shading point. | |||||
| * | |||||
| * radius t^2/cos(theta) | |||||
| * <----------> t = sqrt(1^2 + tan(theta)^2) | |||||
| * tan(th) area = radius*radius*pi | |||||
| * <-----> | |||||
| * \ | (1 + tan(theta)^2)/cos(theta) | |||||
| * \ | (1 + tan(acos(cos(theta)))^2)/cos(theta) | |||||
| * t \th| 1 simplifies to | |||||
| * \-| 1/(cos(theta)^3) | |||||
| * \| magic! | |||||
| * P | |||||
| */ | |||||
| float3 lightD = klight->co; | |||||
| float costheta = dot(-lightD, ray_D); | |||||
| float cosangle = klight->distant.cosangle; | |||||
| /* Workaround to prevent a hang in the classroom scene with AMD HIP drivers 22.10, | |||||
| * Remove when a compiler fix is available. */ | |||||
| #ifdef __HIP__ | |||||
| ls->shader = klight->shader_id; | |||||
| #endif | |||||
| if (costheta < cosangle) | |||||
| return false; | |||||
| ls->type = type; | |||||
| #ifndef __HIP__ | |||||
| ls->shader = klight->shader_id; | |||||
| #endif | |||||
| ls->object = PRIM_NONE; | |||||
| ls->prim = PRIM_NONE; | |||||
| ls->lamp = lamp; | |||||
| /* todo: missing texture coordinates */ | |||||
| ls->u = 0.0f; | |||||
| ls->v = 0.0f; | |||||
| ls->t = FLT_MAX; | |||||
| ls->P = -ray_D; | |||||
| ls->Ng = -ray_D; | |||||
| ls->D = ray_D; | |||||
| ls->group = lamp_lightgroup(kg, lamp); | |||||
| /* compute pdf */ | |||||
| float invarea = klight->distant.invarea; | |||||
| ls->pdf = invarea / (costheta * costheta * costheta); | |||||
| ls->eval_fac = ls->pdf; | |||||
| return true; | |||||
| } | |||||
| CCL_NAMESPACE_END | |||||