* Split light types into own files, move light type specific code from light tree and MNEE. * Move flat light distribution code into own kernel file and host side building function, in preparation of light tree addition. Add light/sample.h as main entry point to kernel light sampling. * Better separate calculation of pdf for selecting a light, and pdf for sampling a point on the light. The selection pdf is now also stored in LightSampling for MNEE to correctly recalculate the full pdf when the shading position changes but the point on the light remains fixed. * Improvement to kernel light storage, using packed_float3, better variable names, etc. Includes contributions by Brecht Van Lommel and Weizhen Huang. Ref T77889
111 lines
3.0 KiB
C
111 lines
3.0 KiB
C
/* 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
|