31 #include <bpt_context.h> 32 #include <bpt_utils.h> 33 #include <bpt_options.h> 42 #define SECONDARY_EYE_VERTICES_BLOCKSIZE 128 43 #define SECONDARY_EYE_VERTICES_CTA_BLOCKS 6 45 #define SECONDARY_LIGHT_VERTICES_BLOCKSIZE 128 46 #define SECONDARY_LIGHT_VERTICES_CTA_BLOCKS 6 48 #define BPT_FULL_BSDF_EVALUATION 1 58 FERMAT_HOST_DEVICE FERMAT_FORCEINLINE
61 VertexSampling _light_sampling = VertexSampling::kAll,
62 VertexOrdering _light_ordering = VertexOrdering::kRandomOrdering,
63 VertexSampling _eye_sampling = VertexSampling::kAll,
64 bool _use_rr =
true) :
65 max_path_length(_options.max_path_length),
66 light_sampling(uint32(_light_sampling)),
67 light_ordering(uint32(_light_ordering)),
68 eye_sampling(uint32(_eye_sampling)),
69 use_vpls(_options.use_vpls),
71 light_tracing(_options.light_tracing),
72 direct_lighting_nee(_options.direct_lighting_nee),
73 direct_lighting_bsdf(_options.direct_lighting_bsdf),
74 indirect_lighting_nee(_options.indirect_lighting_nee),
75 indirect_lighting_bsdf(_options.indirect_lighting_bsdf),
76 visible_lights(_options.visible_lights) {}
78 FERMAT_HOST_DEVICE FERMAT_FORCEINLINE
80 uint32 _max_path_length = 6,
81 VertexSampling _light_sampling = VertexSampling::kAll,
82 VertexOrdering _light_ordering = VertexOrdering::kRandomOrdering,
83 VertexSampling _eye_sampling = VertexSampling::kAll,
84 bool _use_vpls =
true,
86 float _light_tracing = 0.0f,
87 bool _direct_lighting_nee =
true,
88 bool _direct_lighting_bsdf =
true,
89 bool _indirect_lighting_nee =
true,
90 bool _indirect_lighting_bsdf =
true,
91 bool _visible_lights =
true) :
92 max_path_length(_max_path_length),
93 light_sampling(uint32(_light_sampling)),
94 light_ordering(uint32(_light_ordering)),
95 eye_sampling(uint32(_eye_sampling)),
98 light_tracing(_light_tracing),
99 direct_lighting_nee(_direct_lighting_nee),
100 direct_lighting_bsdf(_direct_lighting_bsdf),
101 indirect_lighting_nee(_indirect_lighting_nee),
102 indirect_lighting_bsdf(_indirect_lighting_bsdf),
103 visible_lights(_visible_lights) {}
105 FERMAT_HOST_DEVICE FERMAT_FORCEINLINE
106 BPTConfigBase(
const BPTConfigBase& other) :
107 max_path_length(other.max_path_length),
108 light_sampling(other.light_sampling),
109 light_ordering(other.light_ordering),
110 eye_sampling(other.eye_sampling),
111 use_vpls(other.use_vpls),
112 use_rr(other.use_rr),
113 light_tracing(other.light_tracing),
114 direct_lighting_nee(other.direct_lighting_nee),
115 direct_lighting_bsdf(other.direct_lighting_bsdf),
116 indirect_lighting_nee(other.indirect_lighting_nee),
117 indirect_lighting_bsdf(other.indirect_lighting_bsdf),
118 visible_lights(other.visible_lights) {}
120 uint32 max_path_length : 10;
121 uint32 light_sampling : 1;
122 uint32 light_ordering : 1;
123 uint32 eye_sampling : 1;
126 uint32 direct_lighting_nee : 1;
127 uint32 direct_lighting_bsdf : 1;
128 uint32 indirect_lighting_nee : 1;
129 uint32 indirect_lighting_bsdf : 1;
130 uint32 visible_lights : 1;
137 FERMAT_HOST_DEVICE FERMAT_FORCEINLINE
144 FERMAT_HOST_DEVICE FERMAT_FORCEINLINE
151 FERMAT_HOST_DEVICE FERMAT_FORCEINLINE
154 return (VertexSampling(light_sampling) == VertexSampling::kAll) || absorbed;
162 FERMAT_HOST_DEVICE FERMAT_FORCEINLINE
166 (t == 1 && direct_lighting_nee) ||
167 (t > 1 && indirect_lighting_nee);
175 FERMAT_HOST_DEVICE FERMAT_FORCEINLINE
179 (t == 2 && visible_lights) ||
180 (t == 3 && direct_lighting_bsdf) ||
181 (t > 3 && indirect_lighting_bsdf);
186 template <
typename TBPTContext>
187 FERMAT_HOST_DEVICE FERMAT_FORCEINLINE
189 const uint32 light_path_id,
192 TBPTContext& context,
198 template <
typename TBPTContext>
199 FERMAT_HOST_DEVICE FERMAT_FORCEINLINE
201 const uint32 eye_path_id,
205 TBPTContext& context,
221 template <
typename TBPTContext>
224 const uint32 channel,
226 const uint32 light_path_id,
227 const uint32 eye_path_id,
230 TBPTContext& context,
237 template <
typename TBPTContext>
242 const uint32 eye_path_id,
244 TBPTContext& context,
275 template <
typename TPrimaryCoordinates,
typename TBPTContext,
typename TBPTConfig>
278 const uint32 light_path_id,
279 const uint32 n_light_paths,
280 const TPrimaryCoordinates& primary_coords,
281 TBPTContext& context,
292 if (VertexOrdering(config.light_ordering) == VertexOrdering::kPathOrdering)
295 context.light_vertices.vertex_counts[light_path_id] = 0;
298 context.light_vertices.vertex_path_id[light_path_id] = uint32(-1);
302 if (config.terminate_light_subpath(light_path_id, 0) ==
true)
312 light_vertex = context.light_vertices.vertex[light_path_id];
314 renderer.mesh_vpls.
map(light_vertex.prim_id, light_vertex.uv, &geom, &pdf, &edf);
319 for (uint32 i = 0; i < 3; ++i)
320 samples[i] = primary_coords.sample(light_path_id, 0, i);
322 renderer.mesh_light.
sample(samples, &light_vertex.prim_id, &light_vertex.uv, &geom, &pdf, &edf);
326 config.visit_light_vertex(
333 const bool terminate = config.terminate_light_subpath(light_path_id, 1);
335 if (terminate || (VertexSampling(config.light_sampling) == VertexSampling::kAll))
337 const uint32 slot = (VertexOrdering(config.light_ordering) == VertexOrdering::kRandomOrdering) ?
338 #
if defined(FERMAT_DEVICE_COMPILATION)
348 context.light_vertices.vertex_gbuffer[slot] =
pack_edf(edf);
349 context.light_vertices.vertex_pos[slot] =
cugar::Vector4f(geom.position, cugar::binary_cast<float>(packed_normal));
350 context.light_vertices.vertex_input[slot] = make_uint2(0, cugar::to_rgbe(
cugar::Vector3f(1.0f) / pdf));
351 context.light_vertices.vertex_weights[slot] =
PathWeights(
356 context.light_vertices.vertex_path_id[slot] = light_path_id;
358 if (VertexOrdering(config.light_ordering) == VertexOrdering::kPathOrdering)
361 context.light_vertices.vertex_counts[light_path_id] = 1;
365 if (terminate ==
false)
368 for (uint32 i = 0; i < 3; ++i)
369 samples[i] = primary_coords.sample(light_path_id, 1, i);
384 out_ray.origin = geom.position;
386 out_ray.tmin = 1.0e-4f;
387 out_ray.tmax = 1.0e8f;
390 const uint32 slot = context.scatter_queue.warp_append_slot();
393 context.scatter_queue.rays[slot] = out_ray;
395 context.scatter_queue.probs[slot] = p;
396 context.scatter_queue.pixels[slot] =
PixelInfo(light_path_id, FBufferDesc::DIFFUSE_C).packed;
397 context.scatter_queue.path_weights[slot] = TempPathWeights::light_vertex_1( pdf, p_proj, fabsf(dot(geom.normal_s, out)) );
419 template <
typename TPrimaryCoordinates,
typename TBPTContext,
typename TBPTConfig>
422 const uint32 queue_idx,
423 const uint32 n_light_paths,
424 const TPrimaryCoordinates& primary_coords,
425 TBPTContext& context,
429 const PixelInfo pixel_info = context.in_queue.pixels[queue_idx];
430 const Ray ray = context.in_queue.rays[queue_idx];
431 const Hit hit = context.in_queue.hits[queue_idx];
433 const TempPathWeights path_weights = context.in_queue.path_weights[queue_idx];
435 const uint32 light_path_id = pixel_info.pixel;
437 if (hit.t > 0.0f && hit.triId >= 0)
440 config.visit_light_vertex(
442 context.in_bounce + 1,
449 lv.setup(ray, hit, w.xyz(), path_weights, context.in_bounce + 1, renderer);
451 bool absorbed =
true;
454 if (config.terminate_light_subpath(light_path_id, context.in_bounce + 2) ==
false)
458 for (uint32 i = 0; i < 3; ++i)
459 z[i] = primary_coords.sample(light_path_id, context.in_bounce + 2, i);
469 scatter(lv, z, out_comp, out, p, p_proj, out_w, config.use_rr,
true, BPT_FULL_BSDF_EVALUATION);
471 if (cugar::max_comp(out_w) > 0.0f)
475 out_ray.origin = lv.geom.position;
477 out_ray.tmin = 1.0e-4f;
478 out_ray.tmax = 1.0e8f;
482 context.scatter_queue.warp_append(
494 if (config.store_light_vertex(light_path_id, context.in_bounce + 2, absorbed))
496 const uint32 slot = (VertexOrdering(config.light_ordering) == VertexOrdering::kRandomOrdering) ?
497 #
if defined(FERMAT_DEVICE_COMPILATION)
502 light_path_id + context.light_vertices.vertex_counts[light_path_id] * n_light_paths;
507 context.light_vertices.vertex[slot] =
VPL( hit.triId,
cugar::Vector2f(hit.u, hit.v), 0.0f );
508 context.light_vertices.vertex_gbuffer[slot] =
pack_bsdf(lv.material);
509 context.light_vertices.vertex_pos[slot] =
cugar::Vector4f(lv.geom.position, cugar::binary_cast<float>(packed_normal));
510 context.light_vertices.vertex_input[slot] = make_uint2(packed_direction, cugar::to_rgbe(w.xyz()));
511 context.light_vertices.vertex_weights[slot] =
PathWeights(
515 context.light_vertices.vertex_path_id[slot] = light_path_id | ((context.in_bounce + 1) << 24);
517 if (VertexOrdering(config.light_ordering) == VertexOrdering::kPathOrdering)
520 context.light_vertices.vertex_counts[light_path_id]++;
540 template <
typename TPrimaryCoordinates,
typename TBPTContext,
typename TBPTConfig>
544 const uint32 n_eye_paths,
545 const uint32 n_light_paths,
546 const TPrimaryCoordinates& primary_coords,
547 TBPTContext& context,
552 primary_coords.sample(idx, 1, 0),
553 primary_coords.sample(idx, 1, 1));
559 config.visit_eye_vertex(
568 context.in_queue.pixels[idx] = idx;
571 cugar::Vector3f ray_direction = d.x*context.camera_U + d.y*context.camera_V + context.camera_W;
573 ((float4*)context.in_queue.rays)[2 * idx + 0] = make_float4(ray_origin.x, ray_origin.y, ray_origin.z, 0.0f);
574 ((float4*)context.in_queue.rays)[2 * idx + 1] = make_float4(ray_direction.x, ray_direction.y, ray_direction.z, 1e34f);
577 context.in_queue.weights[idx] =
cugar::Vector4f(1.0f, 1.0f, 1.0f, 1.0f);
579 const float p_e =
camera_direction_pdf(context.camera_U, context.camera_V, context.camera_W, context.camera_W_len, context.camera_square_focal_length, cugar::normalize(ray_direction),
true);
580 const float cos_theta = dot(cugar::normalize(ray_direction), context.camera_W) / context.camera_W_len;
583 context.in_queue.path_weights[idx] = TempPathWeights::eye_vertex_1( p_e, cos_theta, config.light_tracing );
586 *context.in_queue.size = n_eye_paths;
614 template <
typename TSampleSink,
typename TPrimaryCoordinates,
typename TBPTContext,
typename TBPTConfig>
617 const uint32 queue_idx,
618 const uint32 n_eye_paths,
619 const uint32 n_light_paths,
620 TSampleSink& sample_sink,
621 const TPrimaryCoordinates& primary_coords,
622 TBPTContext& context,
626 const PixelInfo pixel_info = context.in_queue.pixels[queue_idx];
627 const Ray ray = context.in_queue.rays[queue_idx];
628 const Hit hit = context.in_queue.hits[queue_idx];
630 const TempPathWeights path_weights = context.in_queue.path_weights[queue_idx];
632 const uint32 eye_path_id = pixel_info.pixel;
636 if (hit.t > 0.0f && hit.triId >= 0)
640 ev.setup(ray, hit, w.xyz(), path_weights, context.in_bounce, renderer);
643 config.visit_eye_vertex(
645 context.in_bounce + 1,
651 bool absorbed =
true;
654 if (config.terminate_eye_subpath(eye_path_id, context.in_bounce + 2) ==
false)
658 for (uint32 i = 0; i < 3; ++i)
659 z[i] = primary_coords.sample(pixel_info.pixel, context.in_bounce + 2, i);
668 scatter(ev, z, out_comp, out, p, p_proj, out_w, config.use_rr,
true, BPT_FULL_BSDF_EVALUATION);
670 if (cugar::max_comp(out_w) > 0.0f)
673 sample_sink.sink_eye_scattering_event(
677 context.in_bounce + 2,
683 out_ray.origin = ev.geom.position;
685 out_ray.tmin = 1.0e-4f;
686 out_ray.tmax = 1.0e8f;
688 const float out_p = p;
690 const PixelInfo out_pixel = context.in_bounce ?
692 PixelInfo(pixel_info.pixel, channel_selector(out_comp));
694 context.scatter_queue.warp_append(
706 const int32 max_path_verts = config.max_path_length + 1;
707 const int32 max_s = max_path_verts - ev.depth - 2;
708 const int32 max_light_depth = max_s - 1;
711 if (max_light_depth >= 0 &&
712 config.perform_connection(eye_path_id, context.in_bounce + 2, absorbed))
714 const bool single_connection =
715 VertexOrdering(config.light_ordering) == VertexOrdering::kRandomOrdering ||
716 VertexSampling(config.light_sampling) == VertexSampling::kEnd;
718 if (single_connection)
723 if (VertexOrdering(config.light_ordering) == VertexOrdering::kRandomOrdering)
727 for (uint32 i = 0; i < 3; ++i)
728 z[i] = primary_coords.sample(pixel_info.pixel, context.in_bounce + 2, 3 + i);
730 const uint32 n_light_vertex_paths = context.light_vertices.vertex_counts[0];
731 const uint32 n_light_vertices = context.light_vertices.vertex_counter[0];
744 light_weight = float(n_light_vertices) / float(n_light_vertex_paths);
748 light_idx = eye_path_id;
753 cugar::Vector4f light_pos = context.light_vertices.vertex_pos[light_idx];
754 const uint2 light_in = context.light_vertices.vertex_input[light_idx];
755 uint4 light_gbuffer = context.light_vertices.vertex_gbuffer[light_idx];
756 PathWeights light_weights = context.light_vertices.vertex_weights[light_idx];
757 const uint32 light_vertex_id = context.light_vertices.vertex_path_id[light_idx];
758 const uint32 light_path_id = light_vertex_id & 0xFFFFFF;
759 const uint32 light_depth = light_vertex_id >> 24;
762 if (light_vertex_id != uint32(-1))
766 lv.setup(light_pos, light_in, light_gbuffer, light_weights, light_depth, renderer);
773 eval_connection(ev, lv, out, out_w, d, config.use_rr, config.direct_lighting_nee, config.direct_lighting_bsdf);
776 out_w *= light_weight;
778 if (cugar::max_comp(out_w) > 0.0f && cugar::is_finite(out_w))
781 if (SHADOW_BIAS) d =
cugar::length(lv.geom.position - (ev.geom.position + ev.in * SHADOW_BIAS));
789 out_ray.origin = ev.geom.position + ev.in * SHADOW_BIAS;
790 out_ray.dir = (lv.geom.position - out_ray.origin);
791 out_ray.tmin = SHADOW_TMIN;
792 out_ray.tmax = 0.9999f;
794 const PixelInfo out_pixel = context.in_bounce ?
796 PixelInfo(pixel_info.pixel, FBufferDesc::DIRECT_C);
798 const uint32 slot = context.shadow_queue.warp_append_slot();
800 context.shadow_queue.pixels[slot] = out_pixel.packed;
801 context.shadow_queue.rays[slot] = out_ray;
803 context.shadow_queue.light_path_id[slot] = light_path_id | ((light_depth + 1) << 24) | ((ev.depth + 2) << 28);
811 const uint32 eye_to_light_paths = n_eye_paths / n_light_paths;
813 const uint32 light_path_id =
814 (n_light_paths == n_eye_paths) ? pixel_info.pixel :
815 pixel_info.pixel / eye_to_light_paths;
818 const int32 n_light_vertices = context.light_vertices.vertex_counts[light_path_id];
821 for (uint32 light_depth = config.direct_lighting_nee ? 0 : 1;
822 light_depth < cugar::min(n_light_vertices, max_light_depth + 1);
825 const float light_weight = 1.0f;
827 const uint32 light_idx = light_path_id + light_depth * n_light_paths;
830 cugar::Vector4f light_pos = context.light_vertices.vertex_pos[light_idx];
831 const uint2 light_in = context.light_vertices.vertex_input[light_idx];
832 uint4 light_gbuffer = context.light_vertices.vertex_gbuffer[light_idx];
833 PathWeights light_weights = context.light_vertices.vertex_weights[light_idx];
837 lv.setup(light_pos, light_in, light_gbuffer, light_weights, light_depth, renderer);
844 eval_connection(ev, lv, out, out_w, d, config.use_rr, config.direct_lighting_nee, config.direct_lighting_bsdf);
847 out_w *= light_weight;
849 if (cugar::max_comp(out_w) > 0.0f && cugar::is_finite(out_w))
852 if (SHADOW_BIAS) d =
cugar::length(lv.geom.position - (ev.geom.position + ev.in * SHADOW_BIAS));
860 out_ray.origin = ev.geom.position + ev.in * SHADOW_BIAS;
861 out_ray.dir = (lv.geom.position - out_ray.origin);
862 out_ray.tmin = SHADOW_TMIN;
863 out_ray.tmax = 0.9999f;
865 const PixelInfo out_pixel = context.in_bounce ?
867 PixelInfo(pixel_info.pixel, FBufferDesc::DIRECT_C);
869 const uint32 slot = context.shadow_queue.warp_append_slot();
871 context.shadow_queue.pixels[slot] = out_pixel.packed;
872 context.shadow_queue.rays[slot] = out_ray;
874 context.shadow_queue.light_path_id[slot] = light_path_id | ((light_depth + 1) << 24) | ((ev.depth + 2) << 28);
883 if (config.accumulate_emissive(eye_path_id, context.in_bounce + 2, absorbed))
887 if (cugar::max_comp(out_w) > 0.0f && cugar::is_finite(out_w))
895 context.in_bounce + 2,
922 template <
typename TBPTContext,
typename TBPTConfig>
928 const uint32 light_depth = context.light_vertices.vertex_path_id[ light_idx ] >> 24;
929 const float light_weight = 1.0f / float(n_light_paths);
931 const uint2 light_in = context.light_vertices.vertex_input[light_idx];
935 cugar::Vector4f light_pos = context.light_vertices.vertex_pos[light_idx];
936 uint4 light_gbuffer = context.light_vertices.vertex_gbuffer[light_idx];
939 PathWeights light_weights = context.light_vertices.vertex_weights[light_idx];
947 light_vertex_geom.position = light_pos.xyz();
948 light_vertex_geom.normal_s =
unpack_direction(cugar::binary_cast<uint32>(light_pos.w));
949 light_vertex_geom.normal_g = light_vertex_geom.normal_s;
950 light_vertex_geom.tangent = cugar::orthogonal(light_vertex_geom.normal_s);
951 light_vertex_geom.binormal = cugar::cross(light_vertex_geom.normal_s, light_vertex_geom.tangent);
955 const float d2 = fmaxf(1.0e-8f, cugar::square_length(light_vertex_geom.position -
cugar::Vector3f(renderer.camera.eye)));
956 const float d = sqrtf(d2);
962 const float cos_theta = cugar::dot(out, context.camera_W) / context.camera_W_len;
963 const float G = fabsf(cos_theta * cugar::dot(out, light_vertex_geom.normal_s)) / d2;
969 const float p_s =
camera_direction_pdf(context.camera_U, context.camera_V, context.camera_W, context.camera_W_len, context.camera_square_focal_length, out, &out_x, &out_y);
970 const float f_s = p_s * float(renderer.res_x * renderer.res_y);
976 if (light_depth == 0)
982 Edf light_bsdf(cugar::from_rgbe(light_gbuffer.x));
985 const cugar::Vector3f f_L = light_bsdf.
f(light_vertex_geom, light_vertex_geom.position, -out);
986 const float p_L = light_bsdf.
p(light_vertex_geom, light_vertex_geom.position, -out, cugar::kProjectedSolidAngle);
988 const float pGp = pdf_product( p_s, G, p_L );
989 const float next_pGp = pdf_product( p_L, light_weights.pG );
991 (config.visible_lights == 0) ? 1.0f :
992 bpt_mis(pGp / (config.light_tracing), next_pGp, light_weights.pGp_sum);
995 out_w =
cugar::Vector4f(light_in_alpha * f_L * f_s * G * mis_w, 1.0f) * light_weight;
1006 const cugar::Vector3f f_L = light_bsdf.
f(light_vertex_geom, light_in_dir, -out);
1007 const float p_L = light_bsdf.
p(light_vertex_geom, light_in_dir, -out, cugar::kProjectedSolidAngle);
1009 const float pGp = pdf_product( p_s, G, p_L );
1010 const float next_pGp = pdf_product( cugar::max_comp(f_L), light_weights.pG );
1012 (light_depth == 1 &&
1013 config.direct_lighting_nee == 0 &&
1014 config.direct_lighting_bsdf == 0) ? 1.0f :
1016 config.indirect_lighting_nee == 0 &&
1017 config.indirect_lighting_bsdf == 0) ? 1.0f :
1018 bpt_mis(pGp / (config.light_tracing), next_pGp, light_weights.pGp_sum);
1021 out_w =
cugar::Vector4f(light_in_alpha * f_L * f_s * G * mis_w, 1.0f) * light_weight;
1024 if (cugar::max_comp(out_w.xyz()) > 0.0f && cugar::is_finite(out_w.xyz()))
1029 out_ray.origin = renderer.camera.eye;
1031 out_ray.tmin = SHADOW_TMIN;
1032 out_ray.tmax = d * 0.9999f;
1034 out_ray.origin = light_vertex_geom.position + light_in_dir * SHADOW_BIAS;
1035 out_ray.dir = renderer.camera.eye - out_ray.origin;
1036 out_ray.tmin = SHADOW_TMIN;
1037 out_ray.tmax = 0.9999f;
1044 FBufferDesc::DIRECT_C);
1046 context.shadow_queue.warp_append(out_pixel, out_ray, out_w, 1.0f);
1062 template <
typename TSampleSink,
typename TBPTContext>
1066 const PixelInfo pixel_info = context.shadow_queue.pixels[queue_idx];
1067 const Hit hit = context.shadow_queue.hits[queue_idx];
1069 const uint32 light_path_id = context.shadow_queue.light_path_id[queue_idx];
1072 const float vis = (hit.t < 0.0f) ? 1.0f : 0.0f;
1074 const uint32 s = (light_path_id >> 24) & 0xF;
1075 const uint32 t = (light_path_id >> 28) & 0xF;
1077 sample_sink.sink(pixel_info.channel, w * vis, light_path_id & 0xFFFFFF, pixel_info.pixel, s, t, context, renderer);
1082 template <
typename TBPTContext,
typename TBPTConfig>
1084 void light_tracing_kernel(
const uint32 n_light_paths, TBPTContext context,
RenderingContextView renderer, TBPTConfig config)
1086 const uint32 thread_id = threadIdx.x + blockIdx.x * blockDim.x;
1088 if (VertexOrdering(config.light_ordering) == VertexOrdering::kRandomOrdering)
1091 const int32 max_light_depth = config.max_path_length - 1;
1093 const uint32 n_light_vertices = context.light_vertices.vertex_counts[max_light_depth];
1095 const uint32 light_idx = thread_id;;
1097 if (light_idx < n_light_vertices)
1102 const uint32 light_path_id = thread_id;
1104 if (light_path_id < n_light_paths)
1106 const uint32 vertex_count = context.light_vertices.vertex_counts[light_path_id];
1107 for (uint32 i = 0; i < vertex_count; ++i)
1108 connect_to_camera(light_path_id + i * n_light_paths, n_light_paths, context, renderer, config);
1113 template <
typename TBPTContext,
typename TBPTConfig>
1118 if (VertexOrdering(config.light_ordering) == VertexOrdering::kRandomOrdering)
1121 const int32 max_light_depth = config.max_path_length - 1;
1123 cudaMemcpy(&n_threads, &context.light_vertices.vertex_counts[max_light_depth],
sizeof(uint32), cudaMemcpyDeviceToHost);
1126 n_threads = n_light_paths;
1131 const uint32 blockSize(128);
1134 light_tracing_kernel << < gridSize, blockSize >> > (n_light_paths, context, renderer, config);
1138 template <
typename TSampleSink,
typename TBPTContext>
1140 void solve_occlusions_kernel(
const uint32 in_queue_size, TSampleSink sample_sink, TBPTContext context,
RenderingContextView renderer)
1142 const uint32 thread_id = threadIdx.x + blockIdx.x * blockDim.x;
1144 if (thread_id < in_queue_size)
1148 template <
typename TSampleSink,
typename TBPTContext>
1149 void solve_occlusions(
const uint32 in_queue_size, TSampleSink sample_sink, TBPTContext context,
RenderingContextView renderer)
1152 if (in_queue_size == 0)
1155 const uint32 blockSize(128);
1157 solve_occlusions_kernel << < gridSize, blockSize >> > (in_queue_size, sample_sink, context, renderer);
1160 template <
typename TPrimaryCoordinates,
typename TBPTContext,
typename TBPTConfig>
1162 void generate_primary_light_vertices_kernel(
const uint32 n_light_paths, TPrimaryCoordinates primary_coords, TBPTContext context,
RenderingContextView renderer,
const TBPTConfig config)
1164 const uint32 light_path_id = threadIdx.x + blockIdx.x * blockDim.x;
1166 if (light_path_id < n_light_paths)
1170 template <
typename TPrimaryCoordinates,
typename TBPTContext,
typename TBPTConfig>
1171 void generate_primary_light_vertices(
const uint32 n_light_paths, TPrimaryCoordinates primary_coords, TBPTContext context,
RenderingContextView renderer,
const TBPTConfig config)
1176 const uint32 blockSize(128);
1178 generate_primary_light_vertices_kernel << < gridSize, blockSize >> > (n_light_paths, primary_coords, context, renderer, config);
1182 if (VertexOrdering(config.light_ordering) == VertexOrdering::kRandomOrdering)
1183 cudaMemcpy(context.light_vertices.vertex_counts, context.light_vertices.vertex_counter,
sizeof(uint32), cudaMemcpyDeviceToDevice);
1187 template <
typename TPrimaryCoordinates,
typename TBPTContext,
typename TBPTConfig>
1189 __launch_bounds__(SECONDARY_LIGHT_VERTICES_BLOCKSIZE, SECONDARY_LIGHT_VERTICES_CTA_BLOCKS)
1190 void process_secondary_light_vertices_kernel(
const uint32 in_queue_size,
const uint32 n_light_paths, TPrimaryCoordinates primary_coords, TBPTContext context,
RenderingContextView renderer,
const TBPTConfig config)
1192 const uint32 thread_id = threadIdx.x + blockIdx.x * blockDim.x;
1194 if (thread_id < in_queue_size)
1198 template <
typename TPrimaryCoordinates,
typename TBPTContext,
typename TBPTConfig>
1199 void process_secondary_light_vertices(
const uint32 in_queue_size,
const uint32 n_light_paths, TPrimaryCoordinates primary_coords, TBPTContext context,
RenderingContextView renderer,
const TBPTConfig config)
1204 const uint32 blockSize(SECONDARY_LIGHT_VERTICES_BLOCKSIZE);
1206 process_secondary_light_vertices_kernel << < gridSize, blockSize >> > (in_queue_size, n_light_paths, primary_coords, context, renderer, config);
1210 if (VertexOrdering(config.light_ordering) == VertexOrdering::kRandomOrdering)
1211 cudaMemcpy(context.light_vertices.vertex_counts + context.in_bounce + 1, context.light_vertices.vertex_counter,
sizeof(uint32), cudaMemcpyDeviceToDevice);
1215 template <
typename TPrimaryCoordinates,
typename TBPTContext,
typename TBPTConfig>
1217 void generate_primary_eye_vertices_kernel(
const uint32 n_eye_paths,
const uint32 n_light_paths, TPrimaryCoordinates primary_coords, TBPTContext context,
RenderingContextView renderer,
const TBPTConfig config)
1219 const uint32 eye_path_id = threadIdx.x + blockIdx.x * blockDim.x;
1221 if (eye_path_id < n_eye_paths)
1225 template <
typename TPrimaryCoordinates,
typename TBPTConfig,
typename TBPTContext>
1226 void generate_primary_eye_vertices(
const uint32 n_eye_paths,
const uint32 n_light_paths, TPrimaryCoordinates primary_coords, TBPTContext context,
RenderingContextView renderer,
const TBPTConfig config)
1228 const uint32 blockSize(128);
1230 generate_primary_eye_vertices_kernel << < gridSize, blockSize >> > (n_eye_paths, n_light_paths, primary_coords, context, renderer, config);
1233 template <
typename TSampleSink,
typename TPrimaryCoordinates,
typename TBPTContext,
typename TBPTConfig>
1235 __launch_bounds__(SECONDARY_EYE_VERTICES_BLOCKSIZE, SECONDARY_EYE_VERTICES_CTA_BLOCKS)
1236 void process_secondary_eye_vertices_kernel(
const uint32 in_queue_size,
const uint32 n_eye_paths,
const uint32 n_light_paths, TSampleSink sink, TPrimaryCoordinates primary_coords, TBPTContext context,
RenderingContextView renderer,
const TBPTConfig config)
1238 const uint32 thread_id = threadIdx.x + blockIdx.x * blockDim.x;
1240 if (thread_id < in_queue_size)
1244 template <
typename TSampleSink,
typename TPrimaryCoordinates,
typename TBPTContext,
typename TBPTConfig>
1245 void process_secondary_eye_vertices(
const uint32 in_queue_size,
const uint32 n_eye_paths,
const uint32 n_light_paths, TSampleSink sink, TPrimaryCoordinates primary_coords, TBPTContext context,
RenderingContextView renderer,
const TBPTConfig config)
1247 const uint32 blockSize(SECONDARY_EYE_VERTICES_BLOCKSIZE);
1249 process_secondary_eye_vertices_kernel << < gridSize, blockSize >> > (in_queue_size, n_eye_paths, n_light_paths, sink, primary_coords, context, renderer, config);
FERMAT_HOST_DEVICE FERMAT_FORCEINLINE void visit_eye_vertex(const uint32 eye_path_id, const uint32 depth, const VertexGeometryId v_id, const EyeVertex &v, TBPTContext &context, RenderingContextView &renderer) const
Definition: bpt_kernels.h:200
CUGAR_HOST_DEVICE uint32 quantize(const float x, const uint32 n)
Definition: numbers.h:600
FERMAT_HOST_DEVICE FERMAT_FORCEINLINE bool accumulate_emissive(const uint32 eye_path_id, const uint32 t, const bool absorbed) const
Definition: bpt_kernels.h:176
__device__ __forceinline__ unsigned int warp_increment(unsigned int *ptr)
Definition: warp_atomics.h:56
FERMAT_HOST_DEVICE void generate_primary_eye_vertex(const uint32 idx, const uint32 n_eye_paths, const uint32 n_light_paths, const TPrimaryCoordinates &primary_coords, TBPTContext &context, RenderingContextView &renderer, TBPTConfig &config)
Definition: bpt_kernels.h:542
Definition: bpt_utils.h:110
FERMAT_HOST_DEVICE FERMAT_FORCEINLINE uint4 pack_bsdf(const MeshMaterial &material)
Definition: bpt_utils.h:215
FERMAT_HOST_DEVICE FERMAT_FORCEINLINE bool terminate_light_subpath(const uint32 path_id, const uint32 s) const
Definition: bpt_kernels.h:138
FERMAT_HOST_DEVICE FERMAT_FORCEINLINE void visit_light_vertex(const uint32 light_path_id, const uint32 depth, const VertexGeometryId v_id, TBPTContext &context, RenderingContextView &renderer) const
Definition: bpt_kernels.h:188
FERMAT_HOST_DEVICE cugar::Vector3f eval_incoming_emission(const EyeVertex &ev, const RenderingContextView &renderer, bool direct_lighting_nee, bool indirect_lighting_nee, bool use_vpls)
Definition: bpt_utils.h:1034
FERMAT_HOST_DEVICE void process_secondary_light_vertex(const uint32 queue_idx, const uint32 n_light_paths, const TPrimaryCoordinates &primary_coords, TBPTContext &context, RenderingContextView &renderer, TBPTConfig &config)
Definition: bpt_kernels.h:421
FERMAT_HOST_DEVICE FERMAT_FORCEINLINE bool store_light_vertex(const uint32 path_id, const uint32 s, const bool absorbed) const
Definition: bpt_kernels.h:152
FERMAT_HOST_DEVICE void sink_eye_scattering_event(const Bsdf::ComponentType component, const cugar::Vector4f value, const uint32 eye_path_id, const uint32 t, TBPTContext &context, RenderingContextView &renderer)
Definition: bpt_kernels.h:239
__global__ __launch_bounds__(SHADE_HITS_BLOCKSIZE, SHADE_HITS_CTA_BLOCKS) void shade_hits_kernel(const uint32 in_queue_size
[SampleSinkBaseBlock]
Definition: bpt_control.h:287
FERMAT_HOST_DEVICE void map(const uint32_t prim_id, const cugar::Vector2f &uv, VertexGeometry *geom, float *pdf, Edf *edf) const
Definition: lights.h:584
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE float atomic_add(float *value, const float op)
Definition: atomics.h:100
FERMAT_HOST_DEVICE void process_secondary_eye_vertex(const uint32 queue_idx, const uint32 n_eye_paths, const uint32 n_light_paths, TSampleSink &sample_sink, const TPrimaryCoordinates &primary_coords, TBPTContext &context, RenderingContextView &renderer, TBPTConfig &config)
Definition: bpt_kernels.h:616
ComponentType
Definition: bsdf.h:139
FERMAT_HOST_DEVICE void sink(const uint32 channel, const cugar::Vector4f value, const uint32 light_path_id, const uint32 eye_path_id, const uint32 s, const uint32 t, TBPTContext &context, RenderingContextView &renderer)
Definition: bpt_kernels.h:223
CUGAR_HOST_DEVICE L divide_ri(const L x, const R y)
Definition: numbers.h:180
FERMAT_HOST_DEVICE FERMAT_FORCEINLINE Bsdf unpack_bsdf(const RenderingContextView &renderer, const uint4 packed_info, const TransportType transport=kParticleTransport)
Definition: bpt_utils.h:240
FERMAT_HOST_DEVICE void connect_to_camera(const uint32 light_idx, const uint32 n_light_paths, TBPTContext &context, RenderingContextView &renderer, const TBPTConfig &config)
Definition: bpt_kernels.h:924
FERMAT_HOST_DEVICE void setup_differential_geometry(const MeshView &mesh, const uint32 tri_id, const float u, const float v, VertexGeometry *geom, float *pdf=0)
Definition: mesh_utils.h:185
Definition: bpt_utils.h:131
FERMAT_HOST_DEVICE void solve_occlusion(const uint32 queue_idx, TSampleSink &sample_sink, TBPTContext &context, RenderingContextView &renderer)
Definition: bpt_kernels.h:1064
FERMAT_HOST_DEVICE FERMAT_FORCEINLINE uint32 pack_direction(const cugar::Vector3f &dir)
Definition: vertex.h:123
Definition: bpt_utils.h:583
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE Vector3f f(const DifferentialGeometry &geometry, const Vector3f in, const Vector3f out) const
Definition: lambert_edf.h:60
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE float p(const DifferentialGeometry &geometry, const Vector3f in, const Vector3f out, const SphericalMeasure measure=kProjectedSolidAngle) const
Definition: lambert_edf.h:80
void light_tracing(const uint32 n_light_paths, TSampleSink sample_sink, TBPTContext &context, const TBPTConfig &config, RenderingContext &renderer, RenderingContextView &renderer_view)
Definition: bpt_control.h:576
FERMAT_HOST_DEVICE FERMAT_FORCEINLINE bool scatter(const VertexType &v, const float z[3], Bsdf::ComponentType &out_component, cugar::Vector3f &out, float &out_p, float &out_p_proj, cugar::Vector3f &out_w, bool RR=true, bool output_alpha=true, bool evaluate_full_bsdf=false, Bsdf::ComponentType components=Bsdf::kAllComponents)
Definition: bpt_utils.h:1070
Definition: bpt_kernels.h:216
FERMAT_HOST_DEVICE bool sample(const float *Z, uint32_t *prim_id, cugar::Vector2f *uv, VertexGeometry *geom, float *pdf, Edf *edf) const
Definition: lights.h:521
Definition: bpt_kernels.h:56
FERMAT_HOST_DEVICE FERMAT_FORCEINLINE cugar::Vector3f unpack_direction(const uint32 packed_dir)
Definition: vertex.h:133
FERMAT_HOST_DEVICE float camera_direction_pdf(const cugar::Vector3f &U, const cugar::Vector3f &V, const cugar::Vector3f &W, const float W_len, const float square_focal_length, const cugar::Vector3f out, float *out_x=0, float *out_y=0)
Definition: camera.h:206
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE void sample(const Vector2f u, const DifferentialGeometry &geometry, const Vector3f in, Vector3f &out, Vector3f &g, float &p, float &p_proj) const
Definition: lambert_edf.h:90
FERMAT_HOST_DEVICE FERMAT_FORCEINLINE bool perform_connection(const uint32 eye_path_id, const uint32 t, const bool absorbed) const
Definition: bpt_kernels.h:163
Definition: pathtracer_core.h:527
FERMAT_HOST_DEVICE FERMAT_FORCEINLINE bool terminate_eye_subpath(const uint32 path_id, const uint32 t) const
Definition: bpt_kernels.h:145
FERMAT_FORCEINLINE FERMAT_HOST_DEVICE cugar::Vector3f f(const cugar::DifferentialGeometry &geometry, const cugar::Vector3f w_i, const cugar::Vector3f w_o, const ComponentType components=kAllComponents) const
Definition: bsdf.h:312
Definition: renderer_view.h:80
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE uint32 length(const vector_view< Iterator > &vec)
Definition: vector_view.h:228
Definition: bpt_utils.h:311
Define CUDA based warp adders.
FERMAT_HOST_DEVICE void generate_primary_light_vertex(const uint32 light_path_id, const uint32 n_light_paths, const TPrimaryCoordinates &primary_coords, TBPTContext &context, RenderingContextView &renderer, TBPTConfig &config)
Definition: bpt_kernels.h:277
FERMAT_HOST_DEVICE FERMAT_FORCEINLINE uint4 pack_edf(const Edf &edf)
Definition: bpt_utils.h:189
FERMAT_FORCEINLINE FERMAT_HOST_DEVICE float p(const cugar::DifferentialGeometry &geometry, const cugar::Vector3f w_i, const cugar::Vector3f w_o, const cugar::SphericalMeasure measure=cugar::kProjectedSolidAngle, const bool RR=true, const ComponentType components=kAllComponents) const
Definition: bsdf.h:474
Definition: bpt_options.h:42