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:
parent
fa4def46c8
commit
ab12d2836b
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user