struct CameraParams { position: vec3, depth: f32, orientation: vec4, fov: vec2, target_size: vec2, } fn get_ray_direction(cp: CameraParams, pixel: vec2) -> vec3 { let half_size = 0.5 * vec2(cp.target_size); let ndc = (vec2(pixel) + vec2(0.5) - half_size) / half_size; // Right-handed coordinate system with X=right, Y=up, and Z=towards the camera let local_dir = vec3(ndc * tan(0.5 * cp.fov), -1.0); return normalize(qrot(cp.orientation, local_dir)); } fn get_projected_pixel_float(cp: CameraParams, point: vec3) -> vec2 { let local_dir = qrot(qinv(cp.orientation), point - cp.position); if local_dir.z >= 0.0 { return vec2(-1.0); } let ndc = local_dir.xy / (-local_dir.z * tan(0.5 * cp.fov)); let half_size = 0.5 * vec2(cp.target_size); return (ndc + vec2(1.0)) * half_size; } fn get_projected_pixel(cp: CameraParams, point: vec3) -> vec2 { return vec2(get_projected_pixel_float(cp, point)); }