LibGDX升级GL30后Box2DLights RayHandler实例化报像素解包缓冲对象错误
适配新版LibGDX的Box2DLights RayHandler初始化异常解决方案
核心报错原因
你遇到的两个连续报错本质是版本兼容问题,和GL30、GL20的上下文切换没有直接绑定关系:
- 旧版Box2DLights的
RayHandler在初始化时,会通过LightMap类创建用于光照计算的帧缓冲(FrameBuffer),这套逻辑适配的是LibGDX 1.9.10及更早版本的FrameBuffer实现 - 新版LibGDX从1.10版本开始,修改了
FrameBuffer内部创建纹理的逻辑:默认关联像素解包缓冲对象(PBO)优化纹理上传性能,当PBO没有正确绑定到合法缓冲对象时,就会直接抛出Cannot use offsets when Pixel Unpack Buffer Object is disabled的OpenGL异常 - 你之前尝试的
Gdx.gl.glBindBuffer(GL30.GL_PIXEL_UNPACK_BUFFER, 1)操作完全错误:你绑定的ID=1的缓冲对象根本不存在,OpenGL会尝试从这块无效的显存区域读取纹理数据,直接导致帧缓冲附件校验失败,才出现了Frame buffer couldn't be constructed: incomplete attachment的新报错
实操修复方案
- 最优修复:升级Box2DLights到适配新版LibGDX的版本
- 2019年之前发布的旧版Box2DLights没有适配LibGDX后续的FrameBuffer实现,是触发异常的根源。直接替换为适配LibGDX 1.10.x、1.11.x、1.12.x版本的维护版Box2DLights,不需要修改你的业务代码,
RayHandler的初始化逻辑会自动适配GL3.0上下文的帧缓冲创建流程。 - 如果你是直接把旧项目的Box2DLights源码拷贝到新项目里,不要直接沿用旧源码的
LightMap类实现,要同步更新和新版LibGDX匹配的FrameBuffer创建逻辑,避免和底层API不兼容。
- 2019年之前发布的旧版Box2DLights没有适配LibGDX后续的FrameBuffer实现,是触发异常的根源。直接替换为适配LibGDX 1.10.x、1.11.x、1.12.x版本的维护版Box2DLights,不需要修改你的业务代码,
- 临时兼容方案(无法升级Box2DLights版本时使用)
- 在你实例化
RayHandler的代码行之前,手动解绑所有绑定到GL_PIXEL_UNPACK_BUFFER目标的PBO,关闭新版LibGDX的PBO纹理上传逻辑,对应代码如下:// 在new RayHandler之前执行,必须传入0解绑PBO Gdx.gl.glBindBuffer(GL30.GL_PIXEL_UNPACK_BUFFER, 0); rays = new RayHandler(world, Game.V_WIDTH/LIGHT_PIXEL_SIZE, Game.V_HEIGHT/LIGHT_PIXEL_SIZE); - 额外校验两个传入的尺寸参数:确认
Game.V_WIDTH/LIGHT_PIXEL_SIZE和Game.V_HEIGHT/LIGHT_PIXEL_SIZE的计算结果是大于0的合法整数,不能出现0、负数或者小数的非合法纹理尺寸,否则也会直接触发帧缓冲构造失败。
- 在你实例化
- 常见避坑点
- 不要手动绑定非0的PBO ID,你之前尝试的绑定ID=1的操作会直接导致帧缓冲完整性检查失败,这类手动绑定操作必须由LibGDX内部的纹理上传逻辑完成,业务代码不要干预。
- 不需要为了兼容这个问题把项目全局的OpenGL上下文从默认GL3.0切回GL2.0,全局切换GL版本会导致其他依赖GL3.0特性的LibGDX功能(比如高性能 SpriteBatch、帧缓冲后期处理)出现异常,只需要在RayHandler初始化的节点临时解绑PBO即可。
内容的提问来源于stack exchange,提问作者Fire 'N Lightnin'
相关产品推荐
相关产品推荐

