一:前言
2017年11月14日,HTC Vive在北京新云南皇冠假日酒店召开2017 Vive开发者峰会(VDC 2017)。HTC Vive在会上发布了一款针对国内市场的VR一体机Vive Focus。
VR一体机Vive Focus优点:画面更加清晰,应用运行的也更加流畅;inside-out技术的运用也解决了陀螺仪追踪带来的延迟、画面抖动的问题;虽然骁龙835的性能还无法像桌面级处理器那样,带来Vive那样极致的VR体验,但更舒适的佩戴和无线的设计,也让用户可以在看VR视频或者玩轻度的VR游戏时,更加的自由、舒适。如下图
二:开发
1.前期准备
HTC vive 官方网站点击打开链接,开发者可以登录 下载官方sdk vive wave vr sdk,里面有demo,推荐使用unity开发,开发相对容易很多。但是本文用的是原生c++开发方式,底层使用开源引擎ogre.
2.开发中可以参照demo中的wvr_hellovr,实现方式也是底层c++ jni方式实现 本文将说一下核心的步骤。
(1)jni初始化中注册系统VR
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
//new Context(vm);
LOGI("register WVR main when library loading");
WVR_RegisterMain(main);
return JNI_VERSION_1_6;
}
int main(int argc, char *argv[]) {
LOGENTRY();
LOGI("HelloVR main, new MainApplication ");
MainApplication *app = new MainApplication();
LOGI("HelloVR main, start call app->initVR()");
if (!app->initVR()) {
LOGW("HelloVR main, initVR fail,start call app->shutdownVR()");
app->shutdownVR();
return 1;
}
if (!app->initGL()) {
LOGW("HelloVR main, initGL failed, start call app->shutdownVR()");
app->shutdownGL();
app->shutdownVR();
return 1;
}
while (1) {
if (app->handleInput())
break;
if (app->renderFrame()) {
LOGE("Unknown render error. Quit.");
break;
}
app->updateHMDMatrixPose();
}
app->shutdownGL();
app->shutdownVR();
return 0;
}
bool MainApplication::initVR() {
LOGENTRY();
LOGI("MainApplication::initVR()");
// Loading the WVR Runtime
WVR_InitError eError = WVR_InitError_None;
LOGI("initVR():start call WVR_Init");
eError = WVR_Init(WVR_AppType_VRContent);
LOGI("initVR():start call WVR_Init end");
if (eError != WVR_InitError_None) {
LOGE("Unable to init VR runtime: %s", WVR_GetInitErrorString(eError));
return false;
}
// Must initialize render runtime before all OpenGL code.
WVR_RenderInitParams_t param;
param = { WVR_GraphicsApiType_OpenGL, WVR_RenderConfig_Timewarp_Asynchronous };
WVR_RenderError pError = WVR_RenderInit(¶m);
if (pError != WVR_RenderError_None) {
LOGE("Present init failed - Error[%d]", pError);
}
return true;
}
可以看到在注册VR时候,会回调初始化VR的函数,同时接着会初始化Gl函数,由于项目不同,开发者可以自己定义gl,自己绘制自己的内容,但是要保证自己绘制opengl要在main线程里面,不同线程会导致后续纹理提交错误。
handleInput
主要是处理手柄交互事件的,用户可以根据不同的手柄inputid值,自定义不同的功能。
renderFrame
这个是核心的渲染封装,里面主要是
获取可用的纹理索引,创建纹理队列,取出对应左右眼纹理提交,提交正确后就可以在头盔中实时渲染出来。
mIndexLeft = WVR_GetAvailableTextureIndex(mLeftEyeQ);
mIndexRight = WVR_GetAvailableTextureIndex(mRightEyeQ);
WVR_TextureParams_t leftEyeTexture = WVR_GetTexture(mLeftEyeQ, mIndexLeft);
WVR_SubmitError e;
e = WVR_SubmitFrame(WVR_Eye_Left, &leftEyeTexture);
if (e != WVR_SubmitError_None) return true;
// Right eye
WVR_TextureParams_t rightEyeTexture = WVR_GetTexture(mRightEyeQ, mIndexRight);
e = WVR_SubmitFrame(WVR_Eye_Right, &rightEyeTexture);
实际开发中从ogre中实时取出当前创建的纹理然后实时提交。
app->updateHMDMatrixPose();
实时更新头盔位置,测试发现如果不掉用,app将无法正确显示。
三:3D效果展示 vysor投屏