คู่มือนี้แสดงวิธีใช้ Cardboard SDK สำหรับ Android เพื่อสร้างประสบการณ์ Virtual Reality (VR) ของคุณเอง
คุณใช้ Cardboard SDK เปลี่ยนสมาร์ทโฟนให้เป็นแพลตฟอร์ม VR ได้ สมาร์ทโฟน สามารถแสดงฉาก 3 มิติที่มีการแสดงภาพสามมิติ ติดตามและตอบสนองการเคลื่อนไหวของศีรษะ และโต้ตอบกับแอปด้วยการตรวจจับเมื่อผู้ใช้กดปุ่มบนแว่น
ในการเริ่มใช้งาน คุณจะใช้ HelloCardboard ซึ่งเป็นเกมสาธิตที่สาธิตวิธีการหลัก ของ Cardboard SDK ในเกม ผู้ใช้จะมองไปรอบโลกเสมือนจริงเพื่อค้นหาและ เก็บรวบรวมออบเจ็กต์ ซึ่งจะแสดงวิธีการต่างๆ ดังนี้
- ตั้งค่าสภาพแวดล้อมในการพัฒนาซอฟต์แวร์
- ดาวน์โหลดและสร้างแอปเดโม
- สแกนคิวอาร์โค้ดของแว่น Cardboard เพื่อบันทึกพารามิเตอร์
- ติดตามการเคลื่อนไหวศีรษะของผู้ใช้
- แสดงภาพสามมิติโดยการตั้งค่าเมทริกซ์การฉายภาพที่ถูกต้องสำหรับดวงตาแต่ละข้าง
HelloCardboard ใช้ Android NDK วิธีเนทีฟทั้งหมดมีดังนี้
- ผูกกับเมธอดคลาส
HelloCardboardApp
แบบไม่ซ้ำ หรือ - สร้างหรือลบอินสแตนซ์ของคลาสนั้น
ตั้งค่าสภาพแวดล้อมในการพัฒนาซอฟต์แวร์
ข้อกำหนดของฮาร์ดแวร์
- อุปกรณ์ Android ที่ใช้ Android 8.0 "Oreo" (API ระดับ 26) ขึ้นไป
- แว่น Cardboard
ข้อกำหนดของซอฟต์แวร์
- Android Studio เวอร์ชัน 2022.1.1 "Electric Eel" ขึ้นไป
- Android SDK 13.0 "Tiramisu" (API ระดับ 33) ขึ้นไป
เฟรมเวิร์ก Android NDK เวอร์ชันล่าสุด
หากต้องการตรวจสอบหรืออัปเดต SDK ที่ติดตั้งไว้ ให้ไปที่ค่ากำหนด > ลักษณะที่ปรากฏและลักษณะการทำงาน
การตั้งค่าระบบ > Android SDK ใน Android Studio
ดาวน์โหลดและสร้างแอปเดโม
Cardboard SDK สร้างโดยใช้ Vulkan ที่คอมไพล์ไว้ล่วงหน้า สำหรับตัวปรับแสงเงาแต่ละตัว ดูขั้นตอนในการสร้างไฟล์ส่วนหัวได้ตั้งแต่ต้น ที่นี่
เรียกใช้คำสั่งต่อไปนี้เพื่อโคลน SDK ของ Cardboard และการสาธิต HelloCardboard แอปจาก GitHub:
git clone https://github.com/googlevr/cardboard.git
ใน Android Studio ให้เลือกเปิดโปรเจ็กต์ Android Studio ที่มีอยู่ จากนั้นเลือก ไดเรกทอรีที่มีการโคลนแอป Cardboard SDK และแอปเดโม HelloCardboard เข้าไป
โค้ดจะปรากฏในหน้าต่างโปรเจ็กต์ใน Android Studio
หากต้องการประกอบ Cardboard SDK ให้ดับเบิลคลิกตัวเลือกประกอบภายใน cardboard/:sdk/Tasks/build ในแท็บ Gradle (มุมมอง > หน้าต่างเครื่องมือ > Gradle)
เรียกใช้แอปเดโม HelloCardboard ในโทรศัพท์โดยเลือกเรียกใช้ > Run... และ เลือกเป้าหมาย
hellocardboard-android
สแกนคิวอาร์โค้ด
หากต้องการบันทึกพารามิเตอร์อุปกรณ์ ให้สแกนคิวอาร์โค้ดบนแว่น Cardboard ดังนี้
หากผู้ใช้กด "ข้าม" และไม่มีพารามิเตอร์ที่บันทึกไว้ก่อนหน้านี้ Cardboard จะบันทึก พารามิเตอร์ Google Cardboard v1 (เปิดตัวที่ Google I/O 2014)
ลองใช้
ใน HelloCardboard คุณจะค้นหาและเก็บภาพทรงกลมทรงกลมในพื้นที่ 3 มิติ
วิธีค้นหาและรวบรวมทรงกลม
ขยับศีรษะไปในทิศทางใดก็ได้จนกว่าคุณจะเห็นรูปร่างแบบลอย
มองตรงไปที่ทรงกลม ซึ่งจะทำให้สีเปลี่ยนสี
กดปุ่มแว่น Cardboard เพื่อ "รวบรวม" ทรงกลม
กำหนดค่าอุปกรณ์
เมื่อผู้ใช้แตะไอคอนรูปเฟืองเพื่อเปลี่ยนแว่น Cardboard nativeSwitchViewer
เมธอด โทร nativeSwitchViewer
ครั้ง
CardboardQrCode_scanQrCodeAndSaveDeviceParams
ซึ่งจะเปิดหน้าต่างเพื่อสแกน
คิวอาร์โค้ดของผู้ชม ความผิดเพี้ยนของเลนส์และพารามิเตอร์อื่นๆ ของผู้ชมจะอัปเดตเพียงครั้งเดียว
สแกนคิวอาร์โค้ดแล้ว
// Called by JNI method
void HelloCardboardApp::SwitchViewer() {
CardboardQrCode_scanQrCodeAndSaveDeviceParams();
}
เปิดใช้โปรแกรมจำลอง x86 ของ Android Studio
หากต้องการสร้างโปรแกรมจำลอง x86 ของ Android Studio ให้นำบรรทัดต่อไปนี้ออกจาก
build.gradle
ไฟล์ใน SDK
และ ตัวอย่าง:
abiFilters 'armeabi-v7a', 'arm64-v8a'
การดำเนินการนี้จะเปิดใช้ ABI ทั้งหมด และจะเพิ่มขนาดของ ABI ที่สร้างขึ้นอย่างมีนัยสำคัญ
.aar
ไฟล์ ดู ABI ของ Android
เพื่อดูข้อมูลเพิ่มเติม
การติดตามการเคลื่อนไหวของศีรษะ
สร้างเครื่องติดตามการเคลื่อนไหวศีรษะ
อุปกรณ์ติดตามศีรษะได้รับการสร้างขึ้นเมื่อสร้าง HelloCardboardApp
:
HelloCardboardApp::HelloCardboardApp(JavaVM* vm, jobject obj, jobject asset_mgr_obj) {
Cardboard_initializeAndroid(vm, obj); // Must be called in constructor
head_tracker_ = CardboardHeadTracker_create();
}
เมื่อสร้างอินสแตนซ์ของ VrActivity
ระบบจะสร้างอินสแตนซ์ของคลาส HelloCardboardApp
โดยเรียกใช้เมธอด nativeOnCreate
:
public void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
nativeApp = nativeOnCreate(getAssets());
//...
}
หยุดเครื่องติดตามการเคลื่อนไหวศีรษะชั่วคราวและเล่นต่อ
หากต้องการหยุดชั่วคราว เล่นต่อ และทำลายอุปกรณ์ติดตามศีรษะ
CardboardHeadTracker_pause(head_tracker_)
CardboardHeadTracker_resume(head_tracker_)
และ CardboardHeadTracker_destroy(head_tracker_)
จะต้องถูกเรียกตามลำดับ ใน
"HelloCardboard" ซึ่งเราเรียกใน nativeOnPause
, nativeOnResume
และ
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;
}
การบิดเบี้ยวของเลนส์
ทุกครั้งที่ Cardboard สแกนคิวอาร์โค้ดใหม่ โค้ดต่อไปนี้จะอ่านพารามิเตอร์ที่บันทึกไว้ และใช้เพื่อสร้างวัตถุบิดเบี้ยวของเลนส์ ซึ่งจะทำให้เกิดการบิดเบี้ยวของเลนส์ที่เหมาะสม กับเนื้อหาที่แสดงผล
CardboardQrCode_getSavedDeviceParams(&buffer, &size);
CardboardLensDistortion_destroy(lens_distortion_);
lens_distortion_ = CardboardLensDistortion_create(
buffer, size, screen_width_, screen_height_);
CardboardQrCode_destroy(buffer);
การแสดงผล
การแสดงผลเนื้อหาใน Cardboard เกี่ยวข้องกับสิ่งต่อไปนี้
- การสร้างพื้นผิว
- กำลังรับเมทริกซ์มุมมองและเส้นโครงสำหรับตาซ้ายและขวา
- การสร้างตัวแสดงผลและการตั้งค่าตาข่ายการบิดเบี้ยว
- การแสดงผลแต่ละเฟรม
สร้างพื้นผิว
เนื้อหาทั้งหมดจะถูกวาดลงบนพื้นผิวซึ่งแบ่งออกเป็นส่วนต่างๆ สำหรับตาซ้ายและขวา
ส่วนเหล่านี้จะเริ่มต้นใน _leftEyeTexture
และ _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");
}
ระบบจะส่งพื้นผิวเหล่านี้ในรูปแบบพารามิเตอร์ไปยัง CardboardDistortionRenderer_renderEyeToDisplay
รับมุมมองและเมทริกซ์การฉายภาพสำหรับตาซ้ายและขวา
ขั้นแรก ให้เรียกเมทริกซ์ตาสำหรับตาซ้ายและขวาดังนี้
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]);
ถัดไป ให้ใช้ตาข่ายตรวจจับการบิดเบี้ยวของดวงตาแต่ละข้าง แล้วส่งต่อให้กับโหมดแสดงภาพการบิดเบี้ยว
CardboardLensDistortion_getDistortionMesh(lens_distortion_, kLeft, &left_mesh);
CardboardLensDistortion_getDistortionMesh(lens_distortion_, kRight, &right_mesh);
สร้างโหมดแสดงภาพและตั้งค่า Mesh ของการบิดเบี้ยวที่ถูกต้อง
โหมดแสดงภาพต้องเริ่มต้นเพียงครั้งเดียว เมื่อสร้างโหมดแสดงภาพแล้ว ให้ตั้งค่า
ตาข่ายที่บิดเบี้ยวของตาซ้ายและขวาตามค่า Mesh ที่แสดงผลจาก
CardboardLensDistortion_getDistortionMesh
distortion_renderer_ = CardboardOpenGlEs2DistortionRenderer_create();
CardboardDistortionRenderer_setMesh(distortion_renderer_, &left_mesh, kLeft);
CardboardDistortionRenderer_setMesh(distortion_renderer_, &right_mesh, kRight);
การแสดงผลเนื้อหา
สำหรับแต่ละเฟรม ให้ดึงข้อมูลการวางแนวศีรษะปัจจุบันจาก CardboardHeadTracker_getPose
:
CardboardHeadTracker_getPose(head_tracker_, monotonic_time_nano, &out_position[0], &out_orientation[0]);
ใช้ทิศทางศีรษะปัจจุบันกับมุมมองและเมทริกซ์การฉายภาพเพื่อสร้างมุมมอง เมทริกซ์การฉายภาพสำหรับดวงตาแต่ละข้างและแสดงผลเนื้อหาไปยังหน้าจอ
// 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();
}
ใช้ CardboardDistortionRenderer_renderEyeToDisplay
เพื่อเพิ่มความบิดเบี้ยว
การแก้ไขเนื้อหา และแสดงผลเนื้อหาไปยังหน้าจอ
// Render
CardboardDistortionRenderer_renderEyeToDisplay(
distortion_renderer_, /* target_display = */ 0, /* x = */ 0, /* y = */ 0,
screen_width_, screen_height_, &left_eye_texture_description_,
&right_eye_texture_description_);