Hướng dẫn này cho bạn biết cách sử dụng Cardboard SDK cho Android để tạo trải nghiệm Thực tế ảo (VR) của riêng bạn.
Bạn có thể dùng Cardboard SDK để biến điện thoại thông minh thành một nền tảng thực tế ảo. Điện thoại thông minh có thể hiển thị cảnh 3D bằng tính năng kết xuất lập thể, theo dõi và phản ứng với chuyển động đầu, đồng thời tương tác với các ứng dụng bằng cách phát hiện thời điểm người dùng nhấn nút xem.
Để bắt đầu, bạn sẽ sử dụng HelloCardboard, một trò chơi minh hoạ các tính năng cốt lõi của Cardboard SDK. Trong trò chơi, người dùng khám phá một thế giới ảo để tìm và thu thập các đối tượng. Tài liệu này hướng dẫn bạn cách:
- Thiết lập môi trường phát triển
- Tải xuống và tạo ứng dụng minh hoạ
- Quét mã QR của một kính xem Cardboard để lưu các thông số của kính
- Theo dõi cử động đầu của người dùng
- Kết xuất hình ảnh lập thể bằng cách đặt ma trận phép chiếu khung hiển thị chính xác cho từng mắt
HelloCardboard sử dụng Android NDK. Mọi phương thức gốc đều:
- Được liên kết duy nhất với một phương thức lớp
HelloCardboardApp
hoặc - Tạo hoặc xoá một thực thể của lớp đó
Thiết lập môi trường phát triển
Yêu cầu về phần cứng:
- Thiết bị Android chạy Android 8.0 "Oreo" (API cấp 26) trở lên
- Thiết bị xem Cardboard
Yêu cầu về phần mềm:
- Android Studio phiên bản 2024.1.2 "Bản cập nhật tính năng Koala" trở lên
- SDK Android 15.0 "Vanilla Ice Cream" (API cấp 35) trở lên
Phiên bản mới nhất của khung Android NDK
Để xem xét hoặc cập nhật các SDK đã cài đặt, hãy chuyển đến phần Preferences (Lựa chọn ưu tiên) > Appearance and Behavior (Giao diện và hành vi)
System Settings (Cài đặt hệ thống) > Android SDK trong Android Studio.
Tải xuống và tạo ứng dụng minh hoạ
Cardboard SDK được tạo bằng tệp tiêu đề Vulkan được biên dịch sẵn cho từng chương trình đổ bóng. Bạn có thể xem các bước để tạo tệp tiêu đề từ đầu tại đây.
Chạy lệnh sau để sao chép Cardboard SDK và ứng dụng minh hoạ HelloCardboard từ GitHub:
git clone https://github.com/googlevr/cardboard.git
Trong Android Studio, hãy chọn Open an existing Android Studio Project (Mở một dự án Android Studio hiện có), sau đó chọn thư mục mà bạn đã sao chép Cardboard SDK và ứng dụng minh hoạ HelloCardboard vào.
Mã của bạn sẽ xuất hiện trong cửa sổ Project (Dự án) trong Android Studio.
Để hợp nhất Cardboard SDK, hãy nhấp đúp vào lựa chọn assemble (hợp nhất) trong thư mục cardboard/:sdk/Tasks/build (cardboard/:sdk/Tasks/build) trong thẻ Gradle (View > Tool Windows > Gradle) (Xem > Cửa sổ công cụ > Gradle).
Chạy ứng dụng minh hoạ HelloCardboard trên điện thoại bằng cách chọn Run (Chạy) > Run... (Chạy...) rồi chọn mục tiêu
hellocardboard-android
.
Quét mã QR
Để lưu các thông số của thiết bị, hãy quét mã QR trên kính xem Cardboard:
Nếu người dùng nhấn vào "BỎ QUA" và không có thông số nào được lưu trước đó, thì Cardboard sẽ lưu các thông số của Google Cardboard phiên bản 1 (ra mắt tại Google I/O 2014).
Xem bản minh hoạ
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.
Cách tìm và thu thập một quả cầu:
Di chuyển đầu theo hướng bất kỳ cho đến khi bạn thấy một hình dạng nổi.
Nhìn thẳng vào quả cầu. Việc này khiến màu sắc của biểu tượng thay đổi.
Nhấn nút trên kính xem Cardboard để "thu thập" quả 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 kính xem Cardboard, phương thức nativeSwitchViewer
sẽ được gọi. nativeSwitchViewer
cuộc gọi CardboardQrCode_scanQrCodeAndSaveDeviceParams
, thao tác này sẽ mở cửa sổ để quét mã QR của người xem. Độ biến dạng ống kính và các thông số khác của người xem sẽ được cập nhật sau khi mã QR được quét.
// Called by JNI method
void HelloCardboardApp::SwitchViewer() {
CardboardQrCode_scanQrCodeAndSaveDeviceParams();
}
Bật trình mô phỏng x86 của Android Studio
Để tạo cho trình mô phỏng x86 của Android Studio, hãy xoá dòng sau đây khỏi các tệp build.gradle
trong SDK và Sample:
abiFilters 'armeabi-v7a', 'arm64-v8a'
Thao tác này sẽ bật tất cả ABI và làm tăng đáng kể kích thước của tệp .aar
được tạo. Hãy xem bài viết ABI Android để biết thêm thông tin.
Theo dõi chuyển động của đầu
Tạo thiết bị theo dõi đầu
Trình theo dõi đầu được tạo một lần trong hàm khởi tạo của HelloCardboardApp
:
HelloCardboardApp::HelloCardboardApp(JavaVM* vm, jobject obj, jobject asset_mgr_obj) {
Cardboard_initializeAndroid(vm, obj); // Must be called in constructor
head_tracker_ = CardboardHeadTracker_create();
}
Khi VrActivity
được tạo, một thực thể của lớp HelloCardboardApp
sẽ được tạo bằng cách gọi phương thức nativeOnCreate
:
public void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
nativeApp = nativeOnCreate(getAssets());
//...
}
Tạm dừng và tiếp tục theo dõi đầu
Để tạm dừng, tiếp tục và huỷ trình theo dõi đầu, bạn phải gọi lần lượt CardboardHeadTracker_pause(head_tracker_)
, CardboardHeadTracker_resume(head_tracker_)
và CardboardHeadTracker_destroy(head_tracker_)
. Trong ứng dụng "HelloCardboard", chúng ta gọi các đối tượng này trong nativeOnPause
, nativeOnResume
và nativeOnDestroy
:
// Code to pause head tracker in hello_cardboard_app.cc
void HelloCardboardApp::OnPause() { CardboardHeadTracker_pause(head_tracker_); }
// Call nativeOnPause in VrActivity
@Override
protected void onPause() {
super.onPause();
nativeOnPause(nativeApp);
//...
}
// Code to resume head tracker in hello_cardboard_app.cc
void HelloCardboardApp::onResume() {
CardboardHeadTracker_resume(head_tracker_);
//...
}
// Call nativeOnResume in VrActivity
@Override
protected void onResume() {
super.onResume();
//...
nativeOnResume(nativeApp);
}
// Code to destroy head tracker in hello_cardboard_app.cc
HelloCardboardApp::~HelloCardboardApp() {
CardboardHeadTracker_destroy(head_tracker_);
//...
}
// Call nativeOnDestroy in VrActivity
@Override
protected void onDestroy() {
super.onDestroy();
nativeOnDestroy(nativeApp);
nativeApp = 0;
}
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à dùng các thông số đó để tạo đối tượng biến dạng ống kính, đối tượng này sẽ áp dụng độ biến dạng ống kính thích hợp cho nội dung được kết xuất:
CardboardQrCode_getSavedDeviceParams(&buffer, &size);
CardboardLensDistortion_destroy(lens_distortion_);
lens_distortion_ = CardboardLensDistortion_create(
buffer, size, screen_width_, screen_height_);
CardboardQrCode_destroy(buffer);
Kết xuất
Việc kết xuất nội dung trong Cardboard bao gồm những việc sau:
- Tạo hoạ tiết
- Lấy ma trận khung hiển thị và ma trận chiếu cho mắt trái và mắt phải
- Tạo trình kết xuất và đặt lưới biến dạng
- Kết xuất từng khung hình
Tạo hoạ tiết
Tất cả nội dung đều được vẽ lê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 được khởi chạy lần lượt trong _leftEyeTexture
và _rightEyeTexture
.
void HelloCardboardApp::GlSetup() {
LOGD("GL SETUP");
if (framebuffer_ != 0) {
GlTeardown();
}
// Create render texture.
glGenTextures(1, &texture_);
glBindTexture(GL_TEXTURE_2D, texture_);
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, screen_width_, screen_height_, 0,
GL_RGB, GL_UNSIGNED_BYTE, 0);
left_eye_texture_description_.texture = texture_;
left_eye_texture_description_.left_u = 0;
left_eye_texture_description_.right_u = 0.5;
left_eye_texture_description_.top_v = 1;
left_eye_texture_description_.bottom_v = 0;
right_eye_texture_description_.texture = texture_;
right_eye_texture_description_.left_u = 0.5;
right_eye_texture_description_.right_u = 1;
right_eye_texture_description_.top_v = 1;
right_eye_texture_description_.bottom_v = 0;
//...
CHECKGLERROR("GlSetup");
}
Các hoạ tiết này được truyền vào dưới dạng tham số cho CardboardDistortionRenderer_renderEyeToDisplay
.
Nhận ma trận khung hiển thị và ma trận 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(
lens_distortion_, kLeft, eye_matrices_[0]);
CardboardLensDistortion_getEyeFromHeadMatrix(
lens_distortion_, kRight, eye_matrices_[1]);
CardboardLensDistortion_getProjectionMatrix(
lens_distortion_, kLeft, kZNear, kZFar, projection_matrices_[0]);
CardboardLensDistortion_getProjectionMatrix(
lens_distortion_, kRight, kZNear, kZFar, projection_matrices_[1]);
Tiếp theo, hãy lấy các lưới biến dạng cho từng mắt và truyền lưới đó đến trình kết xuất biến dạng:
CardboardLensDistortion_getDistortionMesh(lens_distortion_, kLeft, &left_mesh);
CardboardLensDistortion_getDistortionMesh(lens_distortion_, kRight, &right_mesh);
Tạo trình kết xuất và đặt lưới biến dạng chính xác
Bạn chỉ cần khởi chạy trình kết xuất một lần. Sau khi trình kết xuất được tạo, hãy đặt lưới biến dạng mới cho mắt trái và mắt phải theo các giá trị lưới mà hàm CardboardLensDistortion_getDistortionMesh
trả về.
distortion_renderer_ = CardboardOpenGlEs2DistortionRenderer_create();
CardboardDistortionRenderer_setMesh(distortion_renderer_, &left_mesh, kLeft);
CardboardDistortionRenderer_setMesh(distortion_renderer_, &right_mesh, kRight);
Hiển thị nội dung
Đối với mỗi khung hình, hãy truy xuất hướng đầu hiện tại từ CardboardHeadTracker_getPose
:
CardboardHeadTracker_getPose(head_tracker_, monotonic_time_nano, &out_position[0], &out_orientation[0]);
Sử dụng hướng đầu hiện tại với các ma trận khung hiển thị và ma trận chiếu để tạo ma trận chiếu khung hiển thị cho từng mắt và hiển thị nội dung lên màn hình:
// Draw eyes views
for (int eye = 0; eye < 2; ++eye) {
glViewport(eye == kLeft ? 0 : screen_width_ / 2, 0, screen_width_ / 2,
screen_height_);
Matrix4x4 eye_matrix = GetMatrixFromGlArray(eye_matrices_[eye]);
Matrix4x4 eye_view = eye_matrix * head_view_;
Matrix4x4 projection_matrix =
GetMatrixFromGlArray(projection_matrices_[eye]);
Matrix4x4 modelview_target = eye_view * model_target_;
modelview_projection_target_ = projection_matrix * modelview_target;
modelview_projection_room_ = projection_matrix * eye_view;
// Draw room and target. Replace this to render your own content.
DrawWorld();
}
Sử dụng CardboardDistortionRenderer_renderEyeToDisplay
để áp dụng tính năng hiệu chỉnh độ biến dạng cho nội dung và hiển thị nội dung lên màn hình.
// Render
CardboardDistortionRenderer_renderEyeToDisplay(
distortion_renderer_, /* target_display = */ 0, /* x = */ 0, /* y = */ 0,
screen_width_, screen_height_, &left_eye_texture_description_,
&right_eye_texture_description_);