Hướng dẫn này cho bạn biết cách sử dụng Cardboard SDK dành cho Android để tạo ra 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. Một chiếc điện thoại thông minh có thể hiển thị cảnh 3D với kết xuất lập thể, theo dõi và phản ứng với chuyển động của đầu, và 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ạ thể hiện các của Cardboard SDK. Trong trò chơi, người dùng nhìn quanh thế giới ảo để tìm và thu thập các đối tượng. Hướng dẫ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 thiết bị xem Cardboard để lưu các tham số của thiết bị này
- 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 chiếu khung hiển thị chính xác cho mỗi mắt
HelloCardboard sử dụng Android NDK. Mỗi phương thức gốc đều:
- Giới hạn 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 bìa các tông
Yêu cầu về phần mềm:
- Android Studio phiên bản 2022.1.1 "Electric Eel" hoặc cao hơn
- SDK Android 13.0 "Tiramisu" (API cấp 33) trở lên
Phiên bản mới nhất của khung Android NDK
Để xem lại hoặc cập nhật các SDK đã cài đặt, hãy chuyển đến phần Lựa chọn ưu tiên > Giao diện và hành vi
Cài đặt hệ thống > SDK Android trong Android Studio.
Tải xuống và tạo ứng dụng minh hoạ
SDK Cardboard được xây dựng bằng Vulkan được biên dịch trước tệp tiêu đề cho mỗi chương trình đổ bóng. Bạn có thể tìm thấy các bước tạo tệp tiêu đề từ đầu tại đây.
Chạy lệnh sau để sao chép SDK của Cardboard và bản minh hoạ HelloCardboard ứng dụng 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 nơi SDK Cardboard và ứng dụng minh hoạ HelloCardboard được sao chép vào.
Mã nguồn của bạn sẽ xuất hiện trong cửa sổ Project (Dự án) trong Android Studio.
Để lắp ráp Cardboard SDK, hãy nhấp đúp vào tùy chọn lắp ráp bên trong Thư mục 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) > Chạy... và 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 thiết bị xem Cardboard:
Nếu người dùng nhấn "BỎ QUA" và không có thông số nào đã lưu trước đó, Cardboard sẽ lưu Thông số Google Cardboard phiên bản 1 (được phát hành tại Google I/O 2014).
Xem bản minh hoạ
Trong HelloCardboard, bạn sẽ tìm và thu thập các hình cầu trắc địa trong không gian 3D.
Cách tìm và thu thập một hình cầu:
Di chuyển đầu xung quanh theo bất kỳ hướng nào cho đến khi bạn nhìn thấy một hình dạng lơ lửng.
Nhìn thẳng vào hình cầu. Thao tác này sẽ khiến nút thay đổi màu sắc.
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 giữa các thiết bị xem Cardboard, nativeSwitchViewer
được gọi. nativeSwitchViewer
cuộc gọi
CardboardQrCode_scanQrCodeAndSaveDeviceParams
sẽ mở ra cửa sổ để quét
mã QR của người xem. Độ biến dạng ống kính của người xem và các thông số khác được cập nhật một lần
mã QR đã được quét.
// Called by JNI method
void HelloCardboardApp::SwitchViewer() {
CardboardQrCode_scanQrCodeAndSaveDeviceParams();
}
Bật trình mô phỏng Android Studio x86
Để tạo bản dựng cho trình mô phỏng Android Studio x86, hãy xoá dòng sau khỏi
build.gradle
tệp trong SDK
và Mẫu:
abiFilters 'armeabi-v7a', 'arm64-v8a'
Điều này cho phép tất cả ABI và sẽ làm tăng đáng kể kích thước của tệp được tạo
Tệp .aar
. Xem 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 chuyển động của đầu
Công cụ theo dõi chuyển động đầ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 thiết bị theo dõi chuyển động của đầu
Để tạm dừng, tiếp tục và huỷ bỏ công cụ theo dõi chuyển động của đầu,
CardboardHeadTracker_pause(head_tracker_)
, CardboardHeadTracker_resume(head_tracker_)
và CardboardHeadTracker_destroy(head_tracker_)
phải được gọi tương ứng. Trong
"HelloCardboard" chúng tôi sẽ gọi chúng bằng 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 lần 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 chúng để tạo đối tượng méo ống kính, áp dụng độ méo ố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
Kết xuất nội dung trong Cardboard bao gồm những việc sau:
- Tạo hoạ tiết
- Tải ma trận chế độ xem 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à thiết lập 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ẽ trên một hoạ tiết, được chia thành nhiều phần cho mắt trái và mắt phải.
Các phần này được khởi tạo 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 dưới dạng tham số đến CardboardDistortionRenderer_renderEyeToDisplay
.
Xem ma trận chiếu 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 lưới méo cho mỗi mắt và truyền lưới đó đến trình kết xuất méo:
CardboardLensDistortion_getDistortionMesh(lens_distortion_, kLeft, &left_mesh);
CardboardLensDistortion_getDistortionMesh(lens_distortion_, kRight, &right_mesh);
Tạo trình kết xuất và thiết lập đúng lưới méo
Trình kết xuất chỉ cần được khởi động một lần. Sau khi tạo trình kết xuất, hãy đặt
lưới méo cho mắt trái và phải theo các giá trị lưới được trả về từ
Hàm CardboardLensDistortion_getDistortionMesh
.
distortion_renderer_ = CardboardOpenGlEs2DistortionRenderer_create();
CardboardDistortionRenderer_setMesh(distortion_renderer_, &left_mesh, kLeft);
CardboardDistortionRenderer_setMesh(distortion_renderer_, &right_mesh, kRight);
Kết xuất 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 ma trận khung hiển thị và ma trận chiếu để tạo khung hiển thị ma trận chiếu cho mỗi mắt và kết xuất 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();
}
Dùng CardboardDistortionRenderer_renderEyeToDisplay
để áp dụng hiệu ứng méo
sửa 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_);