Hướng dẫn nhanh về Google Cardboard dành cho iOS

Hướng dẫn này cho bạn biết cách sử dụng SDK của Cardboard dành cho iOS để tạo trải nghiệm Thực tế ảo (VR) của riêng bạn.

Bạn có thể sử dụng SDK của Cardboard để biến điện thoại thông minh thành nền tảng thực tế ảo. Điện thoại thông minh có thể hiển thị cảnh 3D ở chế độ kết xuất lập thể, theo dõi và phản ứng với chuyển động của đầu, cũng như tương tác với ứng dụng bằng cách phát hiện khi người dùng nhấn nút trình xem.

Để bắt đầu, bạn sẽ sử dụng HelloCardboard, một trò chơi minh hoạ minh hoạ các tính năng cốt lõi của SDK Cardboard. Trong trò chơi, người dùng sẽ nhìn xung quanh một thế giới ảo để tìm và thu thập các vật thể. Hướng dẫn này sẽ hướng dẫn bạn cách:

  • Thiết lập môi trường phát triển
  • Tải và tạo ứng dụng minh hoạ
  • Quét mã QR của thiết bị xem Cardboard để lưu các thông số của thiết bị
  • Theo dõi cử động đầu của người dùng
  • Kết xuất hình ảnh nổi bằng cách đặt độ méo chính xác cho mỗi mắt

Thiết lập môi trường phát triển

Yêu cầu về phần cứng:

Yêu cầu về phần mềm:

Tải và tạo ứng dụng minh hoạ

SDK của Cardboard được xây dựng bằng các tệp nguồn C++ có Vùng đệm giao thức được biên dịch trước. Bạn có thể xem các bước để tạo tệp nguồn từ đầu tại đây.

  1. Sao chép SDK Cardboard và ứng dụng minh hoạ Hello Cardboard từ GitHub bằng cách chạy lệnh sau:

    git clone https://github.com/googlevr/cardboard.git
  2. Cài đặt phần phụ thuộc Protocol Buffers (Vùng đệm giao thức) vào dự án Xcode bằng cách chạy lệnh này tại gốc kho lưu trữ:

    pod install
  3. Mở không gian làm việc của Cardboard (Cardboard.xcworkspace) trong Xcode.

  4. Hãy thay đổi mã nhận dạng gói của ứng dụng để có thể ký ứng dụng với nhóm của mình.

  5. Chuyển đến SDK > Xây dựng giai đoạn > Liên kết tệp nhị phân với thư viện

    1. Xoá libPods-sdk.a khỏi danh sách bằng cách chọn mục đó rồi nhấp vào nút "+".
    2. Thêm libProtobuf-C++.a vào danh sách bằng cách nhấp vào nút dấu "+" rồi chọn. Trong trường hợp bật lên thông báo gợi ý sử dụng XCFramework, hãy nhấp vào "Vẫn thêm".
  6. Nhấp vào Chạy.

Quét mã QR

Để lưu thông số thiết bị, hãy quét mã QR trên thiết bị xem Cardboard:

Dùng thử bản trình diễn

Trong HelloCardboard, bạn sẽ tìm kiếm và thu thập các quả cầu trắc địa trong không gian 3D.

Để tìm và thu thập hình cầu:

  1. Di chuyển đầu theo hướng bất kỳ cho đến khi bạn nhìn thấy một quả cầu trôi nổi.

  2. Nhìn thẳng vào quả cầu. Thao tác này sẽ làm thay đổi màu sắc.

  3. Nhấn nút thiết bị xem Cardboard để "thu thập" hình cầu.

Định cấu hình thiết bị

Khi người dùng nhấn vào biểu tượng bánh răng để chuyển đổi thiết bị xem Cardboard, phương thức didTapSwitchButton sẽ được gọi trong HelloCardboardOverlayView.

- (void)didTapSwitchButton:(id)sender {
  if ([self.delegate respondsToSelector:@selector(didTapBackButton)]) {
    [self.delegate didChangeViewerProfile];
  }
  self.settingsBackgroundView.hidden = YES;
}

Thao tác này sẽ gọi CardboardQrCode_scanQrCodeAndSaveDeviceParams để mở cửa sổ để quét mã QR của người xem. Khi người dùng quét mã QR, các tham số méo hình của thiết bị sẽ được cập nhật.

- (void)switchViewer {
  CardboardQrCode_scanQrCodeAndSaveDeviceParams();
}

- (void)didChangeViewerProfile {
  [self pauseCardboard];
  [self switchViewer];
  [self resumeCardboard];
}

Theo dõi chuyển động của đầu

Tạo thiết bị theo dõi chuyển động của đầu

Trình theo dõi chuyển động được tạo một lần trong phương thức viewDidLoad của HelloCardboardViewController:

_cardboardHeadTracker = CardboardHeadTracker_create();

Tạm dừng và tiếp tục thiết bị theo dõi chuyển động của đầu

Phương thức pauseCardboardresumeCardboard trong lớp HelloCardboardViewController sẽ tạm dừng và tiếp tục trình theo dõi chuyển động tương ứng. resumeCardboard cũng đặt cờ _updateParams, điều này khiến các tham số thiết bị được cập nhật trong lệnh gọi vẽ tiếp theo.

- (void)pauseCardboard {
  self.paused = true;
  CardboardHeadTracker_pause(_cardboardHeadTracker);
}

- (void)resumeCardboard {
  // Parameters may have changed.
  _updateParams = YES;

  // Check for device parameters existence in app storage. If they're missing,
  // we must scan a Cardboard QR code and save the obtained parameters.
  uint8_t *buffer;
  int size;
  CardboardQrCode_getSavedDeviceParams(&buffer, &size);
  if (size == 0) {
    [self switchViewer];
  }
  CardboardQrCode_destroy(buffer);

  CardboardHeadTracker_resume(_cardboardHeadTracker);
  self.paused = false;
}

Biến dạng ống kính

Mỗi khi Cardboard quét một mã QR mới, mã sau đây sẽ đọc các thông số đã lưu và sử dụng các thông số đó để tạo đối tượng méo ống kính, từ đó áp dụng độ méo ống kính thích hợp cho nội dung đã kết xuất:

CardboardQrCode_getSavedDeviceParams(&encodedDeviceParams, &size);

// Create CardboardLensDistortion.
CardboardLensDistortion_destroy(_cardboardLensDistortion);
_cardboardLensDistortion =
    CardboardLensDistortion_create(encodedDeviceParams, size, width, height);

// Initialize HelloCardboardRenderer.
_renderer.reset(new cardboard::hello_cardboard::HelloCardboardRenderer(
      _cardboardLensDistortion, _cardboardHeadTracker, width, height));

Kết xuất

Quá trình kết xuất nội dung trong Cardboard bao gồm những yếu tố sau:

  • Tạo hoạ tiết
  • Lấy ma trận nhìn và chiếu cho mắt trái và mắt phải
  • Tạo trình kết xuất đồ hoạ và thiết lập lưới biến dạng
  • Kết xuất từng khung

Tạo hoạ tiết

Nội dung được vẽ trên một hoạ tiết, được chia thành các phần cho mắt trái và mắt phải. Các phần này lần lượt được khởi tạo trong _leftEyeTexture_rightEyeTexture. Ứng dụng mẫu sử dụng một hoạ tiết duy nhất cho cả hai mắt, nhưng bạn cũng có thể tạo một hoạ tiết riêng cho mỗi mắt.

// Generate texture to render left and right eyes.
glGenTextures(1, &_eyeTexture);
glBindTexture(GL_TEXTURE_2D, _eyeTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _width, _height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);

_leftEyeTexture.texture = _eyeTexture;
_leftEyeTexture.left_u = 0;
_leftEyeTexture.right_u = 0.5;
_leftEyeTexture.top_v = 1;
_leftEyeTexture.bottom_v = 0;

_rightEyeTexture.texture = _eyeTexture;
_rightEyeTexture.left_u = 0.5;
_rightEyeTexture.right_u = 1;
_rightEyeTexture.top_v = 1;
_rightEyeTexture.bottom_v = 0;
CheckGLError("Create Eye textures");

Các hoạ tiết này được truyền dưới dạng tham số cho CardboardDistortionRenderer_renderEyeToDisplay.

Lấy ma trận nhìn và chiếu cho mắt trái và mắt phải

Trước tiên, hãy truy xuất ma trận mắt cho mắt trái và mắt phải:

CardboardLensDistortion_getEyeFromHeadMatrix(_lensDistortion, kLeft, _eyeMatrices[kLeft]);
CardboardLensDistortion_getEyeFromHeadMatrix(_lensDistortion, kRight, _eyeMatrices[kRight]);
CardboardLensDistortion_getProjectionMatrix(_lensDistortion, kLeft, kZNear, kZFar,
                                            _projMatrices[kLeft]);
CardboardLensDistortion_getProjectionMatrix(_lensDistortion, kRight, kZNear, kZFar,
                                            _projMatrices[kRight]);

Tiếp theo, hãy lấy lưới biến dạng cho mỗi mắt rồi truyền đến trình kết xuất biến dạng:

CardboardLensDistortion_getDistortionMesh(_lensDistortion, kLeft, &leftMesh);
CardboardLensDistortion_getDistortionMesh(_lensDistortion, kRight, &rightMesh);

Tạo trình kết xuất đồ hoạ và thiết lập đúng lưới méo

Trình kết xuất chỉ cần được khởi chạy một lần. Sau khi tạo trình kết xuất, hãy thiết lập lưới méo mới cho mắt trái và mắt phải theo các giá trị lưới được hàm CardboardLensDistortion_getDistortionMesh trả về.

_distortionRenderer = CardboardOpenGlEs2DistortionRenderer_create();
CardboardDistortionRenderer_setMesh(_distortionRenderer, &leftMesh, kLeft);
CardboardDistortionRenderer_setMesh(_distortionRenderer, &rightMesh, kRight);

Hiển thị nội dung

Truy xuất hướng đầu hiện tại từ CardboardHeadTracker_getPose:

CardboardHeadTracker_getPose(_headTracker, targetTime, position, orientation);
_headView =
    GLKMatrix4Multiply(GLKMatrix4MakeTranslation(position[0], position[1], position[2]),
                       GLKMatrix4MakeWithQuaternion(GLKQuaternionMakeWithArray(orientation)));

Sử dụng hướng đầu hiện tại với ma trận khung nhìn và ma trận chiếu để tạo ma trận phép chiếu khung hiển thị và sử dụng các ma trận này để kết xuất nội dung thế giới cho mỗi mắt:

// Draw left eye.
glViewport(0, 0, _width / 2.0, _height);
glScissor(0, 0, _width / 2.0, _height);
DrawWorld(_leftEyeViewPose, GLKMatrix4MakeWithArray(_projMatrices[kLeft]));

// Draw right eye.
glViewport(_width / 2.0, 0, _width / 2.0, _height);
glScissor(_width / 2.0, 0, _width / 2.0, _height);
DrawWorld(_rightEyeViewPose, GLKMatrix4MakeWithArray(_projMatrices[kRight]));

Sử dụng CardboardDistortionRenderer_renderEyeToDisplay để áp dụng tính năng chỉnh sửa độ méo cho nội dung và hiển thị nội dung đó trên màn hình.

CardboardDistortionRenderer_renderEyeToDisplay(_distortionRenderer, renderTarget, /*x=*/0,
                                               /*y=*/0, _width, _height, &_leftEyeTexture,
                                               &_rightEyeTexture);