更新
我误解了这个问题
这真的取决于驱动程序。问题是 OpenGL/OpenGL ES/WebGL 的纹理 API 真的很烂。 Sucks 是“具有意想不到的后果”的技术术语。
问题是驱动程序在您绘制之前无法真正完全上传数据,因为它不知道您要更改哪些内容。您可以按任意顺序和任意大小更改所有 mip 级别,然后将它们全部固定在两者之间,因此在您绘制之前,它不知道您将调用哪些其他函数来操作纹理。
假设您创建了一个 4x4 0 级 mip
gl.texImage2D(
gl.TEXTURE_2D,
0, // mip level
gl.RGBA,
4, // width
4, // height
...);
它应该分配什么内存? 4(宽度)* 4(高度)* 4(RGBA)?但是如果你打电话给gl.generateMipmap呢?现在它需要 4*4*4+2*2*4+1*1*4。好的,但是现在您在第 3 级分配了一个 8x8 mip。您打算然后分别用 64x64、32x32、16x16 替换第 0 到第 2 级,但您先执行第 3 级。在替换以上级别之前替换级别3应该怎么办?然后将级别 4 8x8、5 作为 4x4、6 作为 2x2 和 7 作为 1x1 添加。
如您所见,API 允许您按任意顺序更改 mip。事实上,我可以将级别 7 分配为 723x234,然后再修复它。该 API 旨在直到绘制时间才关心所有 mip 必须具有正确的大小,此时它们最终可以在 GPU 上分配内存并复制 mip。
你可以看到这个问题here的演示和测试。测试会乱序上传 mips,以验证 WebGL 实现是否正确失败,因为它们的大小不正确,并且一旦大小正确,就可以正确开始工作。
您可以看出这可能是一个糟糕的 API 设计。
他们添加了gl.texStorage2D 来修复它,但gl.texStorage2D 在 WebGL1 中不可用,仅在 WebGL2 中可用。 gl.texStorage2D 有新问题 :(
TLDR;当您调用 gl.texImage2D 时,纹理会上传到驱动程序,但驱动程序在绘制时间之前无法上传到 GPU。
可能的解决方案:使用gl.texSubImage2D,因为它不分配内存,因此驱动程序可能会更快上传。我怀疑大多数司机不会,因为你可以在绘图前使用gl.texSubImage2D。还是值得一试
我还要补充一点,gl.LUMIANCE 也可能是一个瓶颈。 IIRC DirectX 没有相应的格式,OpenGL 核心配置文件也没有。两者都支持仅 RED 格式,但 WebGL1 不支持。因此,必须通过扩展上传数据来模拟 LUMIANCE。
旧答案
很遗憾,除了通过texImage2D 和texSubImage2D 之外,无法将视频上传到WebGL
一些浏览器试图让这种情况发生得更快。我注意到您使用的是gl.LUMINANCE。您可以尝试使用gl.RGB 或gl.RGBA 看看事情是否会加快。浏览器可能只针对更常见的情况进行优化。另一方面,它们可能根本没有优化。
已经提出了两个允许在没有副本的情况下使用视频的扩展,但 AFAIK 没有像以往那样实现它们的浏览器。
WEBGL_video_texture
WEBGL_texture_source_iframe
这实际上是一个比听起来要困难得多的问题。
-
视频数据可以有多种格式。你提到了 YUV,但还有其他的。浏览器应该告诉应用程序格式还是浏览器应该转换为标准格式?
告诉的问题是很多开发者会弄错,然后用户会提供他们不支持的格式的视频
WEBGL_video_texture 扩展通过重写着色器转换为标准格式。你告诉它uniform samplerVideoWEBGL video 然后它知道它可以将你的color = texture2D(video, uv) 重写为color = convertFromVideoFormatToRGB(texture(video, uv))。这也意味着如果您播放不同格式的视频,他们必须即时重新编写着色器。
-
同步
将视频数据传输到 WebGL 听起来很棒,但现在您遇到的问题是,当您获取数据并将其渲染到屏幕时,您已经添加了几帧延迟,因此音频不再同步.
如何处理它超出了 WebGL 的范围,因为 WebGL 与音频没有任何关系,但它确实指出它并不像仅仅向 WebGL 提供数据那么简单。一旦你提供了数据,人们就会要求更多的 API 来获取音频和更多信息,这样他们就可以延迟一个或两个并保持同步。
TLDR;除了texImage2D 和texSubImage2D 之外,无法将视频上传到 WebGL