17#include <optix_world.h>
18#include <optixu/optixu_math_namespace.h>
19#include <optixu/optixu_matrix_namespace.h>
21#include "RayTracing.cuh"
26rtDeclareVariable(optix::Ray, ray, rtCurrentRay, );
27rtDeclareVariable(
float, t_hit, rtIntersectionDistance, );
28rtDeclareVariable(
PerRayData, prd, rtPayload, );
30rtDeclareVariable(
unsigned int, UUID, attribute UUID, );
42static __device__ __inline__ float3 glass_tau_rho_alpha(
float cos_theta,
float n,
float KL) {
43 cos_theta = fmaxf(1e-4f, fminf(1.f, cos_theta));
45 const float sin_t = sinf(theta);
46 const float sin_tr = sin_t / n;
47 const float cos_tr = sqrtf(fmaxf(0.f, 1.f - sin_tr * sin_tr));
52 const float r0 = ((n - 1.f) / (n + 1.f)) * ((n - 1.f) / (n + 1.f));
56 const float s_minus = sinf(theta_r - theta);
57 const float s_plus = sinf(theta_r + theta);
58 const float t_minus = tanf(theta_r - theta);
59 const float t_plus = tanf(theta_r + theta);
60 r_per = (s_minus * s_minus) / fmaxf(1e-12f, s_plus * s_plus);
61 r_par = (t_minus * t_minus) / fmaxf(1e-12f, t_plus * t_plus);
64 const float tau_a = (KL > 0.f) ? expf(-KL / fmaxf(1e-4f, cos_tr)) : 1.f;
66 float tau = 0.f, rho = 0.f;
67 for (
int pol = 0; pol < 2; pol++) {
68 const float r = (pol == 0) ? r_per : r_par;
69 const float denom = fmaxf(1e-6f, 1.f - (r * tau_a) * (r * tau_a));
70 const float tau_i = tau_a * (1.f - r) * (1.f - r) / denom;
71 const float rho_i = r * (1.f + tau_a * tau_i);
75 tau = fmaxf(0.f, fminf(1.f, tau));
76 rho = fmaxf(0.f, fminf(1.f, rho));
77 float alpha = 1.f - tau - rho;
81 return make_float3(tau, rho, alpha);
88static __device__ __inline__
float coverNormalFaceCos(
uint hit_position,
const float3 &ray_dir,
bool &face_top) {
90 for (
uint i = 0; i < 16; i++) {
91 m[i] = transform_matrix[optix::make_uint2(i, hit_position)];
93 float3 normal = make_float3(0.f, 0.f, 1.f);
94 const uint ptype = primitive_type[hit_position];
95 if (ptype == 0 || ptype == 3) {
96 float3 s0 = make_float3(0, 0, 0), s1 = make_float3(1, 0, 0), s2 = make_float3(0, 1, 0);
97 d_transformPoint(m, s0);
98 d_transformPoint(m, s1);
99 d_transformPoint(m, s2);
100 normal =
cross(s1 - s0, s2 - s0);
101 }
else if (ptype == 1) {
102 float3 v0 = make_float3(0, 0, 0), v1 = make_float3(0, 1, 0), v2 = make_float3(1, 1, 0);
103 d_transformPoint(m, v0);
104 d_transformPoint(m, v1);
105 d_transformPoint(m, v2);
106 normal =
cross(v1 - v0, v2 - v0);
107 }
else if (ptype == 2) {
108 float3 v0 = make_float3(0, 0, 0), v1 = make_float3(1, 0, 0), v2 = make_float3(0, 1, 0);
109 d_transformPoint(m, v0);
110 d_transformPoint(m, v1);
111 d_transformPoint(m, v2);
112 normal =
cross(v1 - v0, v2 - v0);
114 const float nmag = d_magnitude(normal);
119 normal = normal / nmag;
120 face_top = dot(normal, ray_dir) < 0.f;
121 return fminf(1.f, fabsf(dot(ray_dir, normal)));
124RT_PROGRAM
void closest_hit_direct() {
126 uint hit_position = primitive_positions[UUID];
129 if (hit_position == UINT_MAX) {
133 if ((periodic_flag.x == 1 || periodic_flag.y == 1) && primitive_type[hit_position] == 5) {
135 prd.hit_periodic_boundary =
true;
137 float3 ray_origin = ray.origin + t_hit * ray.direction;
141 float2 xbounds = make_float2(bbox_vertices[
make_uint2(0, 0)].x, bbox_vertices[
make_uint2(1, 1)].x);
142 float2 ybounds = make_float2(bbox_vertices[
make_uint2(0, 0)].y, bbox_vertices[
make_uint2(1, 1)].y);
144 float width_x = xbounds.y - xbounds.x;
145 float width_y = ybounds.y - ybounds.x;
147 prd.periodic_hit = ray_origin;
148 if (periodic_flag.x == 1 && fabs(ray_origin.x - xbounds.x) <= eps) {
149 prd.periodic_hit.x += +width_x - eps;
150 }
else if (periodic_flag.x == 1 && fabs(ray_origin.x - xbounds.y) <= eps) {
151 prd.periodic_hit.x += -width_x + eps;
152 }
else if (periodic_flag.y == 1 && fabs(ray_origin.y - ybounds.x) <= eps) {
153 prd.periodic_hit.y += +width_y - eps;
154 }
else if (periodic_flag.y == 1 && fabs(ray_origin.y - ybounds.y) <= eps) {
155 prd.periodic_hit.y += -width_y + eps;
160RT_PROGRAM
void closest_hit_diffuse() {
163 uint origin_UUID = prd.origin_UUID;
164 uint origin_position = primitive_positions[origin_UUID];
165 uint hit_position = primitive_positions[UUID];
168 if (origin_position == UINT_MAX || hit_position == UINT_MAX) {
177 if ((periodic_flag.x == 1 || periodic_flag.y == 1) && primitive_type[hit_position] == 5) {
179 prd.hit_periodic_boundary =
true;
181 float3 ray_origin = ray.origin + t_hit * ray.direction;
185 float2 xbounds = make_float2(bbox_vertices[
make_uint2(0, 0)].x, bbox_vertices[
make_uint2(1, 1)].x);
186 float2 ybounds = make_float2(bbox_vertices[
make_uint2(0, 0)].y, bbox_vertices[
make_uint2(1, 1)].y);
188 float width_x = xbounds.y - xbounds.x;
189 float width_y = ybounds.y - ybounds.x;
191 prd.periodic_hit = ray_origin;
192 if (periodic_flag.x == 1 && fabs(ray_origin.x - xbounds.x) <= eps) {
193 prd.periodic_hit.x += +width_x - eps;
194 }
else if (periodic_flag.x == 1 && fabs(ray_origin.x - xbounds.y) <= eps) {
195 prd.periodic_hit.x += -width_x + eps;
196 }
else if (periodic_flag.y == 1 && fabs(ray_origin.y - ybounds.x) <= eps) {
197 prd.periodic_hit.y += +width_y - eps;
198 }
else if (periodic_flag.y == 1 && fabs(ray_origin.y - ybounds.y) <= eps) {
199 prd.periodic_hit.y += -width_y + eps;
210 for (
uint i = 0; i < 16; i++) {
211 m[i] = transform_matrix[optix::make_uint2(i, hit_position)];
214 if (primitive_type[hit_position] == 0 || primitive_type[hit_position] == 3) {
215 float3 s0 = make_float3(0, 0, 0);
216 float3 s1 = make_float3(1, 0, 0);
217 float3 s2 = make_float3(0, 1, 0);
218 d_transformPoint(m, s0);
219 d_transformPoint(m, s1);
220 d_transformPoint(m, s2);
221 normal =
cross(s1 - s0, s2 - s0);
222 }
else if (primitive_type[hit_position] == 1) {
223 float3 v0 = make_float3(0, 0, 0);
224 d_transformPoint(m, v0);
225 float3 v1 = make_float3(0, 1, 0);
226 d_transformPoint(m, v1);
227 float3 v2 = make_float3(1, 1, 0);
228 d_transformPoint(m, v2);
229 normal =
cross(v1 - v0, v2 - v0);
230 }
else if (primitive_type[hit_position] == 2) {
231 float3 v0 = make_float3(0, 0, 0);
232 d_transformPoint(m, v0);
233 float3 v1 = make_float3(1, 0, 0);
234 d_transformPoint(m, v1);
235 float3 v2 = make_float3(0, 1, 0);
236 d_transformPoint(m, v2);
237 normal =
cross(v1 - v0, v2 - v0);
238 }
else if (primitive_type[hit_position] == 4) {
239 float3 vmin = make_float3(-0.5, -0.5, -0.5);
240 d_transformPoint(m, vmin);
241 float3 vmax = make_float3(0.5, 0.5, 0.5);
242 d_transformPoint(m, vmax);
244 normal = normalize(normal);
246 bool face = dot(normal, ray.direction) < 0;
249 for (
int b_global = 0; b_global < Nbands_global; b_global++) {
251 if (band_launch_flag[b_global] == 0) {
259 size_t ind_origin = rad_indexer(origin_position, b);
260 size_t ind_hit = rad_indexer(hit_position, b);
263 if (face || primitive_type[hit_position] == 4) {
264 strength = radiation_out_top[ind_hit] * prd.strength;
266 strength = radiation_out_bottom[ind_hit] * prd.strength;
274 size_t radprop_ind_global = mat_indexer(prd.source_ID, origin_position, b_global);
275 float t_rho = rho[radprop_ind_global];
276 float t_tau = tau[radprop_ind_global];
279 if (primitive_type[origin_position] == 4) {
294 float absorption_factor = 1.f - t_rho - t_tau;
295 float contribution = strength * absorption_factor;
299 if (absorption_factor < -1e-5f) {
300 printf(
"ERROR: Negative absorption! rho=%.6f, tau=%.6f, origin_UUID=%u\n", t_rho, t_tau, origin_UUID);
301 absorption_factor = 0.f;
304 atomicAdd(&radiation_in[ind_origin], contribution);
306 if ((t_rho > 0 || t_tau > 0) && strength > 0) {
308 atomicFloatAdd(&scatter_buff_top[ind_origin], strength * t_rho);
309 atomicFloatAdd(&scatter_buff_bottom[ind_origin], strength * t_tau);
311 atomicFloatAdd(&scatter_buff_bottom[ind_origin], strength * t_rho);
312 atomicFloatAdd(&scatter_buff_top[ind_origin], strength * t_tau);
317 size_t indc = cam_mat_indexer(prd.source_ID, origin_position, b_global, camera_ID);
318 float t_rho_cam = rho_cam[indc];
319 float t_tau_cam = tau_cam[indc];
320 if ((t_rho_cam > 0 || t_tau_cam > 0) && strength > 0) {
322 atomicFloatAdd(&scatter_buff_top_cam[ind_origin], strength * t_rho_cam);
323 atomicFloatAdd(&scatter_buff_bottom_cam[ind_origin], strength * t_tau_cam);
325 atomicFloatAdd(&scatter_buff_bottom_cam[ind_origin], strength * t_rho_cam);
326 atomicFloatAdd(&scatter_buff_top_cam[ind_origin], strength * t_tau_cam);
345RT_PROGRAM
void closest_hit_camera() {
348 uint hit_position = primitive_positions[UUID];
351 if (hit_position == UINT_MAX) {
356 uint pixel_index = prd.origin_UUID;
357 size_t Npixels = camera_resolution_full.x * camera_resolution_full.y;
364 if ((periodic_flag.x == 1 || periodic_flag.y == 1) && primitive_type[hit_position] == 5) {
366 prd.hit_periodic_boundary =
true;
368 float3 ray_origin = ray.origin + t_hit * ray.direction;
372 float2 xbounds = make_float2(bbox_vertices[
make_uint2(0, 0)].x, bbox_vertices[
make_uint2(1, 1)].x);
373 float2 ybounds = make_float2(bbox_vertices[
make_uint2(0, 0)].y, bbox_vertices[
make_uint2(1, 1)].y);
375 float width_x = xbounds.y - xbounds.x;
376 float width_y = ybounds.y - ybounds.x;
378 prd.periodic_hit = ray_origin;
379 if (periodic_flag.x == 1 && fabs(ray_origin.x - xbounds.x) <= eps) {
380 prd.periodic_hit.x += +width_x - eps;
381 }
else if (periodic_flag.x == 1 && fabs(ray_origin.x - xbounds.y) <= eps) {
382 prd.periodic_hit.x += -width_x + eps;
383 }
else if (periodic_flag.y == 1 && fabs(ray_origin.y - ybounds.x) <= eps) {
384 prd.periodic_hit.y += +width_y - eps;
385 }
else if (periodic_flag.y == 1 && fabs(ray_origin.y - ybounds.y) <= eps) {
386 prd.periodic_hit.y += -width_y + eps;
397 for (
uint i = 0; i < 16; i++) {
398 m[i] = transform_matrix[optix::make_uint2(i, hit_position)];
401 if (primitive_type[hit_position] == 0 || primitive_type[hit_position] == 3) {
402 float3 s0 = make_float3(0, 0, 0);
403 float3 s1 = make_float3(1, 0, 0);
404 float3 s2 = make_float3(0, 1, 0);
405 d_transformPoint(m, s0);
406 d_transformPoint(m, s1);
407 d_transformPoint(m, s2);
408 normal =
cross(s1 - s0, s2 - s0);
409 }
else if (primitive_type[hit_position] == 1) {
410 float3 v0 = make_float3(0, 0, 0);
411 d_transformPoint(m, v0);
412 float3 v1 = make_float3(0, 1, 0);
413 d_transformPoint(m, v1);
414 float3 v2 = make_float3(1, 1, 0);
415 d_transformPoint(m, v2);
416 normal =
cross(v1 - v0, v2 - v0);
417 }
else if (primitive_type[hit_position] == 2) {
418 float3 v0 = make_float3(0, 0, 0);
419 d_transformPoint(m, v0);
420 float3 v1 = make_float3(1, 0, 0);
421 d_transformPoint(m, v1);
422 float3 v2 = make_float3(0, 1, 0);
423 d_transformPoint(m, v2);
424 normal =
cross(v1 - v0, v2 - v0);
425 }
else if (primitive_type[hit_position] == 4) {
426 float3 vmin = make_float3(-0.5, -0.5, -0.5);
427 d_transformPoint(m, vmin);
428 float3 vmax = make_float3(0.5, 0.5, 0.5);
429 d_transformPoint(m, vmax);
431 normal = normalize(normal);
433 bool face = dot(normal, ray.direction) < 0;
436 float3 camera_normal = d_rotatePoint(make_float3(0, 0, 1), -0.5 * M_PI + camera_direction.x, 0.5f * M_PI - camera_direction.y);
439 for (
size_t b = 0; b < Nbands_launch; b++) {
442 float source_radiance = 0.0f;
443 for (
uint s = 0; s < Nsources; s++) {
444 float flux = source_fluxes[s * Nbands_launch + b];
448 uint source_type = source_types[s];
450 if (source_type == 1) {
452 float radius = source_widths[s].x * 0.5f;
453 float3 oc = ray.origin - source_positions[s];
454 float b = dot(oc, ray.direction);
455 float c = dot(oc, oc) - radius * radius;
456 float discriminant = b * b - c;
458 if (discriminant >= 0.0f) {
459 float t_sphere = -b - sqrtf(discriminant);
460 if (t_sphere > 0.0f && t_sphere < t_hit) {
461 float area = 4.0f *
M_PI * radius * radius;
462 source_radiance += (flux / area) / M_PI;
465 }
else if (source_type == 3) {
468 d_makeTransformMatrix(source_rotations[s], transform);
469 float3 normal = make_float3(transform[2], transform[6], transform[10]);
471 float denom = dot(ray.direction, normal);
472 if (denom < -1e-6f) {
473 float3 oc = source_positions[s] - ray.origin;
474 float t_rect = dot(oc, normal) / denom;
476 if (t_rect > 0.0f && t_rect < t_hit) {
477 float3 hit_point = ray.origin + t_rect * ray.direction;
478 float3 local_hit = hit_point - source_positions[s];
479 float inv_transform[16];
480 d_invertMatrix(transform, inv_transform);
481 d_transformPoint(inv_transform, local_hit);
483 if (fabsf(local_hit.x) <= source_widths[s].x * 0.5f && fabsf(local_hit.y) <= source_widths[s].y * 0.5f) {
484 float area = source_widths[s].x * source_widths[s].y;
485 float cos_angle = -denom;
486 source_radiance += (flux / area) * cos_angle / M_PI;
490 }
else if (source_type == 4) {
493 d_makeTransformMatrix(source_rotations[s], transform);
494 float3 normal = make_float3(transform[2], transform[6], transform[10]);
496 float denom = dot(ray.direction, normal);
497 if (denom < -1e-6f) {
498 float3 oc = source_positions[s] - ray.origin;
499 float t_disk = dot(oc, normal) / denom;
501 if (t_disk > 0.0f && t_disk < t_hit) {
502 float3 hit_point = ray.origin + t_disk * ray.direction;
503 float3 offset = hit_point - source_positions[s];
504 float dist_sq = dot(offset, offset);
506 float radius = source_widths[s].x;
507 if (dist_sq <= radius * radius) {
508 float area =
M_PI * radius * radius;
509 float cos_angle = -denom;
510 source_radiance += (flux / area) * cos_angle / M_PI;
518 size_t ind_hit = rad_indexer(hit_position, b);
520 if (face || primitive_type[hit_position] == 4) {
521 strength = radiation_out_top[ind_hit] * prd.strength;
523 strength = radiation_out_bottom[ind_hit] * prd.strength;
526 if (source_radiance > 0.0f) {
527 strength += source_radiance * prd.strength;
534 double strength_spec = 0;
535 if (specular_reflection_enabled > 0 && specular_exponent[hit_position] > 0.f && scattering_iteration == 0) {
538 for (
int rr = 0; rr < Nsources; rr++) {
543 size_t ind_specular = spec_indexer(rr, camera_ID, hit_position, b);
544 float spec = radiation_specular[ind_specular];
552 float3 light_direction;
553 if (source_types[rr] == 0 || source_types[rr] == 2) {
555 light_direction = normalize(source_positions[rr]);
558 float3 hit_point = ray.origin + t_hit * ray.direction;
559 light_direction = normalize(source_positions[rr] - hit_point);
563 float3 specular_direction = normalize(light_direction - ray.direction);
565 float exponent = specular_exponent[hit_position];
566 double scale_coefficient = 1.0;
567 if (specular_reflection_enabled == 2) {
568 scale_coefficient = specular_scale[hit_position];
571 strength_spec += spec * scale_coefficient * pow(
max(0.f, dot(specular_direction, normal)), exponent) * (exponent + 2.f) /
572 (
double(launch_dim.x) * 2.f *
M_PI);
580 size_t ind_camera = rad_indexer(pixel_index, b);
582 atomicAdd(&radiation_in_camera[ind_camera],
583 (strength + strength_spec) / M_PI);
588RT_PROGRAM
void closest_hit_pixel_label() {
590 uint origin_UUID = prd.origin_UUID;
592 uint hit_position = primitive_positions[UUID];
594 if ((periodic_flag.x == 1 || periodic_flag.y == 1) && primitive_type[hit_position] == 5) {
596 prd.hit_periodic_boundary =
true;
598 float3 ray_origin = ray.origin + t_hit * ray.direction;
602 float2 xbounds = make_float2(bbox_vertices[
make_uint2(0, 0)].x, bbox_vertices[
make_uint2(1, 1)].x);
603 float2 ybounds = make_float2(bbox_vertices[
make_uint2(0, 0)].y, bbox_vertices[
make_uint2(1, 1)].y);
605 float width_x = xbounds.y - xbounds.x;
606 float width_y = ybounds.y - ybounds.x;
608 prd.periodic_hit = ray_origin;
609 if (periodic_flag.x == 1 && fabs(ray_origin.x - xbounds.x) <= eps) {
610 prd.periodic_hit.x += +width_x - eps;
611 }
else if (periodic_flag.x == 1 && fabs(ray_origin.x - xbounds.y) <= eps) {
612 prd.periodic_hit.x += -width_x + eps;
613 }
else if (periodic_flag.y == 1 && fabs(ray_origin.y - ybounds.x) <= eps) {
614 prd.periodic_hit.y += +width_y - eps;
615 }
else if (periodic_flag.y == 1 && fabs(ray_origin.y - ybounds.y) <= eps) {
616 prd.periodic_hit.y += -width_y + eps;
623 camera_pixel_label[origin_UUID] = UUID + 1;
625 float depth = prd.strength + t_hit;
626 float3 camera_direction3 = d_rotatePoint(make_float3(1, 0, 0), -0.5 * M_PI + camera_direction.x, 0.5f * M_PI - camera_direction.y);
627 camera_pixel_depth[origin_UUID] = abs(dot(camera_direction3, ray.direction)) * depth;
641RT_PROGRAM
void any_hit_direct() {
643 if (glass_enabled == 0u) {
647 uint hit_position = primitive_positions[UUID];
648 if (hit_position == UINT_MAX) {
652 if (UUID == prd.origin_UUID) {
653 rtIgnoreIntersection();
667 for (
int b_global = 0; b_global < Nbands_global; b_global++) {
668 if (band_launch_flag[b_global] == 0) {
672 size_t mat_ind = mat_indexer(prd.source_ID, hit_position, b_global);
673 if (is_glass[mat_ind] == 0.f) {
680 float cos_theta = coverNormalFaceCos(hit_position, ray.direction, face_top);
683 for (
int b_global = 0; b_global < Nbands_global; b_global++) {
684 if (band_launch_flag[b_global] == 0) {
688 if (b >= HELIOS_MAX_RADIATION_BANDS) {
692 size_t mat_ind = mat_indexer(prd.source_ID, hit_position, b_global);
693 float3 tra = glass_tau_rho_alpha(cos_theta, glass_n[mat_ind], glass_KL[mat_ind]);
695 size_t flux_idx = source_flux_indexer(prd.source_ID, b);
696 double ext_flux = source_fluxes[flux_idx];
697 double incoming = prd.strength * ext_flux * (double) prd.cover_transmittance[b];
699 size_t cov_ind = rad_indexer(hit_position, b);
700 if (incoming > 0.0) {
701 atomicFloatAdd(&radiation_in[cov_ind], (
float) (incoming * (
double) tra.z));
704 atomicFloatAdd(&scatter_buff_top[cov_ind], (
float) (incoming * (
double) tra.y));
706 atomicFloatAdd(&scatter_buff_bottom[cov_ind], (
float) (incoming * (
double) tra.y));
710 prd.cover_transmittance[b] *= tra.x;
714 rtIgnoreIntersection();
717RT_PROGRAM
void any_hit_diffuse() {
719 if (glass_enabled == 0u) {
723 uint hit_position = primitive_positions[UUID];
724 if (hit_position == UINT_MAX) {
727 if (UUID == prd.origin_UUID) {
728 rtIgnoreIntersection();
739 for (
int b_global = 0; b_global < Nbands_global; b_global++) {
740 if (band_launch_flag[b_global] == 0) {
744 size_t mat_ind = mat_indexer(prd.source_ID, hit_position, b_global);
745 if (is_glass[mat_ind] == 0.f) {
752 float cos_theta = coverNormalFaceCos(hit_position, ray.direction, face_top);
755 for (
int b_global = 0; b_global < Nbands_global; b_global++) {
756 if (band_launch_flag[b_global] == 0) {
760 if (b >= HELIOS_MAX_RADIATION_BANDS) {
764 size_t mat_ind = mat_indexer(prd.source_ID, hit_position, b_global);
765 float3 tra = glass_tau_rho_alpha(cos_theta, glass_n[mat_ind], glass_KL[mat_ind]);
767 double ext_flux = diffuse_flux[b];
768 double incoming = prd.strength * ext_flux * (double) prd.cover_transmittance[b];
770 size_t cov_ind = rad_indexer(hit_position, b);
771 if (incoming > 0.0) {
772 atomicFloatAdd(&radiation_in[cov_ind], (
float) (incoming * (
double) tra.z));
774 atomicFloatAdd(&scatter_buff_top[cov_ind], (
float) (incoming * (
double) tra.y));
776 atomicFloatAdd(&scatter_buff_bottom[cov_ind], (
float) (incoming * (
double) tra.y));
780 prd.cover_transmittance[b] *= tra.x;
784 rtIgnoreIntersection();
787RT_PROGRAM
void miss_direct() {
790 uint origin_position = primitive_positions[prd.origin_UUID];
801 for (
int b_global = 0; b_global < Nbands_global; b_global++) {
803 if (band_launch_flag[b_global] == 0) {
809 size_t ind_origin = rad_indexer(origin_position, b);
812 size_t radprop_ind_global = mat_indexer(prd.source_ID, origin_position, b_global);
813 float t_rho = rho[radprop_ind_global];
814 float t_tau = tau[radprop_ind_global];
817 size_t flux_idx = source_flux_indexer(prd.source_ID, b);
818 float source_flux = source_fluxes[flux_idx];
820 float cover_tau = (b < HELIOS_MAX_RADIATION_BANDS) ? prd.cover_transmittance[b] : 1.f;
821 double strength = prd.strength * source_flux * cover_tau;
822 float absorption = strength * (1.f - t_rho - t_tau);
825 atomicAdd(&radiation_in[ind_origin], absorption);
827 if (t_rho > 0 || t_tau > 0) {
829 atomicFloatAdd(&scatter_buff_top[ind_origin], strength * t_rho);
830 atomicFloatAdd(&scatter_buff_bottom[ind_origin], strength * t_tau);
832 atomicFloatAdd(&scatter_buff_bottom[ind_origin], strength * t_rho);
833 atomicFloatAdd(&scatter_buff_top[ind_origin], strength * t_tau);
838 size_t indc = cam_mat_indexer(prd.source_ID, origin_position, b_global, camera_ID);
839 float t_rho_cam = rho_cam[indc];
840 float t_tau_cam = tau_cam[indc];
841 if ((t_rho_cam > 0 || t_tau_cam > 0) && strength > 0) {
843 atomicFloatAdd(&scatter_buff_top_cam[ind_origin], strength * t_rho_cam);
844 atomicFloatAdd(&scatter_buff_bottom_cam[ind_origin], strength * t_tau_cam);
846 atomicFloatAdd(&scatter_buff_bottom_cam[ind_origin], strength * t_rho_cam);
847 atomicFloatAdd(&scatter_buff_top_cam[ind_origin], strength * t_tau_cam);
857 for (
unsigned int cam = 0; cam < Ncameras; cam++) {
859 size_t weight_ind = source_cam_flux_indexer(prd.source_ID, b, cam);
860 float camera_weight = source_fluxes_cam[weight_ind];
862 size_t ind_specular = spec_indexer(prd.source_ID, cam, origin_position, b);
863 atomicFloatAdd(&radiation_specular[ind_specular], strength * camera_weight);
875__device__
float evaluateDiffuseAngularDistribution(
const float3 &ray_dir,
const float3 &peak_dir,
float power_law_K,
float power_law_norm,
const float4 &prague_params) {
878 if (power_law_K > 0.0f) {
879 float psi =
acos_safe(dot(peak_dir, ray_dir));
880 psi = fmaxf(psi, M_PI / 180.0f);
881 return powf(psi, -power_law_K) * power_law_norm;
885 if (prague_params.w > 0.0f) {
887 float gamma =
acos_safe(dot(ray_dir, peak_dir)) * 180.0f / float(M_PI);
890 float cos_theta = fmaxf(ray_dir.z, 0.0f);
894 float pattern = (1.0f + prague_params.x * expf(-gamma / prague_params.y)) * (1.0f + (prague_params.z - 1.0f) * (1.0f - cos_theta));
898 return pattern * prague_params.w *
M_PI;
907RT_PROGRAM
void miss_diffuse() {
910 uint origin_position = primitive_positions[prd.origin_UUID];
918 for (
size_t b_global = 0; b_global < Nbands_global; b_global++) {
920 if (band_launch_flag[b_global] == 0) {
925 if (diffuse_flux[b] > 0.f) {
928 size_t ind_origin = rad_indexer(origin_position, b);
931 size_t radprop_ind_global = mat_indexer(prd.source_ID, origin_position, b_global);
932 float t_rho = rho[radprop_ind_global];
933 float t_tau = tau[radprop_ind_global];
936 float cover_tau = (b < HELIOS_MAX_RADIATION_BANDS) ? prd.cover_transmittance[b] : 1.f;
939 if (primitive_type[origin_position] == 4) {
942 float sigma_s = t_tau;
943 float beta = kappa + sigma_s;
946 atomicAdd(&radiation_in[ind_origin], diffuse_flux[b] * prd.strength * cover_tau * kappa / beta);
949 atomicAdd(&scatter_buff_top[ind_origin], diffuse_flux[b] * prd.strength * cover_tau * sigma_s / beta);
954 float fd = evaluateDiffuseAngularDistribution(ray.direction, diffuse_peak_dir[b], diffuse_extinction[b], diffuse_dist_norm[b], sky_radiance_params[b]);
956 float strength = fd * diffuse_flux[b] * prd.strength * cover_tau;
959 atomicAdd(&radiation_in[ind_origin], strength * (1.f - t_rho - t_tau));
961 if (t_rho > 0 || t_tau > 0) {
963 atomicFloatAdd(&scatter_buff_top[ind_origin], strength * t_rho);
964 atomicFloatAdd(&scatter_buff_bottom[ind_origin], strength * t_tau);
966 atomicFloatAdd(&scatter_buff_bottom[ind_origin], strength * t_rho);
967 atomicFloatAdd(&scatter_buff_top[ind_origin], strength * t_tau);
972 size_t indc = cam_mat_indexer(prd.source_ID, origin_position, b_global, camera_ID);
973 float t_rho_cam = rho_cam[indc];
974 float t_tau_cam = tau_cam[indc];
975 if ((t_rho_cam > 0 || t_tau_cam > 0) && prd.strength > 0) {
977 atomicFloatAdd(&scatter_buff_top_cam[ind_origin], strength * t_rho_cam);
978 atomicFloatAdd(&scatter_buff_bottom_cam[ind_origin], strength * t_tau_cam);
980 atomicFloatAdd(&scatter_buff_bottom_cam[ind_origin], strength * t_rho_cam);
981 atomicFloatAdd(&scatter_buff_top_cam[ind_origin], strength * t_tau_cam);
992RT_PROGRAM
void miss_camera() {
995 uint pixel_index = prd.origin_UUID;
996 size_t Npixels = camera_resolution_full.x * camera_resolution_full.y;
1001 for (
size_t b = 0; b < Nbands_launch; b++) {
1003 float radiance = 0.0f;
1006 for (
uint s = 0; s < Nsources; s++) {
1007 float flux = source_fluxes[s * Nbands_launch + b];
1011 uint source_type = source_types[s];
1013 if (source_type == 0 || source_type == 2) {
1015 float cos_sun_angle = dot(ray.direction, sun_direction);
1016 if (cos_sun_angle >= solar_disk_cos_angle && solar_disk_radiance[b] > 0.0f) {
1017 radiance += solar_disk_radiance[b];
1019 }
else if (source_type == 1) {
1021 float radius = source_widths[s].x * 0.5f;
1022 if (d_raySphereIntersect(ray.origin, ray.direction, source_positions[s], radius)) {
1023 float area = 4.0f *
M_PI * radius * radius;
1024 radiance += (flux / area) / M_PI;
1026 }
else if (source_type == 3) {
1029 if (d_rayRectangleIntersect(ray.origin, ray.direction, source_positions[s], source_widths[s].x, source_widths[s].y, source_rotations[s], cos_angle)) {
1030 float area = source_widths[s].x * source_widths[s].y;
1031 radiance += (flux / area) * cos_angle / M_PI;
1033 }
else if (source_type == 4) {
1036 float radius = source_widths[s].x;
1037 if (d_rayDiskIntersect(ray.origin, ray.direction, source_positions[s], radius, source_rotations[s], cos_angle)) {
1038 float area =
M_PI * radius * radius;
1039 radiance += (flux / area) * cos_angle / M_PI;
1045 if (radiance <= 0.0f && camera_sky_radiance[b] > 0.f) {
1049 float angular_weight = evaluateDiffuseAngularDistribution(ray.direction, sun_direction,
1052 sky_radiance_params[b]);
1054 radiance = camera_sky_radiance[b] * angular_weight;
1059 if (band_emission_flag[b] != 0u && camera_diffuse_flux[b] > 0.f) {
1060 radiance += camera_diffuse_flux[b] /
M_PI;
1063 if (radiance > 0.0f) {
1068 size_t ind_camera = rad_indexer(pixel_index, b);
1069 atomicAdd(&radiation_in_camera[ind_camera], radiance * prd.strength);
1074RT_PROGRAM
void miss_pixel_label() {
1076 camera_pixel_depth[prd.origin_UUID] = -1;