Cycles: add texture to sun light

Using area-preserving mapping from cone to disk. Has somewhat distortion
near 90°.
The texture rotates with the transformation of the light object, can
have negative and non-uniform scaling.

Pull Request: https://projects.blender.org/blender/blender/pulls/109842
This commit is contained in:
Weizhen Huang 2023-07-10 12:20:47 +02:00 committed by Weizhen Huang
parent fa4def46c8
commit ab12d2836b
4 changed files with 28 additions and 4 deletions

@ -10,6 +10,27 @@
CCL_NAMESPACE_BEGIN
ccl_device_inline void distant_light_uv(const ccl_global KernelLight *klight,
const float3 D,
ccl_private float *u,
ccl_private float *v)
{
/* Map direction (x, y, z) to disk [-0.5, 0.5]^2:
* r^2 = (1 - z) / (1 - cos(klight->distant.angle))
* u_ = 0.5 * x * r / sin_angle(D, -klight->co)
* v_ = 0.5 * y * r / sin_angle(D, -klight->co) */
const float fac = klight->distant.half_inv_sin_half_angle / len(D - klight->co);
/* Get u axis and v axis. */
const Transform itfm = klight->itfm;
const float u_ = dot(D, float4_to_float3(itfm.x)) * fac;
const float v_ = dot(D, float4_to_float3(itfm.y)) * fac;
/* NOTE: Return barycentric coordinates in the same notation as Embree and OptiX. */
*u = v_ + 0.5f;
*v = -u_ - v_;
}
ccl_device_inline bool distant_light_sample(const ccl_global KernelLight *klight,
const float2 rand,
ccl_private LightSample *ls)
@ -24,6 +45,8 @@ ccl_device_inline bool distant_light_sample(const ccl_global KernelLight *klight
ls->eval_fac = klight->distant.eval_fac;
distant_light_uv(klight, ls->D, &ls->u, &ls->v);
return true;
}
@ -92,9 +115,6 @@ ccl_device bool distant_light_sample_from_intersection(KernelGlobals kg,
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;
@ -104,6 +124,8 @@ ccl_device bool distant_light_sample_from_intersection(KernelGlobals kg,
ls->pdf = klight->distant.pdf;
ls->eval_fac = klight->distant.eval_fac;
distant_light_uv(klight, ray_D, &ls->u, &ls->v);
return true;
}

@ -462,7 +462,6 @@ ccl_device bool light_sample_from_intersection(KernelGlobals kg,
ls->object = isect->object;
ls->prim = isect->prim;
ls->lamp = lamp;
/* todo: missing texture coordinates */
ls->t = isect->t;
ls->P = ray_P + ray_D * ls->t;
ls->D = ray_D;

@ -1379,8 +1379,10 @@ typedef struct KernelAreaLight {
typedef struct KernelDistantLight {
float angle;
float one_minus_cosangle;
float half_inv_sin_half_angle;
float pdf;
float eval_fac;
float pad[3];
} KernelDistantLight;
typedef struct KernelLight {

@ -1253,6 +1253,7 @@ void LightManager::device_update_lights(Device *device, DeviceScene *dscene, Sce
klights[light_index].distant.eval_fac = (light->normalize && angle > 0) ?
M_1_PI_F / sqr(sinf(angle)) :
1.0f;
klights[light_index].distant.half_inv_sin_half_angle = 0.5f / sinf(0.5f * angle);
}
else if (light->light_type == LIGHT_BACKGROUND) {
uint visibility = scene->background->get_visibility();