XML3D:大纹理的高效显示和改变

XML3D: Efficient display & change of large textures

我正在使用 XML3D 和球体模型来显示 360 度全景照片。 问题是我需要经常更改大纹理。

如果您只是在两个或三个纹理之间切换,那么会有更快的选择,但是对于这么多纹理,您唯一实用的选择是通过更改图像标签一个接一个地加载它们:

<texture name="diffuseTexture">
   <img id="photo" src="images/photo1.jpg"/>
</texture>

document.querySelector("#photo").src = "images/photo2.jpg";

如果您使用大纹理 (4096x2048) 对此进行分析,您会发现调用 gl.texImage2D 花费了大量时间,图像数据在此处被解码、转换并发送到 GPU。即使在台式机上,这也会导致卡顿,在移动设备上情况会变得更糟。

减小纹理的大小会大大加快处理速度。例如,将它们从 4096x2048 降低到 2048x1024 会使我的桌面上 gl.texImage2D 花费的时间从 ~53% 降低到 ~13%。

更低级别的 WebGL 库可能会在此处为您提供更多选项(例如在将图像提供给 texImage2D 之前将图像手动转换为 Uint8Arrays),但 XML3D 在设计时并未真正考虑到这一点。只要你使用大纹理,无论你做什么,特别是在移动设备上,你都会遇到减速。

如果您可以将照片放入视频中,效果会更好,因为在这种情况下解码和转换是在 GPU 上完成的。当然,这也有其缺点。

可以在着色器中使用统一变量非常简单地将一个纹理淡入另一个纹理:

uniform float uFade;
...
vec4 color1 = texture2D(texture1, texcoords);
vec4 color2 = texture2D(texture2, texcoords);
gl_FragColor = mix(color1, color2, uFade);

模糊涉及几个步骤。首先,您需要将上述混合渲染到屏幕外的 FrameBuffer 中。它成为水平模糊着色器的输入纹理,它的输出被提供给垂直模糊着色器,最后它的输出在场景渲染过程中用作天空对象的纹理。前三个步骤应渲染到全屏四边形上。

可以 在 XML3D 中使用 RenderInterface 和您自己的 RenderPasses 完成,但是在我看来,要获得与简单的褪色。