Panduan ini menunjukkan cara menggunakan Cardboard SDK untuk Android guna membuat pengalaman Virtual Reality (VR) Anda sendiri.
Anda dapat menggunakan Cardboard SDK untuk mengubah smartphone menjadi platform VR. Smartphone dapat menampilkan adegan 3D dengan rendering stereoskopik, melacak dan bereaksi terhadap gerakan kepala, serta berinteraksi dengan aplikasi dengan mendeteksi saat pengguna menekan tombol penampil.
Untuk memulai, Anda akan menggunakan HelloCardboard, game demo yang menunjukkan fitur inti Cardboard SDK. Dalam game, pengguna melihat-lihat dunia virtual untuk menemukan dan mengumpulkan objek. Bagian ini menunjukkan cara:
- Menyiapkan lingkungan pengembangan
- Mendownload dan mem-build aplikasi demo
- Pindai kode QR penampil Cardboard untuk menyimpan parameternya
- Melacak gerakan kepala pengguna
- Merender gambar stereoskopik dengan menyetel matriks proyeksi tampilan yang benar untuk setiap mata
HelloCardboard menggunakan Android NDK. Setiap metode native adalah:
- Terikat secara unik ke metode class
HelloCardboardApp
, atau - Membuat atau menghapus instance class tersebut
Menyiapkan lingkungan pengembangan
Persyaratan hardware:
- Perangkat Android yang menjalankan Android 8.0 "Oreo" (level API 26) atau yang lebih tinggi
- Penampil Cardboard
Persyaratan software:
- Android Studio versi 2024.1.2 "Koala Feature Drop" atau yang lebih baru
- Android SDK 15.0 "Vanilla Ice Cream" (level API 35) atau yang lebih tinggi
Versi terbaru framework Android NDK
Untuk meninjau atau mengupdate SDK yang diinstal, buka Preferences > Appearance and Behavior
System Settings > Android SDK di Android Studio.
Mendownload dan mem-build aplikasi demo
Cardboard SDK dibuat menggunakan file header Vulkan yang telah dikompilasi sebelumnya untuk setiap shader. Langkah-langkah untuk membuat file header dari awal dapat ditemukan di sini.
Jalankan perintah berikut untuk meng-clone Cardboard SDK dan aplikasi demo HelloCardboard dari GitHub:
git clone https://github.com/googlevr/cardboard.git
Di Android Studio, pilih Open an existing Android Studio Project, lalu pilih direktori tempat Cardboard SDK dan aplikasi demo HelloCardboard di-clone.
Kode Anda akan muncul di jendela Project di Android Studio.
Untuk merakit Cardboard SDK, klik dua kali opsi assemble dalam folder cardboard/:sdk/Tasks/build di tab Gradle (View > Tool Windows > Gradle).
Jalankan aplikasi demo HelloCardboard di ponsel Anda dengan memilih Run > Run... dan pilih target
hellocardboard-android
.
Pindai kode QR
Untuk menyimpan parameter perangkat, pindai kode QR di penampil Cardboard:
Jika pengguna menekan "LEWATI" dan tidak ada parameter yang disimpan sebelumnya, Cardboard akan menyimpan parameter Google Cardboard v1 (diluncurkan di Google I/O 2014).
Coba demo
Di HelloCardboard, Anda akan mencari dan mengumpulkan bola geodesik di ruang 3D.
Untuk menemukan dan mengumpulkan bola:
Gerakkan kepala Anda ke segala arah hingga Anda melihat bentuk mengambang.
Lihat langsung ke arah bola. Hal ini menyebabkan warna berubah.
Tekan tombol penampil Cardboard untuk "mengumpulkan" bola.
Mengonfigurasi perangkat
Saat pengguna mengetuk ikon roda gigi untuk mengganti penampil Cardboard, metode nativeSwitchViewer
dipanggil. nativeSwitchViewer
calls
CardboardQrCode_scanQrCodeAndSaveDeviceParams
, yang membuka jendela untuk memindai
kode QR penonton. Distorsi lensa penonton dan parameter lainnya diperbarui setelah kode QR dipindai.
// Called by JNI method
void HelloCardboardApp::SwitchViewer() {
CardboardQrCode_scanQrCodeAndSaveDeviceParams();
}
Mengaktifkan emulator x86 Android Studio
Untuk membuat emulator x86 Android Studio, hapus baris berikut dari file
build.gradle
di SDK
dan Sample:
abiFilters 'armeabi-v7a', 'arm64-v8a'
Hal ini akan mengaktifkan semua ABI dan akan meningkatkan ukuran file .aar
yang dihasilkan secara signifikan. Lihat ABI Android
untuk mengetahui informasi selengkapnya.
Pelacakan gerak kepala
Membuat pelacak kepala
Pelacak kepala dibuat satu kali di konstruktor HelloCardboardApp
:
HelloCardboardApp::HelloCardboardApp(JavaVM* vm, jobject obj, jobject asset_mgr_obj) {
Cardboard_initializeAndroid(vm, obj); // Must be called in constructor
head_tracker_ = CardboardHeadTracker_create();
}
Saat VrActivity
dibuat, instance class HelloCardboardApp
dihasilkan dengan memanggil metode nativeOnCreate
:
public void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
nativeApp = nativeOnCreate(getAssets());
//...
}
Menjeda dan melanjutkan pelacak kepala
Untuk menjeda, melanjutkan, dan menghancurkan pelacak kepala, CardboardHeadTracker_pause(head_tracker_)
, CardboardHeadTracker_resume(head_tracker_)
, dan CardboardHeadTracker_destroy(head_tracker_)
harus dipanggil. Di aplikasi "HelloCardboard", kita memanggilnya di nativeOnPause
, nativeOnResume
, dan
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;
}
Distorsi lensa
Setiap kali Cardboard memindai kode QR baru, kode berikut akan membaca parameter yang disimpan dan menggunakannya untuk membuat objek distorsi lensa, yang menerapkan distorsi lensa yang tepat ke konten yang dirender:
CardboardQrCode_getSavedDeviceParams(&buffer, &size);
CardboardLensDistortion_destroy(lens_distortion_);
lens_distortion_ = CardboardLensDistortion_create(
buffer, size, screen_width_, screen_height_);
CardboardQrCode_destroy(buffer);
Rendering
Rendering konten di Cardboard melibatkan hal-hal berikut:
- Membuat tekstur
- Mendapatkan matriks tampilan dan proyeksi untuk mata kiri dan kanan
- Membuat perender dan menyetel mesh distorsi
- Merender setiap frame
Membuat tekstur
Semua konten digambar ke tekstur, yang dibagi menjadi beberapa bagian untuk mata kiri dan kanan.
Bagian ini masing-masing diinisialisasi di _leftEyeTexture
dan _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");
}
Tekstur ini diteruskan sebagai parameter ke CardboardDistortionRenderer_renderEyeToDisplay
.
Mendapatkan matriks tampilan dan proyeksi untuk mata kiri dan kanan
Pertama, ambil matriks mata untuk mata kiri dan kanan:
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]);
Selanjutnya, dapatkan mesh distorsi untuk setiap mata dan teruskan ke perender distorsi:
CardboardLensDistortion_getDistortionMesh(lens_distortion_, kLeft, &left_mesh);
CardboardLensDistortion_getDistortionMesh(lens_distortion_, kRight, &right_mesh);
Buat perender dan tetapkan mesh distorsi yang benar
Perender hanya perlu diinisialisasi sekali. Setelah perender dibuat, tetapkan mesh distorsi baru untuk mata kiri dan kanan sesuai dengan nilai mesh yang ditampilkan dari fungsi CardboardLensDistortion_getDistortionMesh
.
distortion_renderer_ = CardboardOpenGlEs2DistortionRenderer_create();
CardboardDistortionRenderer_setMesh(distortion_renderer_, &left_mesh, kLeft);
CardboardDistortionRenderer_setMesh(distortion_renderer_, &right_mesh, kRight);
Merender konten
Untuk setiap frame, ambil orientasi kepala saat ini dari CardboardHeadTracker_getPose
:
CardboardHeadTracker_getPose(head_tracker_, monotonic_time_nano, &out_position[0], &out_orientation[0]);
Gunakan orientasi kepala saat ini dengan matriks tampilan dan proyeksi untuk menyusun matriks proyeksi tampilan bagi setiap mata dan merender konten ke layar:
// 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();
}
Gunakan CardboardDistortionRenderer_renderEyeToDisplay
untuk menerapkan koreksi distorsi pada konten, dan merender konten ke layar.
// Render
CardboardDistortionRenderer_renderEyeToDisplay(
distortion_renderer_, /* target_display = */ 0, /* x = */ 0, /* y = */ 0,
screen_width_, screen_height_, &left_eye_texture_description_,
&right_eye_texture_description_);