我正在尝试在我的一个基于OpenGL的应用程序中使用Cardboard Android SDK来构建VR体验。
为此,我正在关注google的pie-noon项目。我正在尝试使用undistortTexture()
类的函数CardboardView
来应用最终失真。此函数将GLuint作为纹理ID,使用渲染到纹理技术进行渲染。
我已做了相应的一切,但由于某些原因,只出现黑屏。
以下是我的代码
帧缓冲区的初始化
GL_CALL(glGenTextures(1, &g_undistort_texture_id));
GL_CALL(glBindTexture(GL_TEXTURE_2D, g_undistort_texture_id));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr));
GL_CALL(glGenRenderbuffers(1, &g_undistort_renderbuffer_id));
GL_CALL(glBindRenderbuffer(GL_RENDERBUFFER, g_undistort_renderbuffer_id));
GL_CALL(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width,
height));
GL_CALL(glGenFramebuffers(1, &g_undistort_framebuffer_id));
GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, g_undistort_framebuffer_id));
GL_CALL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, g_undistort_texture_id, 0));
GL_CALL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
g_undistort_renderbuffer_id));
GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE){
EXAMPLE_LOG("GLDEBUG::: New Frame Buffer is Complete");
}else{
EXAMPLE_LOG("GLDEBUG::: New Frame Buffer is NOT Complete");
}
渲染和失真代码
// swap buffers
GL_CALL(eglSwapBuffers(m_displayService.GetDisplay(), m_displayService.GetSurface()));
// clear buffers
GLHelpers::ClearBuffers();
// bind your render to texture frame buffer
glBindFramebuffer(GL_FRAMEBUFFER, m_displayService.GetFrameBufferId());
// engine draw call
app->Draw(deltaSeconds);
// bind back default frame buffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// set viewport back to full screen from steroscopic viewport for VR
glViewport(0, 0, m_displayService.GetDisplayWidth()*2.f, m_displayService.GetDisplayHeight());
// jni call to "UndistortTexture()" function of MainActivity which contains CardboardView and calls cardboard view's undistortTexture()
JNIEnv* env = m_pNativeState->mainThreadEnv;
jobject activity = m_pNativeState->activity;
jclass fpl_class = env->GetObjectClass(activity);
jmethodID undistort = env->GetMethodID(fpl_class, "UndistortTexture", "(I)V");
env->CallVoidMethod(activity, undistort, (jint)m_displayService.GetTextureId());
env->DeleteLocalRef(fpl_class);
以下是JNI调用的Java函数
public void UndistortTexture(int textureId){
try {
m_cardboardView.undistortTexture(textureId);
} catch (Exception e) {
Log.e("backgroundThreadActivity", "exception", e);
}
}
创建Surfaceview后,我按照以下更新屏幕参数
public void SetHeadMountedDisplayResolution(int width, int height) {
try {
if (m_cardboardView == null)
return;
Display display = getWindowManager().getDefaultDisplay();
ScreenParams sp = new ScreenParams(display);
Phone.PhoneParams pp = new Phone.PhoneParams();
pp.setXPpi(width / sp.getWidthMeters() * METERS_PER_INCH);
pp.setYPpi(height / sp.getHeightMeters() * METERS_PER_INCH);
sp = ScreenParams.fromProto(display, pp);
sp.setWidth(width);
sp.setHeight(height);
m_cardboardView.updateScreenParams(sp);
} catch (Exception e) {
Log.e("backgroundThreadActivity", "exception", e);
}
}