Explain how ray direction is calculated in environment map camera

Hi,

I’m working through the OptiX tutorials and have some question about Tutorial 12.

This tutorial is using environment map camera. However, I’m not understanding the following code:
RT_PROGRAM void env_camera()
{
size_t2 screen = output_buffer.size();
float2 d = make_float2(launch_index) / make_float2(screen) * make_float2(2.0f * M_PIf , M_PIf) + make_float2(M_PIf, 0);
float3 angle = make_float3(cos(d.x) * sin(d.y), -cos(d.y), sin(d.x) * sin(d.y));
float3 ray_origin = eye;
float3 ray_direction = normalize(angle.x * normalize(U) + angle.y * normalize(V) + angle.z * normalize(W));

}

Can someone explain the math behind these code or point out the resource which I can learn.

Thanks a lot

Wei

“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