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();
        }
    }