我正在使用 XML3D 和球体模型来显示 360 度照片。问题是我需要经常更改大纹理。
- 使用 XML3D 或 webgl 渲染 360 度照片的最佳方式是什么?
- 如何优化纹理切换?拥有一组较小的纹理会更好吗?是否有任何一套渲染 360 度图像的“良好做法”?
在两个 360 “天空”纹理之间实现模糊效果的最佳方法是什么?
我正在使用 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 库可能会在此处为您提供更多选择(例如在将图像转换为 Uint8Arrays 后再将它们提供给 texImage2D),但 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 来完成,但是 IMO 要想获得与简单淡入淡出没有太大不同的效果,会遇到很多麻烦。