17#include <optix_device.h>
30static __forceinline__ __device__
unsigned int lcg(
unsigned int &prev) {
31 const unsigned int LCG_A = 1664525u;
32 const unsigned int LCG_C = 1013904223u;
33 prev = (LCG_A * prev + LCG_C);
34 return prev & 0x00FFFFFF;
37static __forceinline__ __device__
float rnd(
unsigned int &prev) {
38 return (
float)lcg(prev) / (float)0x01000000;
41template<
unsigned int N>
42static __forceinline__ __device__
unsigned int tea(
unsigned int val0,
unsigned int val1) {
43 unsigned int v0 = val0, v1 = val1, s0 = 0;
44 for (
unsigned int n = 0; n < N; n++) {
46 v0 += ((v1 << 4) + 0xa341316c) ^ (v1 + s0) ^ ((v1 >> 5) + 0xc8013ea4);
47 v1 += ((v0 << 4) + 0xad90777d) ^ (v0 + s0) ^ ((v0 >> 5) + 0x7e95761e);
52__device__ __forceinline__
void atomicFloatAdd(
float *address,
float val) {
53 atomicAdd(address, val);
56__device__ __forceinline__
void d_transformPoint(
const float (&T)[16], float3 &v) {
58 V.x = T[0]*v.x + T[1]*v.y + T[2]*v.z + T[3];
59 V.y = T[4]*v.x + T[5]*v.y + T[6]*v.z + T[7];
60 V.z = T[8]*v.x + T[9]*v.y + T[10]*v.z + T[11];
64__device__ __forceinline__ float3 d_rotatePoint(
const float3 &pos,
float theta,
float phi) {
65 float st = sinf(theta), ct = cosf(theta);
66 float sp = sinf(phi), cp = cosf(phi);
68 tmp.x = cp*ct*pos.x + (-sp)*pos.y + cp*st*pos.z;
69 tmp.y = sp*ct*pos.x + cp*pos.y + sp*st*pos.z;
70 tmp.z = -st*pos.x + ct*pos.z;
74__device__ __forceinline__
float d_magnitude(
const float3 v) {
75 return sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);
78static __forceinline__ __device__
float acos_safe(
float x) {
79 return acosf(fmaxf(-1.f, fminf(1.f, x)));
82static __forceinline__ __device__
float asin_safe(
float x) {
83 return asinf(fmaxf(-1.f, fminf(1.f, x)));
91static __forceinline__ __device__ float3 glass_tau_rho_alpha(
float cos_theta,
float n,
float KL) {
92 cos_theta = fmaxf(1e-4f, fminf(1.f, cos_theta));
94 const float sin_t = sinf(theta);
95 const float sin_tr = sin_t / n;
96 const float cos_tr = sqrtf(fmaxf(0.f, 1.f - sin_tr * sin_tr));
103 const float r0 = ((n - 1.f) / (n + 1.f)) * ((n - 1.f) / (n + 1.f));
107 const float s_minus = sinf(theta_r - theta);
108 const float s_plus = sinf(theta_r + theta);
109 const float t_minus = tanf(theta_r - theta);
110 const float t_plus = tanf(theta_r + theta);
111 r_per = (s_minus * s_minus) / fmaxf(1e-12f, s_plus * s_plus);
112 r_par = (t_minus * t_minus) / fmaxf(1e-12f, t_plus * t_plus);
116 const float tau_a = (KL > 0.f) ? expf(-KL / fmaxf(1e-4f, cos_tr)) : 1.f;
119 float tau = 0.f, rho = 0.f;
121 for (
int pol = 0; pol < 2; pol++) {
122 const float r = (pol == 0) ? r_per : r_par;
123 const float denom = fmaxf(1e-6f, 1.f - (r * tau_a) * (r * tau_a));
124 const float tau_i = tau_a * (1.f - r) * (1.f - r) / denom;
125 const float rho_i = r * (1.f + tau_a * tau_i);
129 tau = fmaxf(0.f, fminf(1.f, tau));
130 rho = fmaxf(0.f, fminf(1.f, rho));
131 float alpha = 1.f - tau - rho;
132 if (alpha < 0.f) { alpha = 0.f; }
133 return make_float3(tau, rho, alpha);
137static __forceinline__ __device__
void initCoverTransmittance(
PerRayData &prd) {
139 for (
int i = 0; i < HELIOS_MAX_RADIATION_BANDS; i++) {
148static __device__
float evaluateDiffuseAngularDistribution(
const float3 &ray_dir,
const float3 &peak_dir,
149 float power_law_K,
float power_law_norm,
150 const float4 &sky_params) {
151 if (power_law_K > 0.f) {
152 float psi =
acos_safe(dot(peak_dir, ray_dir));
153 psi = fmaxf(psi,
M_PI / 180.f);
154 return powf(psi, -power_law_K) * power_law_norm;
156 if (sky_params.w > 0.f) {
157 float gamma =
acos_safe(dot(ray_dir, peak_dir)) * 180.f /
M_PI;
158 float cos_theta = fmaxf(ray_dir.z, 0.f);
159 float pattern = (1.f + sky_params.x * expf(-gamma / sky_params.y))
160 * (1.f + (sky_params.z - 1.f) * (1.f - cos_theta));
161 return pattern * sky_params.w *
M_PI;
167__device__ __forceinline__
void loadTransformMatrix(uint32_t pos,
float (&T)[16]) {
168 for (
int i = 0; i < 16; i++) {
177static __forceinline__ __device__
bool sampleMask(int32_t msk_id,
float uv_u,
float uv_v) {
178 if (msk_id < 0)
return true;
179 const int32_t width = params.
mask_sizes[msk_id * 2];
180 const int32_t height = params.
mask_sizes[msk_id * 2 + 1];
182 int ix = (int)(floorf(
float(width - 1) * uv_u));
183 int iy = (int)(floorf(
float(height - 1) * (1.f - uv_v)));
184 ix =
max(0,
min(ix, width - 1));
185 iy =
max(0,
min(iy, height - 1));
186 return params.
mask_data[offset + (uint32_t)(iy * width + ix)] != 0u;
191static __forceinline__ __device__
void d_makeTransformMatrix(float3 rotation,
float (&T)[16]) {
192 float sx = sinf(rotation.x), cx = cosf(rotation.x);
193 float sy = sinf(rotation.y), cy = cosf(rotation.y);
194 float sz = sinf(rotation.z), cz = cosf(rotation.z);
195 T[0] = cz * cy; T[1] = cz * sy * sx - sz * cx; T[2] = cz * sy * cx + sz * sx; T[3] = 0.f;
196 T[4] = sz * cy; T[5] = sz * sy * sx + cz * cx; T[6] = sz * sy * cx - cz * sx; T[7] = 0.f;
197 T[8] = -sy; T[9] = cy * sx; T[10] = cy * cx; T[11] = 0.f;
198 T[12] = 0.f; T[13] = 0.f; T[14] = 0.f; T[15] = 1.f;
203static __forceinline__ __device__
void d_sampleDisk(uint32_t &seed, float3 &sample) {
204 float Rx = rnd(seed), Ry = rnd(seed);
205 float sp_x = -1.f + 2.f * Rx;
206 float sp_y = -1.f + 2.f * Ry;
209 if (sp_x > sp_y) { r = sp_x; p = sp_y / sp_x; }
210 else { r = sp_y; p = 2.f - sp_x / sp_y; }
212 if (sp_x < sp_y) { r = -sp_x; p = 4.f + sp_y / sp_x; }
213 else { r = -sp_y; p = (sp_y != 0.f) ? 6.f - sp_x / sp_y : 0.f; }
216 sample = make_float3(r * cosf(p), r * sinf(p), 0.f);
220static __forceinline__ __device__
void d_sampleSquare(uint32_t &seed, float3 &sample) {
221 sample = make_float3(-0.5f + rnd(seed), -0.5f + rnd(seed), 0.f);
225static __forceinline__ __device__
void d_invertMatrix(
const float (&m)[16],
float (&minv)[16]) {
227 inv[0] = m[5]*m[10]*m[15] - m[5]*m[11]*m[14] - m[9]*m[6]*m[15] + m[9]*m[7]*m[14] + m[13]*m[6]*m[11] - m[13]*m[7]*m[10];
228 inv[4] = -m[4]*m[10]*m[15] + m[4]*m[11]*m[14] + m[8]*m[6]*m[15] - m[8]*m[7]*m[14] - m[12]*m[6]*m[11] + m[12]*m[7]*m[10];
229 inv[8] = m[4]*m[9]*m[15] - m[4]*m[11]*m[13] - m[8]*m[5]*m[15] + m[8]*m[7]*m[13] + m[12]*m[5]*m[11] - m[12]*m[7]*m[9];
230 inv[12] = -m[4]*m[9]*m[14] + m[4]*m[10]*m[13] + m[8]*m[5]*m[14] - m[8]*m[6]*m[13] - m[12]*m[5]*m[10] + m[12]*m[6]*m[9];
231 inv[1] = -m[1]*m[10]*m[15] + m[1]*m[11]*m[14] + m[9]*m[2]*m[15] - m[9]*m[3]*m[14] - m[13]*m[2]*m[11] + m[13]*m[3]*m[10];
232 inv[5] = m[0]*m[10]*m[15] - m[0]*m[11]*m[14] - m[8]*m[2]*m[15] + m[8]*m[3]*m[14] + m[12]*m[2]*m[11] - m[12]*m[3]*m[10];
233 inv[9] = -m[0]*m[9]*m[15] + m[0]*m[11]*m[13] + m[8]*m[1]*m[15] - m[8]*m[3]*m[13] - m[12]*m[1]*m[11] + m[12]*m[3]*m[9];
234 inv[13] = m[0]*m[9]*m[14] - m[0]*m[10]*m[13] - m[8]*m[1]*m[14] + m[8]*m[2]*m[13] + m[12]*m[1]*m[10] - m[12]*m[2]*m[9];
235 inv[2] = m[1]*m[6]*m[15] - m[1]*m[7]*m[14] - m[5]*m[2]*m[15] + m[5]*m[3]*m[14] + m[13]*m[2]*m[7] - m[13]*m[3]*m[6];
236 inv[6] = -m[0]*m[6]*m[15] + m[0]*m[7]*m[14] + m[4]*m[2]*m[15] - m[4]*m[3]*m[14] - m[12]*m[2]*m[7] + m[12]*m[3]*m[6];
237 inv[10] = m[0]*m[5]*m[15] - m[0]*m[7]*m[13] - m[4]*m[1]*m[15] + m[4]*m[3]*m[13] + m[12]*m[1]*m[7] - m[12]*m[3]*m[5];
238 inv[14] = -m[0]*m[5]*m[14] + m[0]*m[6]*m[13] + m[4]*m[1]*m[14] - m[4]*m[2]*m[13] - m[12]*m[1]*m[6] + m[12]*m[2]*m[5];
239 inv[3] = -m[1]*m[6]*m[11] + m[1]*m[7]*m[10] + m[5]*m[2]*m[11] - m[5]*m[3]*m[10] - m[9]*m[2]*m[7] + m[9]*m[3]*m[6];
240 inv[7] = m[0]*m[6]*m[11] - m[0]*m[7]*m[10] - m[4]*m[2]*m[11] + m[4]*m[3]*m[10] + m[8]*m[2]*m[7] - m[8]*m[3]*m[6];
241 inv[11] = -m[0]*m[5]*m[11] + m[0]*m[7]*m[9] + m[4]*m[1]*m[11] - m[4]*m[3]*m[9] - m[8]*m[1]*m[7] + m[8]*m[3]*m[5];
242 inv[15] = m[0]*m[5]*m[10] - m[0]*m[6]*m[9] - m[4]*m[1]*m[10] + m[4]*m[2]*m[9] + m[8]*m[1]*m[6] - m[8]*m[2]*m[5];
243 float det = m[0]*inv[0] + m[1]*inv[4] + m[2]*inv[8] + m[3]*inv[12];
245 for (
int i = 0; i < 16; i++) minv[i] = inv[i] * det;
249static __forceinline__ __device__
bool d_raySphereIntersect(
const float3 &ray_origin,
const float3 &ray_direction,
250 const float3 &sphere_center,
float sphere_radius) {
251 const float3 oc = make_float3(ray_origin.x - sphere_center.x, ray_origin.y - sphere_center.y,
252 ray_origin.z - sphere_center.z);
253 const float b = dot(oc, ray_direction);
254 const float c = dot(oc, oc) - sphere_radius * sphere_radius;
255 const float disc = b * b - c;
256 if (disc < 0.0f)
return false;
257 return (-b - sqrtf(disc)) > 0.0f;
261static __forceinline__ __device__
bool d_rayRectangleIntersect(
const float3 &ray_origin,
const float3 &ray_direction,
262 const float3 &rect_center,
float rect_width,
float rect_length,
263 const float3 &rect_rotation,
float &out_cos_angle) {
265 d_makeTransformMatrix(rect_rotation, transform);
266 const float3 normal = make_float3(transform[2], transform[6], transform[10]);
267 const float denom = dot(ray_direction, normal);
268 if (denom >= -1e-6f)
return false;
269 const float3 oc = make_float3(rect_center.x - ray_origin.x, rect_center.y - ray_origin.y,
270 rect_center.z - ray_origin.z);
271 const float t = dot(oc, normal) / denom;
272 if (t <= 0.0f)
return false;
273 float3 hit = make_float3(ray_origin.x + t * ray_direction.x - rect_center.x,
274 ray_origin.y + t * ray_direction.y - rect_center.y,
275 ray_origin.z + t * ray_direction.z - rect_center.z);
277 d_invertMatrix(transform, inv_t);
278 d_transformPoint(inv_t, hit);
279 if (fabsf(hit.x) > rect_width * 0.5f || fabsf(hit.y) > rect_length * 0.5f)
return false;
280 out_cos_angle = -denom;
285static __forceinline__ __device__
bool d_rayDiskIntersect(
const float3 &ray_origin,
const float3 &ray_direction,
286 const float3 &disk_center,
float disk_radius,
287 const float3 &disk_rotation,
float &out_cos_angle) {
289 d_makeTransformMatrix(disk_rotation, transform);
290 const float3 normal = make_float3(transform[2], transform[6], transform[10]);
291 const float denom = dot(ray_direction, normal);
292 if (denom >= -1e-6f)
return false;
293 const float3 oc = make_float3(disk_center.x - ray_origin.x, disk_center.y - ray_origin.y,
294 disk_center.z - ray_origin.z);
295 const float t = dot(oc, normal) / denom;
296 if (t <= 0.0f)
return false;
297 const float3 hit = make_float3(ray_origin.x + t * ray_direction.x - disk_center.x,
298 ray_origin.y + t * ray_direction.y - disk_center.y,
299 ray_origin.z + t * ray_direction.z - disk_center.z);
300 if (dot(hit, hit) > disk_radius * disk_radius)
return false;
301 out_cos_angle = -denom;
320extern "C" __global__
void __intersection__patch() {
321 const uint32_t prim_idx = optixGetPrimitiveIndex();
322 const uint32_t pos = prim_idx;
325 const float3 ray_origin = optixGetWorldRayOrigin();
326 const float3 ray_direction = optixGetWorldRayDirection();
327 const float t_min = optixGetRayTmin();
328 const float t_max = optixGetRayTmax();
342 float3 e1 = make_float3(v1.x - v0.x, v1.y - v0.y, v1.z - v0.z);
343 float3 e3 = make_float3(v3.x - v0.x, v3.y - v0.y, v3.z - v0.z);
344 float3 n =
cross(e1, e3);
345 float nd = dot(ray_direction, n);
346 if (fabsf(nd) < 1e-8f)
return;
348 float t = dot(make_float3(v0.x - ray_origin.x, v0.y - ray_origin.y, v0.z - ray_origin.z), n) / nd;
349 if (t < t_min || t > t_max)
return;
352 float3 hit = make_float3(ray_origin.x + t * ray_direction.x,
353 ray_origin.y + t * ray_direction.y,
354 ray_origin.z + t * ray_direction.z);
355 const float slack = 1e-4f;
356 float mnx = fminf(fminf(v0.x, v1.x), fminf(v2.x, v3.x)) - slack;
357 float mxx = fmaxf(fmaxf(v0.x, v1.x), fmaxf(v2.x, v3.x)) + slack;
358 float mny = fminf(fminf(v0.y, v1.y), fminf(v2.y, v3.y)) - slack;
359 float mxy = fmaxf(fmaxf(v0.y, v1.y), fmaxf(v2.y, v3.y)) + slack;
360 float mnz = fminf(fminf(v0.z, v1.z), fminf(v2.z, v3.z)) - slack;
361 float mxz = fmaxf(fmaxf(v0.z, v1.z), fmaxf(v2.z, v3.z)) + slack;
362 if (hit.x < mnx || hit.x > mxx || hit.y < mny || hit.y > mxy ||
363 hit.z < mnz || hit.z > mxz)
return;
365 optixReportIntersection(t, 0, uuid, 0u);
369 if (ptype != 0 && ptype != 1 && ptype != 3)
return;
372 loadTransformMatrix(pos, T);
374 if (ptype == 0 || ptype == 3) {
377 float3 normal = make_float3(T[2], T[6], T[10]);
378 float nd = dot(ray_direction, normal);
379 if (fabsf(nd) < 1e-8f)
return;
382 float3 patch_origin = make_float3(T[3], T[7], T[11]);
383 float t = dot(patch_origin - ray_origin, normal) / nd;
384 if (t < t_min || t > t_max)
return;
387 float3 hit_local = ray_origin + t * ray_direction - patch_origin;
388 float3 local_x = make_float3(T[0], T[4], T[8]);
389 float3 local_y = make_float3(T[1], T[5], T[9]);
390 float lx2 = dot(local_x, local_x);
391 float ly2 = dot(local_y, local_y);
392 if (lx2 < 1e-12f || ly2 < 1e-12f)
return;
393 float u = dot(hit_local, local_x) / lx2;
394 float v = dot(hit_local, local_y) / ly2;
395 if (u < -0.5f || u > 0.5f || v < -0.5f || v > 0.5f)
return;
398 const int32_t msk_id = params.
mask_IDs[pos];
401 if (params.
uv_IDs[pos] >= 0) {
403 float2 uv0 = params.
uv_data[pos * 4 + 0];
404 float2 uv1 = params.
uv_data[pos * 4 + 1];
405 float2 uv2 = params.
uv_data[pos * 4 + 2];
406 float du = uv1.x - uv0.x;
407 float dv = uv2.y - uv0.y;
408 uv_u = uv0.x + (u + 0.5f) * du;
409 uv_v = uv0.y + (v + 0.5f) * dv;
415 if (!sampleMask(msk_id, uv_u, uv_v))
return;
422 uint32_t face_attr = (nd < 0.f) ? 1u : 0u;
423 optixReportIntersection(t, 0, uuid, face_attr);
428 const float3 v0 = make_float3(T[3], T[7], T[11]);
429 const float3 v1 = make_float3(T[1] + T[3], T[5] + T[7], T[9] + T[11]);
430 const float3 v2 = make_float3(T[0] + T[1] + T[3], T[4] + T[5] + T[7], T[8] + T[9] + T[11]);
433 float a = v0.x - v1.x, b = v0.x - v2.x, c = ray_direction.x, d = v0.x - ray_origin.x;
434 float e = v0.y - v1.y, f = v0.y - v2.y, g = ray_direction.y, h = v0.y - ray_origin.y;
435 float i = v0.z - v1.z, j = v0.z - v2.z, k = ray_direction.z, l = v0.z - ray_origin.z;
437 float m = f * k - g * j, n = h * k - g * l, p = f * l - h * j;
438 float q = g * i - e * k, s = e * j - f * i;
440 float tri_denom = a * m + b * q + c * s;
441 if (fabsf(tri_denom) < 1e-12f)
return;
442 float inv_denom = 1.f / tri_denom;
444 float e1 = d * m - b * n - c * p;
445 float beta = e1 * inv_denom;
446 if (beta < 0.f)
return;
448 float r = e * l - h * i;
449 float e2 = a * n + d * q + c * r;
450 float gamma = e2 * inv_denom;
451 if (gamma < 0.f || beta + gamma > 1.f)
return;
453 float e3 = a * p - b * r + d * s;
454 float t = e3 * inv_denom;
455 if (t < t_min || t > t_max)
return;
458 const int32_t msk_id = params.
mask_IDs[pos];
461 if (params.
uv_IDs[pos] >= 0) {
463 float2 uv0 = params.
uv_data[pos * 4 + 0];
464 float2 uv1 = params.
uv_data[pos * 4 + 1];
465 float2 uv2 = params.
uv_data[pos * 4 + 2];
467 float2 uv = make_float2(uv0.x + beta * (uv1.x - uv0.x) + gamma * (uv2.x - uv0.x),
468 uv0.y + beta * (uv1.y - uv0.y) + gamma * (uv2.y - uv0.y));
476 if (!sampleMask(msk_id, uv_u, uv_v))
return;
480 float3 edge0 = make_float3(v1.x - v0.x, v1.y - v0.y, v1.z - v0.z);
481 float3 edge1 = make_float3(v2.x - v0.x, v2.y - v0.y, v2.z - v0.z);
482 float3 tri_nrm = make_float3(edge0.y * edge1.z - edge0.z * edge1.y,
483 edge0.z * edge1.x - edge0.x * edge1.z,
484 edge0.x * edge1.y - edge0.y * edge1.x);
487 uint32_t face_attr = (dot(ray_direction, tri_nrm) < 0.f) ? 1u : 0u;
488 optixReportIntersection(t, 0, uuid, face_attr);
492extern "C" __global__
void __intersection__disk() {
497extern "C" __global__
void __intersection__tile() {
501extern "C" __global__
void __intersection__voxel() {
506extern "C" __global__
void __intersection__bbox() {
514extern "C" __global__
void __miss__direct() {
518 const uint32_t Nprims = params.Nprimitives;
519 const uint32_t Nbands_global = params.Nbands_global;
520 const uint32_t Nbands_launch = params.Nbands_launch;
523 for (uint32_t b_global = 0; b_global < Nbands_global; b_global++) {
528 const uint32_t ind_origin = origin_position * Nbands_launch + (uint32_t)b;
531 const uint32_t radprop_ind = prd->
source_ID * Nprims * Nbands_global
532 + origin_position * Nbands_global
534 const float t_rho = params.
rho[radprop_ind];
535 const float t_tau = params.
tau[radprop_ind];
538 const uint32_t flux_idx = prd->
source_ID * Nbands_launch + (uint32_t)b;
542 const float cover_tau = (b < HELIOS_MAX_RADIATION_BANDS) ? prd->
cover_transmittance[b] : 1.f;
544 const double strength = prd->
strength * (double)source_flux * (
double)cover_tau;
545 const float absorption = (float)(strength * (1.0 - t_rho - t_tau));
547 atomicFloatAdd(¶ms.
radiation_in[ind_origin], absorption);
549 if (t_rho > 0.f || t_tau > 0.f) {
551 atomicFloatAdd(¶ms.
scatter_buff_top[ind_origin], (
float)(strength * t_rho));
555 atomicFloatAdd(¶ms.
scatter_buff_top[ind_origin], (
float)(strength * t_tau));
561 const uint32_t Ncameras = params.Ncameras;
562 const uint32_t cam_id = params.camera_ID;
563 const uint32_t rc_idx = prd->
source_ID * Nprims * Nbands_global * Ncameras
564 + origin_position * Nbands_global * Ncameras
565 + b_global * Ncameras + cam_id;
566 const float t_rho_cam = params.
rho_cam[rc_idx];
567 const float t_tau_cam = params.
tau_cam ? params.
tau_cam[rc_idx] : 0.f;
568 if ((t_rho_cam > 0.f || t_tau_cam > 0.f) && strength > 0.0) {
571 atomicFloatAdd(¶ms.scatter_buff_bottom_cam[ind_origin], (
float)(strength * t_tau_cam));
573 atomicFloatAdd(¶ms.scatter_buff_bottom_cam[ind_origin], (
float)(strength * t_rho_cam));
583 for (uint32_t cam = 0; cam < params.Ncameras; cam++) {
585 const uint32_t weight_idx = prd->
source_ID * Nbands_launch * params.Ncameras
586 + (uint32_t)b * params.Ncameras + cam;
589 const uint32_t ind_specular = prd->
source_ID * params.Ncameras * Nprims * Nbands_launch
590 + cam * Nprims * Nbands_launch
591 + origin_position * Nbands_launch + (uint32_t)b;
592 atomicFloatAdd(¶ms.
radiation_specular[ind_specular], (
float)(strength * camera_weight));
598extern "C" __global__
void __miss__diffuse() {
602 if (origin_position == UINT_MAX)
return;
604 const uint32_t Nprims = params.Nprimitives;
605 const uint32_t Nbands_global = params.Nbands_global;
606 const uint32_t Nbands_launch = params.Nbands_launch;
609 printf(
"ERROR (OptiX8 __miss__diffuse): diffuse_flux is null. "
610 "Call updateDiffuseRadiation() before launchDiffuseRays().\n");
614 const float3 ray_dir = optixGetWorldRayDirection();
617 for (uint32_t b_global = 0; b_global < Nbands_global; b_global++) {
628 const float fd = evaluateDiffuseAngularDistribution(ray_dir, peak_d, power_K, power_N, sky_p);
630 const float cover_tau = (b < HELIOS_MAX_RADIATION_BANDS) ? prd->
cover_transmittance[b] : 1.f;
633 const uint32_t ind_origin = origin_position * Nbands_launch + (uint32_t)b;
634 const uint32_t radprop_ind = prd->
source_ID * Nprims * Nbands_global
635 + origin_position * Nbands_global + b_global;
636 const float t_rho = params.
rho[radprop_ind];
637 const float t_tau = params.
tau[radprop_ind];
639 atomicFloatAdd(¶ms.
radiation_in[ind_origin], strength * (1.f - t_rho - t_tau));
641 if (t_rho > 0.f || t_tau > 0.f) {
653 const uint32_t Ncameras = params.Ncameras;
654 const uint32_t cam_id = params.camera_ID;
655 const uint32_t rc_idx = prd->
source_ID * Nprims * Nbands_global * Ncameras
656 + origin_position * Nbands_global * Ncameras
657 + b_global * Ncameras + cam_id;
658 const float t_rho_cam = params.
rho_cam[rc_idx];
659 const float t_tau_cam = params.
tau_cam ? params.
tau_cam[rc_idx] : 0.f;
660 if ((t_rho_cam > 0.f || t_tau_cam > 0.f) && strength > 0.f) {
663 atomicFloatAdd(¶ms.scatter_buff_bottom_cam[ind_origin], strength * t_tau_cam);
665 atomicFloatAdd(¶ms.scatter_buff_bottom_cam[ind_origin], strength * t_rho_cam);
673extern "C" __global__
void __miss__camera() {
676 const uint32_t Nbands_l = params.Nbands_launch;
677 const float3 ray_origin = optixGetWorldRayOrigin();
678 const float3 ray_dir = optixGetWorldRayDirection();
680 for (uint32_t b = 0; b < Nbands_l; b++) {
681 float radiance = 0.0f;
683 for (uint32_t s = 0; s < params.Nsources; s++) {
685 if (flux <= 0.0f)
continue;
687 const uint32_t stype = params.source_types[s];
688 if (stype == 0 || stype == 2) {
691 dot(ray_dir, params.sun_direction) >= params.solar_disk_cos_angle) {
694 }
else if (stype == 1) {
696 if (d_raySphereIntersect(ray_origin, ray_dir, params.source_positions[s],
697 params.source_widths[s].x * 0.5f)) {
698 const float area = 4.0f *
M_PI * params.source_widths[s].x * 0.5f * params.source_widths[s].x * 0.5f;
699 radiance += (flux / area) /
M_PI;
701 }
else if (stype == 3) {
704 if (d_rayRectangleIntersect(ray_origin, ray_dir, params.source_positions[s],
705 params.source_widths[s].x, params.source_widths[s].y,
706 params.source_rotations[s], cos_angle)) {
707 const float area = params.source_widths[s].x * params.source_widths[s].y;
708 radiance += (flux / area) * cos_angle /
M_PI;
710 }
else if (stype == 4) {
713 if (d_rayDiskIntersect(ray_origin, ray_dir, params.source_positions[s],
714 params.source_widths[s].x, params.source_rotations[s], cos_angle)) {
715 const float area =
M_PI * params.source_widths[s].x * params.source_widths[s].x;
716 radiance += (flux / area) * cos_angle /
M_PI;
724 : make_float4(0.f, 0.f, 0.f, 0.f);
726 evaluateDiffuseAngularDistribution(ray_dir, params.sun_direction, 0.0f, 1.0f, sky_p);
736 if (radiance > 0.0f) {
743extern "C" __global__
void __miss__pixel_label() {
745 if (params.camera_pixel_depth) {
746 params.camera_pixel_depth[prd->
origin_UUID] = -1.0f;
763static __forceinline__ __device__
void handlePeriodicBoundaryHit(
PerRayData *prd, uint32_t hit_uuid) {
764 const float t_hit = optixGetRayTmax();
765 const float3 ray_orig = optixGetWorldRayOrigin();
766 const float3 ray_dir = optixGetWorldRayDirection();
767 const float3 hit_pos = make_float3(ray_orig.x + t_hit * ray_dir.x,
768 ray_orig.y + t_hit * ray_dir.y,
769 ray_orig.z + t_hit * ray_dir.z);
779 const float width = xmax - xmin;
780 prd->
periodic_hit.x += (bbox_local == 0) ? width : -width;
783 const uint32_t y_base = (params.
periodic_flag.x == 1) ? 2u : 0u;
786 const float width = ymax - ymin;
787 prd->
periodic_hit.y += (bbox_local == y_base) ? width : -width;
798static __forceinline__ __device__
float coverCosTheta(uint32_t hit_position,
const float3 &ray_dir) {
801 loadTransformMatrix(hit_position, T);
804 const float3 v0 = make_float3(T[3], T[7], T[11]);
805 const float3 v1 = make_float3(T[1] + T[3], T[5] + T[7], T[9] + T[11]);
806 const float3 v2 = make_float3(T[0] + T[1] + T[3], T[4] + T[5] + T[7], T[8] + T[9] + T[11]);
807 const float3 e0 = make_float3(v1.x - v0.x, v1.y - v0.y, v1.z - v0.z);
808 const float3 e1 = make_float3(v2.x - v0.x, v2.y - v0.y, v2.z - v0.z);
809 normal =
cross(e0, e1);
811 normal = make_float3(T[2], T[6], T[10]);
813 const float nmag = d_magnitude(normal);
814 if (nmag < 1e-12f)
return 1.f;
815 return fminf(1.f, fabsf(dot(ray_dir, normal)) / nmag);
824static __forceinline__ __device__
void coverAnyHitBody(
bool is_direct) {
825 const uint32_t hit_uuid = optixGetAttribute_0();
827 if (hit_position == UINT_MAX)
return;
828 if (params.
is_glass ==
nullptr)
return;
833 if (hit_uuid == prd->
origin_UUID) { optixIgnoreIntersection();
return; }
835 const uint32_t Nprims = params.Nprimitives;
836 const uint32_t Nbands_global = params.Nbands_global;
837 const uint32_t Nbands_launch = params.Nbands_launch;
845 for (uint32_t b_global = 0; b_global < Nbands_global; b_global++) {
848 const uint32_t mat_ind = prd->
source_ID * Nprims * Nbands_global + hit_position * Nbands_global + b_global;
849 if (params.
is_glass[mat_ind] == 0)
return;
853 const bool face_top = (optixGetAttribute_1() == 1u);
854 const float3 ray_dir = optixGetWorldRayDirection();
855 const float cos_theta = coverCosTheta(hit_position, ray_dir);
858 for (uint32_t b_global = 0; b_global < Nbands_global; b_global++) {
861 if (b >= HELIOS_MAX_RADIATION_BANDS)
break;
863 const uint32_t mat_ind = prd->
source_ID * Nprims * Nbands_global
864 + hit_position * Nbands_global + b_global;
866 const float n = params.
glass_n[mat_ind];
867 const float KL = params.
glass_KL[mat_ind];
868 const float3 tra = glass_tau_rho_alpha(cos_theta, n, KL);
871 double ext_flux = 0.0;
873 const uint32_t flux_idx = prd->
source_ID * Nbands_launch + (uint32_t)b;
885 const uint32_t cov_ind = hit_position * Nbands_launch + (uint32_t)b;
887 if (incoming > 0.0) {
888 atomicFloatAdd(¶ms.
radiation_in[cov_ind], (
float)(incoming * (
double)tra.z));
891 atomicFloatAdd(¶ms.
scatter_buff_top[cov_ind], (
float)(incoming * (
double)tra.y));
902 optixIgnoreIntersection();
905extern "C" __global__
void __anyhit__direct() {
906 coverAnyHitBody(
true);
909extern "C" __global__
void __anyhit__diffuse() {
910 coverAnyHitBody(
false);
913extern "C" __global__
void __closesthit__direct() {
918 const uint32_t hit_uuid = optixGetAttribute_0();
922 prd->hit_periodic_boundary =
true;
923 handlePeriodicBoundaryHit(prd, hit_uuid);
930extern "C" __global__
void __closesthit__diffuse() {
931 const uint32_t hit_uuid = optixGetAttribute_0();
932 const bool face_top = (optixGetAttribute_1() == 1u);
939 prd->hit_periodic_boundary =
true;
940 handlePeriodicBoundaryHit(prd, hit_uuid);
946 if (origin_position == UINT_MAX || hit_position == UINT_MAX)
return;
948 const uint32_t Nprims = params.Nprimitives;
949 const uint32_t Nbands_global = params.Nbands_global;
950 const uint32_t Nbands_launch = params.Nbands_launch;
953 for (uint32_t b_global = 0; b_global < Nbands_global; b_global++) {
957 const uint32_t ind_origin = origin_position * Nbands_launch + (uint32_t)b;
958 const uint32_t ind_hit = hit_position * Nbands_launch + (uint32_t)b;
962 if (strength == 0.0)
continue;
964 const uint32_t radprop_ind = prd->
source_ID * Nprims * Nbands_global
965 + origin_position * Nbands_global + b_global;
966 const float t_rho = params.
rho[radprop_ind];
967 const float t_tau = params.
tau[radprop_ind];
969 atomicFloatAdd(¶ms.
radiation_in[ind_origin], (
float)(strength * (1.0 - t_rho - t_tau)));
971 if (t_rho > 0.f || t_tau > 0.f) {
973 atomicFloatAdd(¶ms.
scatter_buff_top[ind_origin], (
float)(strength * t_rho));
977 atomicFloatAdd(¶ms.
scatter_buff_top[ind_origin], (
float)(strength * t_tau));
983 const uint32_t Ncameras = params.Ncameras;
984 const uint32_t cam_id = params.camera_ID;
985 const uint32_t rc_idx = prd->
source_ID * Nprims * Nbands_global * Ncameras
986 + origin_position * Nbands_global * Ncameras
987 + b_global * Ncameras + cam_id;
988 const float t_rho_cam = params.
rho_cam[rc_idx];
989 const float t_tau_cam = params.
tau_cam ? params.
tau_cam[rc_idx] : 0.f;
990 if ((t_rho_cam > 0.f || t_tau_cam > 0.f) && strength > 0.0) {
993 atomicFloatAdd(¶ms.scatter_buff_bottom_cam[ind_origin], (
float)(strength * t_tau_cam));
995 atomicFloatAdd(¶ms.scatter_buff_bottom_cam[ind_origin], (
float)(strength * t_rho_cam));
1007extern "C" __global__
void __closesthit__camera() {
1008 const uint32_t hit_uuid = optixGetAttribute_0();
1012 if (hit_position == 0xFFFFFFFFu)
return;
1017 handlePeriodicBoundaryHit(prd, hit_uuid);
1018 prd->hit_periodic_boundary =
true;
1023 const uint32_t Nbands_l = params.Nbands_launch;
1024 const uint32_t Nprims = params.Nprimitives;
1025 const float t_hit = optixGetRayTmax();
1026 const float3 ray_origin = optixGetWorldRayOrigin();
1027 const float3 ray_direction = optixGetWorldRayDirection();
1030 const bool face_top = (optixGetAttribute_1() == 1u);
1034 loadTransformMatrix(hit_position, T);
1035 float3 n0 = make_float3(0.f, 0.f, 0.f); d_transformPoint(T, n0);
1036 float3 n1 = make_float3(1.f, 0.f, 0.f); d_transformPoint(T, n1);
1037 float3 n2 = make_float3(0.f, 1.f, 0.f); d_transformPoint(T, n2);
1038 float3 normal = normalize(
cross(n1 - n0, n2 - n0));
1040 if (face_top != (dot(normal, ray_direction) < 0.f)) {
1041 normal = make_float3(-normal.x, -normal.y, -normal.z);
1044 for (uint32_t b = 0; b < Nbands_l; b++) {
1046 const uint32_t ind_hit = hit_position * Nbands_l + b;
1047 float strength = (float)prd->
strength *
1052 for (uint32_t s = 0; s < params.Nsources; s++) {
1054 if (flux <= 0.0f)
continue;
1056 const uint32_t stype = params.source_types[s];
1057 float source_radiance = 0.0f;
1061 const float radius = params.source_widths[s].x * 0.5f;
1062 const float3 oc = make_float3(ray_origin.x - params.source_positions[s].x,
1063 ray_origin.y - params.source_positions[s].y,
1064 ray_origin.z - params.source_positions[s].z);
1065 const float bd = dot(oc, ray_direction);
1066 const float cd = dot(oc, oc) - radius * radius;
1067 const float disc = bd * bd - cd;
1069 const float t_sphere = -bd - sqrtf(disc);
1070 if (t_sphere > 0.0f && t_sphere < t_hit) {
1071 const float area = 4.0f *
M_PI * radius * radius;
1072 source_radiance = (flux / area) /
M_PI;
1075 }
else if (stype == 3) {
1078 d_makeTransformMatrix(params.source_rotations[s], trans);
1079 const float3 snormal = make_float3(trans[2], trans[6], trans[10]);
1080 const float denom = dot(ray_direction, snormal);
1081 if (denom < -1e-6f) {
1082 const float3 oc = make_float3(params.source_positions[s].x - ray_origin.x,
1083 params.source_positions[s].y - ray_origin.y,
1084 params.source_positions[s].z - ray_origin.z);
1085 const float t_r = dot(oc, snormal) / denom;
1086 if (t_r > 0.0f && t_r < t_hit) {
1087 float3 hp = make_float3(ray_origin.x + t_r * ray_direction.x - params.source_positions[s].x,
1088 ray_origin.y + t_r * ray_direction.y - params.source_positions[s].y,
1089 ray_origin.z + t_r * ray_direction.z - params.source_positions[s].z);
1091 d_invertMatrix(trans, inv_t);
1092 d_transformPoint(inv_t, hp);
1093 if (fabsf(hp.x) <= params.source_widths[s].x * 0.5f &&
1094 fabsf(hp.y) <= params.source_widths[s].y * 0.5f) {
1095 const float area = params.source_widths[s].x * params.source_widths[s].y;
1096 source_radiance = (flux / area) * (-denom) /
M_PI;
1100 }
else if (stype == 4) {
1103 d_makeTransformMatrix(params.source_rotations[s], trans);
1104 const float3 snormal = make_float3(trans[2], trans[6], trans[10]);
1105 const float denom = dot(ray_direction, snormal);
1106 if (denom < -1e-6f) {
1107 const float3 oc = make_float3(params.source_positions[s].x - ray_origin.x,
1108 params.source_positions[s].y - ray_origin.y,
1109 params.source_positions[s].z - ray_origin.z);
1110 const float t_d = dot(oc, snormal) / denom;
1111 if (t_d > 0.0f && t_d < t_hit) {
1112 const float3 hp = make_float3(ray_origin.x + t_d * ray_direction.x - params.source_positions[s].x,
1113 ray_origin.y + t_d * ray_direction.y - params.source_positions[s].y,
1114 ray_origin.z + t_d * ray_direction.z - params.source_positions[s].z);
1115 const float radius = params.source_widths[s].x;
1116 if (dot(hp, hp) <= radius * radius) {
1117 const float area =
M_PI * radius * radius;
1118 source_radiance = (flux / area) * (-denom) /
M_PI;
1124 if (source_radiance > 0.0f) {
1125 strength += source_radiance * (float)prd->
strength;
1130 float strength_spec = 0.0f;
1131 if (params.specular_reflection_enabled > 0 &&
1132 params.specular_exponent && params.specular_exponent[hit_position] > 0.f &&
1133 params.scattering_iteration == 0 &&
1135 for (uint32_t rr = 0; rr < params.Nsources; rr++) {
1136 const uint32_t ind_spec = rr * params.Ncameras * Nprims * Nbands_l
1137 + params.camera_ID * Nprims * Nbands_l
1138 + hit_position * Nbands_l + b;
1142 if (params.source_types[rr] == 0 || params.source_types[rr] == 2) {
1143 light_dir = normalize(params.source_positions[rr]);
1145 const float3 hp = make_float3(ray_origin.x + t_hit * ray_direction.x,
1146 ray_origin.y + t_hit * ray_direction.y,
1147 ray_origin.z + t_hit * ray_direction.z);
1148 light_dir = normalize(make_float3(params.source_positions[rr].x - hp.x,
1149 params.source_positions[rr].y - hp.y,
1150 params.source_positions[rr].z - hp.z));
1152 const float3 spec_dir = normalize(light_dir - ray_direction);
1153 const float exponent = params.specular_exponent[hit_position];
1154 float scale_coeff = 1.0f;
1155 if (params.specular_reflection_enabled == 2 && params.specular_scale) {
1156 scale_coeff = params.specular_scale[hit_position];
1158 const float cos_spec = fmaxf(0.f, dot(spec_dir, normal));
1159 strength_spec += spec * scale_coeff
1160 * powf(cos_spec, exponent) * (exponent + 2.f)
1161 / ((
float)params.launch_dim_x * 2.f *
M_PI);
1168 (strength + strength_spec) /
M_PI);
1176extern "C" __global__
void __closesthit__pixel_label() {
1177 const uint32_t hit_uuid = optixGetAttribute_0();
1184 hit_position != 0xFFFFFFFFu && params.
primitive_type[hit_position] == 5) {
1185 handlePeriodicBoundaryHit(prd, hit_uuid);
1186 prd->hit_periodic_boundary =
true;
1191 if (params.camera_pixel_label) {
1192 params.camera_pixel_label[origin_UUID] = hit_uuid + 1u;
1196 if (params.camera_pixel_depth) {
1197 const float t_hit = optixGetRayTmax() + (float)prd->
strength;
1198 const float3 ray_dir = optixGetWorldRayDirection();
1199 const float3 cam_dir = d_rotatePoint(make_float3(1.f, 0.f, 0.f),
1202 params.camera_pixel_depth[origin_UUID] = fabsf(dot(cam_dir, ray_dir)) * t_hit;
1210extern "C" __global__
void __raygen__direct() {
1212 const uint3 idx = optixGetLaunchIndex();
1213 const uint32_t xi = idx.x;
1214 const uint32_t yi = idx.y;
1215 const uint32_t prim_local = idx.z;
1217 const uint32_t dim_x = params.launch_dim_x;
1218 const uint32_t dim_y = params.launch_dim_y;
1219 const uint32_t Nrays = dim_x * dim_y;
1220 const uint32_t prim_pos = params.
launch_offset + prim_local;
1222 if (prim_pos >= params.Nprimitives)
return;
1229 loadTransformMatrix(prim_pos, T);
1231 const uint32_t linear_idx = xi + dim_x * yi;
1232 uint32_t seed = tea<16>(linear_idx + Nrays * prim_local, params.random_seed);
1234 for (
int jj = 0; jj < NY; jj++) {
1235 for (
int ii = 0; ii < NX; ii++) {
1238 const uint32_t UUID = params.
primitiveID[prim_pos] + (uint32_t)(jj * NX + ii);
1240 const float Rx = rnd(seed);
1241 const float Ry = rnd(seed);
1246 if (ptype == 0 || ptype == 3) {
1247 const float dx = 1.0f / float(NX);
1248 const float dy = 1.0f / float(NY);
1249 sp.x = -0.5f + ii * dx + (float(xi) + Rx) * dx /
float(dim_x);
1250 sp.y = -0.5f + jj * dy + (float(yi) + Ry) * dy /
float(dim_y);
1254 const int32_t msk_orig = params.
mask_IDs[prim_pos];
1255 if (msk_orig >= 0) {
1256 for (
int attempt = 0; attempt < 10; attempt++) {
1258 if (params.
uv_IDs[prim_pos] >= 0) {
1259 float2 uv0 = params.
uv_data[prim_pos * 4 + 0];
1260 float2 uv1 = params.
uv_data[prim_pos * 4 + 1];
1261 float2 uv2 = params.
uv_data[prim_pos * 4 + 2];
1262 uv_u = uv0.x + (sp.x + 0.5f) * (uv1.x - uv0.x);
1263 uv_v = uv0.y + (sp.y + 0.5f) * (uv2.y - uv0.y);
1268 if (sampleMask(msk_orig, uv_u, uv_v))
break;
1269 sp.x = -0.5f + (ii + rnd(seed)) * dx;
1270 sp.y = -0.5f + (jj + rnd(seed)) * dy;
1274 float3 v0 = make_float3(0.f, 0.f, 0.f); d_transformPoint(T, v0);
1275 float3 v1 = make_float3(1.f, 0.f, 0.f); d_transformPoint(T, v1);
1276 float3 v2 = make_float3(0.f, 1.f, 0.f); d_transformPoint(T, v2);
1277 normal = normalize(
cross(v1 - v0, v2 - v0));
1279 }
else if (ptype == 1) {
1280 if (Rx < Ry) { sp.x = Rx; sp.y = Ry; }
1281 else { sp.x = Ry; sp.y = Rx; }
1285 const int32_t msk_orig_t = params.
mask_IDs[prim_pos];
1286 if (msk_orig_t >= 0) {
1287 for (
int attempt = 0; attempt < 10; attempt++) {
1289 if (params.
uv_IDs[prim_pos] >= 0) {
1290 float2 uv0 = params.
uv_data[prim_pos * 4 + 0];
1291 float2 uv1 = params.
uv_data[prim_pos * 4 + 1];
1292 float2 uv2 = params.
uv_data[prim_pos * 4 + 2];
1293 const float beta = sp.y - sp.x;
1294 const float gamma = sp.x;
1295 float2 uv = make_float2(
1296 uv0.x + beta * (uv1.x - uv0.x) + gamma * (uv2.x - uv0.x),
1297 uv0.y + beta * (uv1.y - uv0.y) + gamma * (uv2.y - uv0.y));
1304 if (sampleMask(msk_orig_t, uv_u, uv_v))
break;
1305 float Rx2 = rnd(seed), Ry2 = rnd(seed);
1306 if (Rx2 < Ry2) { sp.x = Rx2; sp.y = Ry2; }
1307 else { sp.x = Ry2; sp.y = Rx2; }
1311 float3 v0 = make_float3(0.f, 0.f, 0.f); d_transformPoint(T, v0);
1312 float3 v1 = make_float3(0.f, 1.f, 0.f); d_transformPoint(T, v1);
1313 float3 v2 = make_float3(1.f, 1.f, 0.f); d_transformPoint(T, v2);
1314 normal = normalize(
cross(v1 - v0, v2 - v0));
1318 printf(
"ERROR (OptiX8 __raygen__direct): unsupported primitive type %u at index %u\n",
1324 float3 ray_origin = sp;
1325 d_transformPoint(T, ray_origin);
1328 for (uint32_t rr = 0; rr < params.Nsources; rr++) {
1330 const uint32_t src_type = params.source_types[rr];
1332 float3 ray_direction;
1336 if (src_type == 0) {
1337 ray_direction = normalize(params.source_positions[rr]);
1339 strength = (1.0 / double(dim_x * dim_y)) * (
double)fabsf(dot(normal, ray_direction));
1341 }
else if (src_type == 1 || src_type == 2) {
1342 float theta_s =
acos_safe(1.f - 2.f * rnd(seed));
1343 float phi_s = rnd(seed) * 2.f *
M_PI;
1344 float3 sphere_pt = make_float3(0.5f * params.source_widths[rr].x * sinf(theta_s) * cosf(phi_s),
1345 0.5f * params.source_widths[rr].x * sinf(theta_s) * sinf(phi_s),
1346 0.5f * params.source_widths[rr].x * cosf(theta_s));
1347 ray_direction = sphere_pt + params.source_positions[rr] - ray_origin;
1348 ray_tmax = d_magnitude(ray_direction);
1349 ray_direction = normalize(ray_direction);
1353 const uint32_t N = 10;
1354 for (uint32_t j = 0; j < N; j++) {
1355 for (uint32_t i = 0; i < N; i++) {
1356 float theta =
acos_safe(1.f - 2.f * (
float(i) + 0.5f) /
float(N));
1357 float phi = (float(j) + 0.5f) * 2.f *
M_PI /
float(N);
1358 float3 ldir = make_float3(sinf(theta)*cosf(phi), sinf(theta)*sinf(phi), cosf(theta));
1359 if (dot(ldir, ray_direction) < 0.f) {
1360 strength += (1.0 / double(dim_x * dim_y)) * (
double)fabsf(dot(normal, ray_direction))
1361 * (double)fabsf(dot(ldir, ray_direction))
1362 / ((
double)ray_tmax * (double)ray_tmax)
1364 * (double)params.source_widths[rr].x * (
double)params.source_widths[rr].x;
1369 }
else if (src_type == 3) {
1370 float light_transform[16];
1371 float3 rot3 = params.source_rotations[rr];
1372 d_makeTransformMatrix(rot3, light_transform);
1375 d_sampleSquare(seed, square_pt);
1376 square_pt = make_float3(params.source_widths[rr].x * square_pt.x, params.source_widths[rr].y * square_pt.y, square_pt.z);
1377 d_transformPoint(light_transform, square_pt);
1379 float3 light_dir = make_float3(0.f, 0.f, 1.f);
1380 d_transformPoint(light_transform, light_dir);
1382 ray_direction = square_pt + params.source_positions[rr] - ray_origin;
1383 if (dot(ray_direction, light_dir) > 0.f)
continue;
1385 ray_tmax = d_magnitude(ray_direction);
1386 ray_direction = normalize(ray_direction);
1387 strength = (1.0 / double(dim_x * dim_y))
1388 * (
double)fabsf(dot(normal, ray_direction))
1389 * (double)fabsf(dot(light_dir, ray_direction))
1390 / ((
double)ray_tmax * (double)ray_tmax)
1391 * (double)params.source_widths[rr].x * (
double)params.source_widths[rr].y
1394 }
else if (src_type == 4) {
1395 float light_transform[16];
1396 float3 rot3 = params.source_rotations[rr];
1397 d_makeTransformMatrix(rot3, light_transform);
1400 d_sampleDisk(seed, disk_pt);
1401 d_transformPoint(light_transform, disk_pt);
1403 float3 light_dir = make_float3(0.f, 0.f, 1.f);
1404 d_transformPoint(light_transform, light_dir);
1406 ray_direction = params.source_widths[rr].x * disk_pt + params.source_positions[rr] - ray_origin;
1407 if (dot(ray_direction, light_dir) > 0.f)
continue;
1409 ray_tmax = d_magnitude(ray_direction);
1410 ray_direction = normalize(ray_direction);
1411 strength = (1.0 / double(dim_x * dim_y))
1412 * (
double)fabsf(dot(normal, ray_direction))
1413 * (double)fabsf(dot(light_dir, ray_direction))
1414 / ((
double)ray_tmax * (double)ray_tmax)
1415 * (double)params.source_widths[rr].x * (
double)params.source_widths[rr].x;
1425 prd.hit_periodic_boundary =
false;
1426 prd.
face = (dot(ray_direction, normal) > 0.f);
1427 initCoverTransmittance(prd);
1434 if (!prd.
face && tsf == 0)
continue;
1435 if (tsf == 3)
continue;
1438 float3 current_origin = ray_origin;
1440 for (
int wrap = 0; wrap < 10; ++wrap) {
1441 packPointer(&prd, u0, u1);
1449 OptixVisibilityMask(255),
1450 OPTIX_RAY_FLAG_NONE,
1456 if (!prd.hit_periodic_boundary)
break;
1458 prd.hit_periodic_boundary =
false;
1471extern "C" __global__
void __raygen__diffuse() {
1473 const uint3 idx = optixGetLaunchIndex();
1474 const uint32_t theta_idx = idx.x;
1475 const uint32_t phi_idx = idx.y;
1476 const uint32_t prim_local = idx.z;
1478 const uint32_t dim_x = params.launch_dim_x;
1479 const uint32_t dim_y = params.launch_dim_y;
1480 const uint32_t dimxy = dim_x * dim_y;
1482 const uint32_t prim_pos = params.
launch_offset + prim_local;
1483 if (prim_pos >= params.Nprimitives)
return;
1493 loadTransformMatrix(prim_pos, T);
1496 const uint32_t linear_idx = theta_idx + dim_x * phi_idx;
1497 uint32_t seed = tea<16>(linear_idx + dimxy * prim_local, params.random_seed);
1500 const float Rt = (theta_idx + rnd(seed)) /
float(dim_x);
1501 const float Rp = (phi_idx + rnd(seed)) /
float(dim_y);
1503 const float p = 2.f *
M_PI * Rp;
1504 float3 ray_dir_canonical;
1505 ray_dir_canonical.x = sinf(t) * cosf(p);
1506 ray_dir_canonical.y = sinf(t) * sinf(p);
1507 ray_dir_canonical.z = cosf(t);
1509 for (
int jj = 0; jj < NY; jj++) {
1510 for (
int ii = 0; ii < NX; ii++) {
1512 const uint32_t UUID = params.
primitiveID[prim_pos] + (uint32_t)(jj * NX + ii);
1514 const float Rx = rnd(seed);
1515 const float Ry = rnd(seed);
1520 if (ptype == 0 || ptype == 3) {
1521 const float dx = 1.f / float(NX);
1522 const float dy = 1.f / float(NY);
1523 sp.x = -0.5f + (ii + Rx) * dx;
1524 sp.y = -0.5f + (jj + Ry) * dy;
1528 const int32_t msk_orig_d = params.
mask_IDs[prim_pos];
1529 if (msk_orig_d >= 0) {
1530 for (
int attempt = 0; attempt < 10; attempt++) {
1532 if (params.
uv_IDs[prim_pos] >= 0) {
1533 float2 uv0 = params.
uv_data[prim_pos * 4 + 0];
1534 float2 uv1 = params.
uv_data[prim_pos * 4 + 1];
1535 float2 uv2 = params.
uv_data[prim_pos * 4 + 2];
1536 uv_u = uv0.x + (sp.x + 0.5f) * (uv1.x - uv0.x);
1537 uv_v = uv0.y + (sp.y + 0.5f) * (uv2.y - uv0.y);
1542 if (sampleMask(msk_orig_d, uv_u, uv_v))
break;
1543 sp.x = -0.5f + (ii + rnd(seed)) * dx;
1544 sp.y = -0.5f + (jj + rnd(seed)) * dy;
1548 float3 v0 = make_float3(0.f, 0.f, 0.f); d_transformPoint(T, v0);
1549 float3 v1 = make_float3(1.f, 0.f, 0.f); d_transformPoint(T, v1);
1550 float3 v2 = make_float3(0.f, 1.f, 0.f); d_transformPoint(T, v2);
1551 normal = normalize(
cross(v1 - v0, v2 - v0));
1553 }
else if (ptype == 1) {
1554 if (Rx < Ry) { sp.x = Rx; sp.y = Ry; }
1555 else { sp.x = Ry; sp.y = Rx; }
1559 const int32_t msk_orig_dt = params.
mask_IDs[prim_pos];
1560 if (msk_orig_dt >= 0) {
1561 for (
int attempt = 0; attempt < 10; attempt++) {
1563 if (params.
uv_IDs[prim_pos] >= 0) {
1564 float2 uv0 = params.
uv_data[prim_pos * 4 + 0];
1565 float2 uv1 = params.
uv_data[prim_pos * 4 + 1];
1566 float2 uv2 = params.
uv_data[prim_pos * 4 + 2];
1567 const float beta = sp.y - sp.x;
1568 const float gamma = sp.x;
1569 float2 uv = make_float2(
1570 uv0.x + beta * (uv1.x - uv0.x) + gamma * (uv2.x - uv0.x),
1571 uv0.y + beta * (uv1.y - uv0.y) + gamma * (uv2.y - uv0.y));
1578 if (sampleMask(msk_orig_dt, uv_u, uv_v))
break;
1579 float Rx2 = rnd(seed), Ry2 = rnd(seed);
1580 if (Rx2 < Ry2) { sp.x = Rx2; sp.y = Ry2; }
1581 else { sp.x = Ry2; sp.y = Rx2; }
1585 float3 v0 = make_float3(0.f, 0.f, 0.f); d_transformPoint(T, v0);
1586 float3 v1 = make_float3(0.f, 1.f, 0.f); d_transformPoint(T, v1);
1587 float3 v2 = make_float3(1.f, 1.f, 0.f); d_transformPoint(T, v2);
1588 normal = normalize(
cross(v1 - v0, v2 - v0));
1592 printf(
"ERROR (OptiX8 __raygen__diffuse): unsupported primitive type %u at index %u\n",
1598 float3 ray_dir = d_rotatePoint(ray_dir_canonical,
1600 atan2f(normal.y, normal.x));
1603 float3 ray_origin = sp;
1604 d_transformPoint(T, ray_origin);
1610 prd.hit_periodic_boundary =
false;
1611 prd.
strength = 1.0 / double(dimxy);
1612 initCoverTransmittance(prd);
1618 float3 cur_origin = ray_origin;
1619 for (
int wrap = 0; wrap < 10; ++wrap) {
1620 packPointer(&prd, u0, u1);
1623 cur_origin, ray_dir,
1625 OptixVisibilityMask(255),
1626 OPTIX_RAY_FLAG_NONE,
1630 if (!prd.hit_periodic_boundary)
break;
1632 prd.hit_periodic_boundary =
false;
1636 float3 neg_dir = make_float3(-ray_dir.x, -ray_dir.y, -ray_dir.z);
1637 float3 cur_origin = ray_origin;
1638 for (
int wrap = 0; wrap < 10; ++wrap) {
1639 packPointer(&prd, u0, u1);
1642 cur_origin, neg_dir,
1644 OptixVisibilityMask(255),
1645 OPTIX_RAY_FLAG_NONE,
1649 if (!prd.hit_periodic_boundary)
break;
1651 prd.hit_periodic_boundary =
false;
1665extern "C" __global__
void __raygen__camera() {
1666 const uint3 idx = optixGetLaunchIndex();
1667 const uint32_t ray_idx = idx.x;
1668 const uint32_t col = idx.y;
1669 const uint32_t row = idx.z;
1671 const uint32_t dim_x = params.launch_dim_x;
1672 const uint32_t dim_y = params.launch_dim_y;
1675 const uint32_t ii = (uint32_t)params.camera_pixel_offset.x + col;
1676 const uint32_t jj = (uint32_t)params.camera_pixel_offset.y + row;
1679 const uint32_t pixel_index = jj * (uint32_t)params.camera_resolution_full.x + ii;
1682 const uint32_t linear_idx = dim_x * col + ray_idx;
1683 uint32_t seed = tea<16>(linear_idx + dim_x * dim_y * row, params.random_seed);
1685 const float Rx = rnd(seed);
1686 const float Ry = rnd(seed);
1690 const float multiplier = 1.0f / params.FOV_aspect_ratio;
1692 sp.y = -0.5f + ((float)ii + Rx) / (float)params.camera_resolution_full.x;
1693 sp.z = ( 0.5f - ((float)jj + Ry) / (float)params.camera_resolution_full.y) * multiplier;
1694 sp.x = params.camera_viewplane_length;
1697 const float3 p = make_float3(
1698 params.camera_focal_length,
1699 sp.y / params.camera_viewplane_length * params.camera_focal_length,
1700 sp.z / params.camera_viewplane_length * params.camera_focal_length);
1703 float3 ray_origin = make_float3(0.f, 0.f, 0.f);
1704 if (params.camera_lens_diameter > 0.f) {
1706 d_sampleDisk(seed, disk_sample);
1707 ray_origin = make_float3(0.f, 0.5f * disk_sample.x * params.camera_lens_diameter,
1708 0.5f * disk_sample.y * params.camera_lens_diameter);
1711 float3 ray_direction = make_float3(p.x - ray_origin.x, p.y - ray_origin.y, p.z - ray_origin.z);
1716 ray_origin = d_rotatePoint(ray_origin, theta, phi) + params.camera_position;
1717 ray_direction = d_rotatePoint(ray_direction, theta, phi);
1718 ray_direction = ray_direction * (1.0f / d_magnitude(ray_direction));
1721 prd.
strength = 1.0f / (float)dim_x;
1722 prd.origin_UUID = pixel_index;
1726 prd.hit_periodic_boundary =
false;
1729 packPointer(&prd, p0, p1);
1731 const float t_min = 1e-5f;
1732 const float t_max = 1e30f;
1734 float3 cur_origin = ray_origin;
1735 for (
int wrap = 0; wrap < 10; wrap++) {
1736 prd.hit_periodic_boundary =
false;
1737 optixTrace(params.traversable, cur_origin, ray_direction,
1739 OptixVisibilityMask(255), OPTIX_RAY_FLAG_NONE,
1742 if (!prd.hit_periodic_boundary)
break;
1743 cur_origin = prd.periodic_hit;
1752extern "C" __global__
void __raygen__pixel_label() {
1753 const uint3 idx = optixGetLaunchIndex();
1754 const uint32_t col = idx.y;
1755 const uint32_t row = idx.z;
1757 const uint32_t dim_y = params.launch_dim_y;
1760 const uint32_t ii = (uint32_t)params.camera_pixel_offset.x + col;
1761 const uint32_t jj = (uint32_t)params.camera_pixel_offset.y + row;
1762 const uint32_t pixel_index = jj * (uint32_t)params.camera_resolution_full.x + ii;
1764 uint32_t seed = tea<16>(dim_y * row + col, params.random_seed);
1767 const float multiplier = 1.0f / params.FOV_aspect_ratio;
1769 sp.y = -0.5f + ((float)ii + 0.5f) / (float)params.camera_resolution_full.x;
1770 sp.z = ( 0.5f - ((float)jj + 0.5f) / (float)params.camera_resolution_full.y) * multiplier;
1771 sp.x = params.camera_viewplane_length;
1773 const float3 p = make_float3(
1774 params.camera_focal_length,
1775 sp.y / params.camera_viewplane_length * params.camera_focal_length,
1776 sp.z / params.camera_viewplane_length * params.camera_focal_length);
1778 float3 ray_origin = make_float3(0.f, 0.f, 0.f);
1779 float3 ray_direction = p;
1783 ray_origin = d_rotatePoint(ray_origin, theta, phi) + params.camera_position;
1784 ray_direction = d_rotatePoint(ray_direction, theta, phi);
1785 ray_direction = ray_direction * (1.0f / d_magnitude(ray_direction));
1789 prd.origin_UUID = pixel_index;
1793 prd.hit_periodic_boundary =
false;
1796 packPointer(&prd, p0, p1);
1798 const float t_min = 1e-5f;
1799 const float t_max = 1e30f;
1801 float3 cur_origin = ray_origin;
1802 for (
int wrap = 0; wrap < 10; wrap++) {
1803 prd.hit_periodic_boundary =
false;
1804 optixTrace(params.traversable, cur_origin, ray_direction,
1806 OptixVisibilityMask(255), OPTIX_RAY_FLAG_NONE,
1809 if (!prd.hit_periodic_boundary)
break;
1810 cur_origin = prd.periodic_hit;