GearVR+ARCore开发问题:无需绘图仅获取GLContext的实现咨询
解决GearVR中调用ARCore依赖GLContext功能的方案
我之前在做类似的GearVR + ARCore集成时也遇到过这个问题,核心矛盾就是GearVR的GVRAc框架会完全接管渲染上下文,直接加隐藏的GLSurfaceView确实行不通——毕竟setMain()方法绑定的是GearVR专属的布局和渲染流程,外来的View很容易和它的上下文冲突。这里有两个经过验证的可行方案,你可以根据需求选择:
方案一:复用GearVR的主GLContext(最推荐)
其实GearVR本身就是基于OpenGL ES运行的,它的主渲染循环已经持有一个有效的GLContext,我们完全可以把这个上下文直接给ARCore用,不需要额外创建任何View:
- 在你的
GVRAc子类里,重写渲染相关的回调方法(比如onDrawEye或者onDrawFrame,具体取决于你用的GearVR SDK版本) - 在回调方法内部,当前线程就是GL线程,上下文处于活跃状态,直接初始化ARCore的
Session:// 初始化ARCore Session,自动复用当前活跃的GLContext Session arSession = new Session(this); Config arConfig = arSession.getConfig(); if (arSession.isSupported(arConfig)) { arSession.configure(arConfig); // 在这里调用所有需要GLContext的ARCore API,比如追踪更新、平面检测等 } - 注意:ARCore的所有核心操作都必须在GL线程执行,而GearVR的渲染回调本身就在GL线程,完美匹配需求,不需要额外处理线程切换,也不会干扰GearVR本身的渲染。
方案二:创建离屏GL上下文(PBuffer Surface)
如果复用主上下文会有状态冲突(比如ARCore的GL操作影响GearVR的渲染状态),可以创建一个离屏的PBuffer Surface来单独给ARCore提供GLContext,这种方式完全不需要创建可见的View:
- 用
EGL14API手动搭建离屏上下文环境,代码示例如下:// 初始化EGL显示 EGLDisplay display = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY); EGL14.eglInitialize(display, null, 0, null, 0); // 配置EGL属性,匹配ARCore需要的OpenGL ES 3.0+版本 int[] configAttribs = { EGL14.EGL_RED_SIZE, 8, EGL14.EGL_GREEN_SIZE, 8, EGL14.EGL_BLUE_SIZE, 8, EGL14.EGL_DEPTH_SIZE, 16, EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES3_BIT_KHR, EGL14.EGL_NONE }; EGLConfig[] configs = new EGLConfig[1]; int[] numConfigs = new int[1]; EGL14.eglChooseConfig(display, configAttribs, 0, configs, 0, configs.length, numConfigs, 0); // 创建1x1的PBuffer离屏Surface(足够ARCore使用,不需要大尺寸) int[] surfaceAttribs = { EGL14.EGL_WIDTH, 1, EGL14.EGL_HEIGHT, 1, EGL14.EGL_NONE }; EGLSurface pbufferSurface = EGL14.eglCreatePbufferSurface(display, configs[0], surfaceAttribs, 0); // 创建独立的GLContext int[] contextAttribs = { EGL14.EGL_CONTEXT_CLIENT_VERSION, 3, EGL14.EGL_NONE }; EGLContext arContext = EGL14.eglCreateContext(display, configs[0], EGL14.EGL_NO_CONTEXT, contextAttribs, 0); // 绑定上下文到当前线程,之后就可以调用ARCore API了 EGL14.eglMakeCurrent(display, pbufferSurface, pbufferSurface, arContext); // 初始化ARCore Session Session arSession = new Session(this); // ... 执行ARCore的追踪、检测等操作 - 要注意把这个逻辑放在单独的后台线程里,避免阻塞GearVR的主渲染线程;另外在应用退出时,一定要正确销毁EGL的display、surface和context,防止内存泄漏。
为什么隐藏GLSurfaceView的方案行不通?
GearVR的GVRAc.setMain()方法会完全接管整个窗口的渲染管线,它内部维护了自己的Surface和GLContext,你添加的GLSurfaceView会和这个主上下文抢占资源,要么GLSurfaceView无法获取有效上下文,要么GearVR的渲染被打断,本质上是和GearVR的框架设计冲突的,所以这种方案不建议尝试。
内容的提问来源于stack exchange,提问作者JongWon Jung
相关产品推荐
相关产品推荐

