166
145
return pdf * kernel_data.integrator.pdf_lights;
169
__device void regular_light_sample(KernelGlobals *kg, int point,
170
float randu, float randv, float3 P, LightSample *ls, float *pdf)
172
float4 data0 = kernel_tex_fetch(__light_data, point*LIGHT_SIZE + 0);
173
float4 data1 = kernel_tex_fetch(__light_data, point*LIGHT_SIZE + 1);
151
__device float3 disk_light_sample(float3 v, float randu, float randv)
155
make_orthonormals(v, &ru, &rv);
156
to_unit_disk(&randu, &randv);
158
return ru*randu + rv*randv;
161
__device float3 distant_light_sample(float3 D, float radius, float randu, float randv)
163
return normalize(D + disk_light_sample(D, randu, randv)*radius);
166
__device float3 sphere_light_sample(float3 P, float3 center, float radius, float randu, float randv)
168
return disk_light_sample(normalize(P - center), randu, randv)*radius;
171
__device float3 area_light_sample(float3 axisu, float3 axisv, float randu, float randv)
173
randu = randu - 0.5f;
174
randv = randv - 0.5f;
176
return axisu*randu + axisv*randv;
179
__device float spot_light_attenuation(float4 data1, float4 data2, LightSample *ls)
181
float3 dir = make_float3(data2.y, data2.z, data2.w);
184
float spot_angle = data1.w;
185
float spot_smooth = data2.x;
187
float attenuation = dot(dir, I);
189
if(attenuation <= spot_angle) {
193
float t = attenuation - spot_angle;
195
if(t < spot_smooth && spot_smooth != 0.0f)
196
attenuation *= smoothstepf(t/spot_smooth);
202
__device float lamp_light_pdf(KernelGlobals *kg, const float3 Ng, const float3 I, float t)
204
float cos_pi = dot(Ng, I);
212
__device void lamp_light_sample(KernelGlobals *kg, int lamp,
213
float randu, float randv, float3 P, LightSample *ls)
215
float4 data0 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 0);
216
float4 data1 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 1);
175
218
LightType type = (LightType)__float_as_int(data0.x);
220
ls->shader = __float_as_int(data1.x);
178
225
if(type == LIGHT_DISTANT) {
179
226
/* distant light */
180
float3 D = make_float3(data0.y, data0.z, data0.w);
181
float size = data1.y;
227
float3 lightD = make_float3(data0.y, data0.z, data0.w);
229
float radius = data1.y;
230
float invarea = data1.w;
184
D = distant_light_sample(D, size, randu, randv);
233
D = distant_light_sample(D, radius, randu, randv);
240
float costheta = dot(lightD, D);
241
ls->pdf = invarea/(costheta*costheta*costheta);
242
ls->eval_fac = ls->pdf*kernel_data.integrator.inv_pdf_lights;
191
244
#ifdef __BACKGROUND_MIS__
192
245
else if(type == LIGHT_BACKGROUND) {
193
246
/* infinite area light (e.g. light dome or env light) */
194
float3 D = background_light_sample(kg, randu, randv, pdf);
247
float3 D = background_light_sample(kg, randu, randv, &ls->pdf);
203
257
ls->P = make_float3(data0.y, data0.z, data0.w);
205
if(type == LIGHT_POINT) {
206
float size = data1.y;
210
ls->P += sphere_light_sample(P, ls->P, size, randu, randv);
212
ls->Ng = normalize(P - ls->P);
259
if(type == LIGHT_POINT || type == LIGHT_SPOT) {
260
float radius = data1.y;
264
ls->P += sphere_light_sample(P, ls->P, radius, randu, randv);
266
ls->D = normalize_len(ls->P - P, &ls->t);
269
float invarea = data1.z;
270
ls->eval_fac = (0.25f*M_1_PI_F)*invarea;
273
if(type == LIGHT_SPOT) {
274
/* spot light attentuation */
275
float4 data2 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 2);
276
ls->eval_fac *= spot_light_attenuation(data1, data2, ls);
216
float4 data2 = kernel_tex_fetch(__light_data, point*LIGHT_SIZE + 2);
217
float4 data3 = kernel_tex_fetch(__light_data, point*LIGHT_SIZE + 3);
281
float4 data2 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 2);
282
float4 data3 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 3);
219
float3 axisu = make_float3(data1.y, data1.z, data2.w);
284
float3 axisu = make_float3(data1.y, data1.z, data1.w);
220
285
float3 axisv = make_float3(data2.y, data2.z, data2.w);
221
286
float3 D = make_float3(data3.y, data3.z, data3.w);
223
288
ls->P += area_light_sample(axisu, axisv, randu, randv);
290
ls->D = normalize_len(ls->P - P, &ls->t);
292
float invarea = data2.x;
294
ls->eval_fac = 0.25f*invarea;
298
ls->eval_fac *= kernel_data.integrator.inv_pdf_lights;
299
ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t);
303
__device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D, float t, LightSample *ls)
305
float4 data0 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 0);
306
float4 data1 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 1);
308
LightType type = (LightType)__float_as_int(data0.x);
230
310
ls->shader = __float_as_int(data1.x);
235
__device float regular_light_pdf(KernelGlobals *kg,
236
const float3 Ng, const float3 I, float t)
238
float pdf = kernel_data.integrator.pdf_lights;
243
float cos_pi = dot(Ng, I);
248
return t*t*pdf/cos_pi;
315
if(!(ls->shader & SHADER_USE_MIS))
318
if(type == LIGHT_DISTANT) {
320
float radius = data1.y;
327
/* a distant light is infinitely far away, but equivalent to a disk
328
* shaped light exactly 1 unit away from the current shading point.
330
* radius t^2/cos(theta)
331
* <----------> t = sqrt(1^2 + tan(theta)^2)
332
* tan(th) area = radius*radius*pi
334
* \ | (1 + tan(theta)^2)/cos(theta)
335
* \ | (1 + tan(acos(cos(theta)))^2)/cos(theta)
336
* t \th| 1 simplifies to
337
* \-| 1/(cos(theta)^3)
342
float3 lightD = make_float3(data0.y, data0.z, data0.w);
343
float costheta = dot(-lightD, D);
344
float cosangle = data1.z;
346
if(costheta < cosangle)
354
float invarea = data1.w;
355
ls->pdf = invarea/(costheta*costheta*costheta);
356
ls->eval_fac = ls->pdf;
358
else if(type == LIGHT_POINT || type == LIGHT_SPOT) {
359
float3 lightP = make_float3(data0.y, data0.z, data0.w);
360
float radius = data1.y;
366
if(!ray_aligned_disk_intersect(P, D, t,
367
lightP, radius, &ls->P, &ls->t))
373
float invarea = data1.z;
374
ls->eval_fac = (0.25f*M_1_PI_F)*invarea;
377
if(type == LIGHT_SPOT) {
378
/* spot light attentuation */
379
float4 data2 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 2);
380
ls->eval_fac *= spot_light_attenuation(data1, data2, ls);
382
if(ls->eval_fac == 0.0f)
386
else if(type == LIGHT_AREA) {
388
float4 data2 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 2);
389
float4 data3 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 3);
391
float invarea = data2.x;
395
float3 axisu = make_float3(data1.y, data1.z, data1.w);
396
float3 axisv = make_float3(data2.y, data2.z, data2.w);
397
float3 Ng = make_float3(data3.y, data3.z, data3.w);
400
if(dot(D, Ng) >= 0.0f)
403
ls->P = make_float3(data0.y, data0.z, data0.w);
405
if(!ray_quad_intersect(P, D, t,
406
ls->P, axisu, axisv, &ls->P, &ls->t))
412
ls->eval_fac = 0.25f*ls->pdf;
419
ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t);
420
ls->eval_fac *= kernel_data.integrator.inv_pdf_lights;
251
425
/* Triangle Light */
427
__device void object_transform_light_sample(KernelGlobals *kg, LightSample *ls, int object, float time)
429
#ifdef __INSTANCING__
430
/* instance transform */
432
#ifdef __OBJECT_MOTION__
434
Transform tfm = object_fetch_transform_motion_test(kg, object, time, &itfm);
436
Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
437
Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
440
ls->P = transform_point(&tfm, ls->P);
441
ls->Ng = normalize(transform_direction(&tfm, ls->Ng));
253
446
__device void triangle_light_sample(KernelGlobals *kg, int prim, int object,
254
float randu, float randv, LightSample *ls)
447
float randu, float randv, float time, LightSample *ls)
256
449
/* triangle, so get position, normal, shader */
257
450
ls->P = triangle_sample_MT(kg, prim, randu, randv);
258
451
ls->Ng = triangle_normal_MT(kg, prim, &ls->shader);
259
452
ls->object = object;
455
ls->shader |= SHADER_USE_MIS;
262
ls->type = LIGHT_AREA;
457
ls->type = LIGHT_TRIANGLE;
264
#ifdef __INSTANCING__
265
/* instance transform */
266
if(ls->object >= 0) {
267
object_position_transform(kg, ls->object, &ls->P);
268
object_normal_transform(kg, ls->object, &ls->Ng);
460
object_transform_light_sample(kg, ls, object, time);
273
463
__device float triangle_light_pdf(KernelGlobals *kg,
274
464
const float3 Ng, const float3 I, float t)
466
float pdf = kernel_data.integrator.pdf_triangles;
276
467
float cos_pi = fabsf(dot(Ng, I));
278
469
if(cos_pi == 0.0f)
281
return (t*t*kernel_data.integrator.pdf_triangles)/cos_pi;
472
return t*t*pdf/cos_pi;
479
__device void curve_segment_light_sample(KernelGlobals *kg, int prim, int object,
480
int segment, float randu, float randv, float time, LightSample *ls)
482
/* this strand code needs completion */
483
float4 v00 = kernel_tex_fetch(__curves, prim);
485
int k0 = __float_as_int(v00.x) + segment;
488
float4 P1 = kernel_tex_fetch(__curve_keys, k0);
489
float4 P2 = kernel_tex_fetch(__curve_keys, k1);
491
float l = len(P2 - P1);
495
float3 tg = float4_to_float3(P2 - P1) / l;
496
float3 xc = make_float3(tg.x * tg.z, tg.y * tg.z, -(tg.x * tg.x + tg.y * tg.y));
497
if (dot(xc, xc) == 0.0f)
498
xc = make_float3(tg.x * tg.y, -(tg.x * tg.x + tg.z * tg.z), tg.z * tg.y);
500
float3 yc = cross(tg, xc);
501
float gd = ((r2 - r1)/l);
503
/* normal currently ignores gradient */
504
ls->Ng = sinf(2 * M_PI_F * randv) * xc + cosf(2 * M_PI_F * randv) * yc;
505
ls->P = randu * l * tg + (gd * l + r1) * ls->Ng;
510
ls->type = LIGHT_STRAND;
512
ls->shader = __float_as_int(v00.z) | SHADER_USE_MIS;
514
object_transform_light_sample(kg, ls, object, time);
284
519
/* Light Distribution */
286
521
__device int light_distribution_sample(KernelGlobals *kg, float randt)
288
523
/* this is basically std::upper_bound as used by pbrt, to find a point light or
289
triangle to emit from, proportional to area. a good improvement would be to
290
also sample proportional to power, though it's not so well defined with
524
* triangle to emit from, proportional to area. a good improvement would be to
525
* also sample proportional to power, though it's not so well defined with
293
528
int len = kernel_data.integrator.num_distribution + 1;
326
560
int object = __float_as_int(l.w);
327
triangle_light_sample(kg, prim, object, randu, randv, ls);
331
regular_light_sample(kg, point, randu, randv, P, ls, pdf);
334
/* compute incoming direction and distance */
562
int segment = __float_as_int(l.z);
567
curve_segment_light_sample(kg, prim, object, segment, randu, randv, time, ls);
570
triangle_light_sample(kg, prim, object, randu, randv, time, ls);
572
/* compute incoming direction, distance and pdf */
336
573
ls->D = normalize_len(ls->P - P, &ls->t);
339
__device float light_sample_pdf(KernelGlobals *kg, LightSample *ls, float3 I, float t)
344
pdf = triangle_light_pdf(kg, ls->Ng, I, t);
574
ls->pdf = triangle_light_pdf(kg, ls->Ng, -ls->D, ls->t);
578
lamp_light_sample(kg, lamp, randu, randv, P, ls);
582
__device int light_select_num_samples(KernelGlobals *kg, int index)
584
float4 data3 = kernel_tex_fetch(__light_data, index*LIGHT_SIZE + 3);
585
return __float_as_int(data3.x);
588
__device void light_select(KernelGlobals *kg, int index, float randu, float randv, float3 P, LightSample *ls)
590
lamp_light_sample(kg, index, randu, randv, P, ls);
593
__device int lamp_light_eval_sample(KernelGlobals *kg, float randt)
596
int index = light_distribution_sample(kg, randt);
598
/* fetch light data */
599
float4 l = kernel_tex_fetch(__light_distribution, index);
600
int prim = __float_as_int(l.y);
346
pdf = regular_light_pdf(kg, ls->Ng, I, t);
351
__device void light_select(KernelGlobals *kg, int index, float randu, float randv, float3 P, LightSample *ls, float *pdf)
353
regular_light_sample(kg, index, randu, randv, P, ls, pdf);
356
__device float light_select_pdf(KernelGlobals *kg, LightSample *ls, float3 I, float t)
358
return regular_light_pdf(kg, ls->Ng, I, t);
361
610
CCL_NAMESPACE_END