GL_OUT_OF_MEMORY 使用A-frame显示立体图像
GL_OUT_OF_MEMORY using A-frame to display stereoscopic images
我创建了一个概念验证 SPA (source code / demo) which loads stereoscopic images from a web server and renders them in stereoscopic 3D using the aframe-stereo-component for A-frame。
在 Oculus 浏览器和 Firefox Reality 中的 Quest 2 上对此进行测试,效果很好:当通过 WebXR 在沉浸式 VR 模式下查看时,每个图像都显示为 3D。
但是,在滚动浏览一定数量的图像(通常为 8 到 12 张)后,幻灯片停止工作。
在 Firefox Reality 中,这表现为应用程序冻结并变得无响应。
在Oculus 浏览器中,显示了图片描述,但图片区域仍然是黑色。
使用 adb 将 Quest 2 连接到 PC 并使用 Chrome DevTools 检查页面,发生这种情况时我可以看到以下输出:
23:07:59.195 [.WebGL-0x55930300]GL ERROR :GL_OUT_OF_MEMORY : glTexImage2D:
23:07:59.195 [.WebGL-0x55930300]GL ERROR :GL_INVALID_OPERATION : glGenerateMipmap: Can not generate mips
23:07:59.195 [.WebGL-0x55930300]RENDER WARNING: texture bound to texture unit 0 is not renderable. It might be non-power-of-2 or have incompatible texture filtering (maybe)?
23:08:03.340 [.WebGL-0x55930300]GL ERROR :GL_OUT_OF_MEMORY : glTexImage2D:
23:08:03.340 [.WebGL-0x55930300]GL ERROR :GL_INVALID_OPERATION : glGenerateMipmap: Can not generate mips
23:08:03.340 [.WebGL-0x55930300]GL ERROR :GL_OUT_OF_MEMORY : glTexImage2D:
23:08:03.340 [.WebGL-0x55930300]GL ERROR :GL_INVALID_OPERATION : glGenerateMipmap: Can not generate mips
23:08:03.499 WebGL: too many errors, no more errors will be reported to the console for this context.
不可否认,正在加载的图像是大型 JPS 文件(2 到 3Mb)并且每张图像都渲染了两次:每只眼睛一次。
但是,<img>
元素用于通过将图像内容添加到 DOM 来加载图像内容,并且当请求下一张图像时,它会被删除并清空以使图像内容无效,因此理论上只有一张图像应该在任何时候加载。
因此,我假设某处一定存在内存泄漏,导致在加载大量图像后内存被填满,但我不确定它在哪里泄漏。
我无法使用 Chrome/Firefox 在 PC 上重现该问题,但这可能是因为它的内存比 Quest 2 多。
相关source code摘录:
<a-scene id="scene" vr-mode-ui="enabled: false" >
<a-assets id="assets"></a-assets>
<a-plane id="left-image"
material="repeat:0.5 1"
scale="2 1 1"
position="0 0 -1"
stereo="eye:left"
>
</a-plane>
<a-plane id="right-image"
material="repeat:0.5 1; offset: 0.5 0"
scale="2 1 1"
position="0 0 -1"
stereo="eye: right"
></a-plane>
</a-scene>
const stereoImageId = 'fullsize-image'
const _stereoImage = '#'+stereoImageId;
const leye = $('#left-image')[0];
const reye = $('#right-image')[0];
const $assets = $('#assets');
const removeStereoImage = function(){
let $stereoImage = $(_stereoImage);
if($stereoImage.length){
let stereoImage = $stereoImage[0];
stereoImage.onload = stereoImage.onerror = null;
$stereoImage.attr('src', '').remove();
$stereoImage = stereoImage = null;
}
};
const unloadStereoImage = function(){
removeStereoImage();
leye.setAttribute("material", "src", '');
reye.setAttribute("material", "src", '');
setStereoImageVisibility(false);
};
const setStereoImageVisibility = function(visible){
leye.setAttribute("visible", visible)
reye.setAttribute("visible", visible)
};
const showImg = function(url, description){
function onImgLoaded(){
leye.setAttribute("material", "src", _stereoImage);
reye.setAttribute("material", "src", _stereoImage);
setStereoImageVisibility(true);
}
unloadStereoImage();
let stereoImage = document.createElement('img');
stereoImage.setAttribute('id', stereoImageId);
stereoImage.setAttribute('crossorigin', "anonymous");
stereoImage.setAttribute('src', url);
stereoImage.onload = onImgLoaded;
$(stereoImage).appendTo($assets);
};
我也在源代码库中raised this as an issue
资产管理系统 (a-assets
) 旨在帮助处理 preloading 资产,而不是在运行时将它们扔进扔出。
从资产中删除 <img>
元素不会处理纹理(缓存在 material system 中)。
您可以访问和清除缓存,但我会尝试管理图像 'manually',
- 一样通过
new THREE.Texture(src)
加载图像
应用material和
element.getObject3D("mesh").material.map = texture;
material.needsUpdate = true;
- 删除旧纹理
以为纹理是 too big,但我猜每个都会崩溃。
我创建了一个概念验证 SPA (source code / demo) which loads stereoscopic images from a web server and renders them in stereoscopic 3D using the aframe-stereo-component for A-frame。
在 Oculus 浏览器和 Firefox Reality 中的 Quest 2 上对此进行测试,效果很好:当通过 WebXR 在沉浸式 VR 模式下查看时,每个图像都显示为 3D。
但是,在滚动浏览一定数量的图像(通常为 8 到 12 张)后,幻灯片停止工作。 在 Firefox Reality 中,这表现为应用程序冻结并变得无响应。
在Oculus 浏览器中,显示了图片描述,但图片区域仍然是黑色。 使用 adb 将 Quest 2 连接到 PC 并使用 Chrome DevTools 检查页面,发生这种情况时我可以看到以下输出:
23:07:59.195 [.WebGL-0x55930300]GL ERROR :GL_OUT_OF_MEMORY : glTexImage2D:
23:07:59.195 [.WebGL-0x55930300]GL ERROR :GL_INVALID_OPERATION : glGenerateMipmap: Can not generate mips
23:07:59.195 [.WebGL-0x55930300]RENDER WARNING: texture bound to texture unit 0 is not renderable. It might be non-power-of-2 or have incompatible texture filtering (maybe)?
23:08:03.340 [.WebGL-0x55930300]GL ERROR :GL_OUT_OF_MEMORY : glTexImage2D:
23:08:03.340 [.WebGL-0x55930300]GL ERROR :GL_INVALID_OPERATION : glGenerateMipmap: Can not generate mips
23:08:03.340 [.WebGL-0x55930300]GL ERROR :GL_OUT_OF_MEMORY : glTexImage2D:
23:08:03.340 [.WebGL-0x55930300]GL ERROR :GL_INVALID_OPERATION : glGenerateMipmap: Can not generate mips
23:08:03.499 WebGL: too many errors, no more errors will be reported to the console for this context.
不可否认,正在加载的图像是大型 JPS 文件(2 到 3Mb)并且每张图像都渲染了两次:每只眼睛一次。
但是,<img>
元素用于通过将图像内容添加到 DOM 来加载图像内容,并且当请求下一张图像时,它会被删除并清空以使图像内容无效,因此理论上只有一张图像应该在任何时候加载。
因此,我假设某处一定存在内存泄漏,导致在加载大量图像后内存被填满,但我不确定它在哪里泄漏。
我无法使用 Chrome/Firefox 在 PC 上重现该问题,但这可能是因为它的内存比 Quest 2 多。
相关source code摘录:
<a-scene id="scene" vr-mode-ui="enabled: false" >
<a-assets id="assets"></a-assets>
<a-plane id="left-image"
material="repeat:0.5 1"
scale="2 1 1"
position="0 0 -1"
stereo="eye:left"
>
</a-plane>
<a-plane id="right-image"
material="repeat:0.5 1; offset: 0.5 0"
scale="2 1 1"
position="0 0 -1"
stereo="eye: right"
></a-plane>
</a-scene>
const stereoImageId = 'fullsize-image'
const _stereoImage = '#'+stereoImageId;
const leye = $('#left-image')[0];
const reye = $('#right-image')[0];
const $assets = $('#assets');
const removeStereoImage = function(){
let $stereoImage = $(_stereoImage);
if($stereoImage.length){
let stereoImage = $stereoImage[0];
stereoImage.onload = stereoImage.onerror = null;
$stereoImage.attr('src', '').remove();
$stereoImage = stereoImage = null;
}
};
const unloadStereoImage = function(){
removeStereoImage();
leye.setAttribute("material", "src", '');
reye.setAttribute("material", "src", '');
setStereoImageVisibility(false);
};
const setStereoImageVisibility = function(visible){
leye.setAttribute("visible", visible)
reye.setAttribute("visible", visible)
};
const showImg = function(url, description){
function onImgLoaded(){
leye.setAttribute("material", "src", _stereoImage);
reye.setAttribute("material", "src", _stereoImage);
setStereoImageVisibility(true);
}
unloadStereoImage();
let stereoImage = document.createElement('img');
stereoImage.setAttribute('id', stereoImageId);
stereoImage.setAttribute('crossorigin', "anonymous");
stereoImage.setAttribute('src', url);
stereoImage.onload = onImgLoaded;
$(stereoImage).appendTo($assets);
};
我也在源代码库中raised this as an issue
资产管理系统 (a-assets
) 旨在帮助处理 preloading 资产,而不是在运行时将它们扔进扔出。
从资产中删除 <img>
元素不会处理纹理(缓存在 material system 中)。
您可以访问和清除缓存,但我会尝试管理图像 'manually',
- 一样通过
new THREE.Texture(src)
加载图像 应用material和
element.getObject3D("mesh").material.map = texture; material.needsUpdate = true;
- 删除旧纹理
以为纹理是 too big,但我猜每个都会崩溃。