private JsonManifest.View Capture(
            string base_image_name,
            Quaternion orientation,
            Vector3 position,
            Matrix4x4 reference_from_world,
            string export_path)
        {
            // Save initial camera state
            Vector3    initial_camera_position = color_camera_.transform.position;
            Quaternion initial_camera_rotation = color_camera_.transform.rotation;

            // Setup cameras
            color_camera_.transform.position = position;
            color_camera_.transform.rotation = orientation;
            depth_camera_.transform.position = position;
            depth_camera_.transform.rotation = orientation;

            // Write out color data
            string color_image_name = base_image_name + "_Color." +
                                      (IsHighDynamicRange() ? "exr" : "png");

            color_camera_.ResetReplacementShader();
            color_camera_.targetTexture = color_render_texture_;
            color_camera_.Render();
            WriteImage(color_render_texture_, Texture2DFromDynamicRange(), PathCombine(export_path, color_image_name), true);

            // Write out depth data
            string depth_image_name = base_image_name + "_Depth.exr";

            depth_camera_.SetReplacementShader(render_depth_shader_, "RenderType");
            depth_camera_.targetTexture = depth_render_texture_;
            depth_camera_.Render();
            WriteImage(depth_render_texture_, texture_fp32_, PathCombine(export_path, depth_image_name), false);

            // Record the capture results.
            JsonManifest.View view = new JsonManifest.View();
            view.projective_camera.image_width           = color_render_texture_.width;
            view.projective_camera.image_height          = color_render_texture_.height;
            view.projective_camera.clip_from_eye_matrix  = JsonManifest.MatrixToArray(color_camera_.projectionMatrix);
            view.projective_camera.world_from_eye_matrix = JsonManifest.MatrixToArray(reference_from_world * color_camera_.cameraToWorldMatrix);
            view.projective_camera.depth_type            = "EYE_Z";
            view.depth_image_file.color.path             = color_image_name;
            view.depth_image_file.color.channel_0        = "R";
            view.depth_image_file.color.channel_1        = "G";
            view.depth_image_file.color.channel_2        = "B";
            view.depth_image_file.color.channel_alpha    = "CONSTANT_ONE";
            view.depth_image_file.depth.path             = depth_image_name;
            view.depth_image_file.depth.channel_0        = "R";

            // Restore camera state
            color_camera_.transform.position = initial_camera_position;
            color_camera_.transform.rotation = initial_camera_rotation;

            return(view);
        }
        private void CaptureSample()
        {
            // Transforms all cameras from world space to the eye space
            // of the reference camera.
            Matrix4x4    reference_from_world = color_camera_.worldToCameraMatrix;
            const string base_image_name      = "Cube";

            string[] cube_face_names =
            {
                "Front",
                "Back",
                "Right",
                "Left",
                "Top",
                "Bottom",
            };

            int num_sides = cube_face_names.Length;

            if (current_side_ == 0)
            {
                StartCaptureSamples();
                view_group_       = new JsonManifest.ViewGroup();
                view_group_.views = new JsonManifest.View[6];
            }

            int        side = current_side_;
            Quaternion face_rotation;

            switch (side)
            {
            case 0:
                face_rotation = Quaternion.identity;
                break;

            case 1:
                face_rotation = Quaternion.AngleAxis(180f, Vector3.up);
                break;

            case 2:
                face_rotation = Quaternion.AngleAxis(90f, Vector3.up);
                break;

            case 3:
                face_rotation = Quaternion.AngleAxis(-90f, Vector3.up);
                break;

            case 4:
                face_rotation = Quaternion.AngleAxis(-90f, Vector3.right);
                break;

            case 5:
            default:
                face_rotation = Quaternion.AngleAxis(90f, Vector3.right);
                break;
            }

            string progress_status     = "Baking " + (sample_index_ + 1) + "/ " + samples_per_face_ + " Frame " + (capture_frame_ + 1) + "/" + max_frames_;
            int    capture_task_index  = sample_index_ * num_sides + side;
            int    total_capture_tasks = samples_per_face_ * num_sides * max_frames_;

            status_interface_.SendProgress(progress_status,
                                           (float)capture_task_index / total_capture_tasks);
            if (!status_interface_.TaskContinuing())
            {
                return;
            }

            // Use cached samples
            JsonManifest.View view = Capture(
                base_image_name + "_" + cube_face_names[side] + "_" + sample_index_,
                face_rotation,
                samples_[sample_index_],
                reference_from_world,
                export_path_);

            // Shows the task is complete.
            status_interface_.SendProgress(progress_status,
                                           (float)(capture_task_index + 1) / total_capture_tasks);

            switch (side)
            {
            case 0:
                view_group_.views[0] = view;
                break;

            case 1:
                view_group_.views[1] = view;
                break;

            case 2:
                view_group_.views[3] = view;
                break;

            case 3:
                view_group_.views[2] = view;
                break;

            case 4:
                view_group_.views[5] = view;
                break;

            case 5:
            default:
                view_group_.views[4] = view;
                break;
            }

            ++current_side_;
            if (current_side_ == num_sides)
            {
                if (sample_index_ == 0)
                {
                    // Forces recreation of render targets at the normal resolution after
                    // capturing the center headbox at the typically-higher resolution.
                    DestroyRenderTargets();
                }

                current_side_ = 0;
                capture_manifest_.view_groups.Add(view_group_);
                EndCaptureSample();
            }
        }