“This new camera shoots rays in a spherical distribution” (see OptiX_Quickstart_Guide_5.1.0.pdf page 23 in the doc folder)

float2 d = make_float2(launch_index) / make_float2(screen) * make_float2(2.0f * M_PIf , M_PIf) + make_float2(M_PIf, 0);
// make_float2(launch_index) / make_float2(screen) are 2 dimensional values d.x, d.y between 0.0 .. 1.0 for x and y dependend on the
// width/height of the output buffer; these values are converted to radians:
// d.x = launch_index.x / width * 360° + 180° (result in radians) 2*PI = 360°
// d.y = launch_index.y / height * 180° + 0° (result in radians) PI = 180°
// the spherical coordinates (3D version of "polar coordinates"):
// for x direction 2 * PI is multiplied; range 360 degrees, (azimuth) around the Y axis of the unit sphere restricted to interval 180° .. 540°
// (which is same range as -180° .. + 180°) = standard convention for geographic longitude
// for y direction PI is multiplied; range 180 degrees, (inclination) around the X axis for the unit sphere) latitude
// calculate angles Yaw, Pitch, Roll for all 3 dimensions from spherical coordinates azimuth (in d.x) and inclination (in d.y)
// using parametric equations for a sphere (a circle rotating around a diameter generates a sphere):
float3 angle = make_float3(cos(d.x) * sin(d.y), -cos(d.y), sin(d.x) * sin(d.y));
// d.x is the azimuth
// d.y is the inclination
// Pitch angle = cos(d.x) * sin(d.y) // around the X axis
// Yaw angle = -cos(d.y) // around the Y axis
// Roll angle = sin(d.x) * sin(d.y) // around the Z axis
float3 ray_origin = eye; // camera eye position is origin of this ray
float3 ray_direction = normalize(angle.x*normalize(U) + angle.y*normalize(V) + angle.z*normalize(W));
// apply the angles on U,V,W coordinates. function updateCamera() updates them from eye,lookat,up
// using calculateCameraVariables() in sutil.cpp in the same way as on the pinhole cam
// finally "normalize" ensures to get a vector with unit length 1.0