使用CORS从跨域图像加载WebGL纹理

在Firefox以及Chrome中,现在可以将跨域图像加载到WebGL纹理中,前提是它们已获得CORS的批准。

最显著的是,此功能允许进行令人印象深刻的3D映射应用程序,例如Google MapsGL诺基亚地图3D

发生了什么

今年早些时候,WebGL规范编辑草案针对安全问题进行了更新新增内容包括:

  1. 一个强制性条款,禁止在一般情况下将跨域元素用作WebGL纹理。
  2. 一个非规范性条款,专门允许具有CORS批准的跨域元素。为此,<img>元素的HTML规范进行了更新,添加了一个新的crossorigin属性

第一个在Firefox 5中实现,第二个现在在Firefox 8中实现。

如何使用此功能

两种CORS模式:“anonymous”(匿名)和“use-credentials”(使用凭据)。我们将重点关注“anonymous”,因为它是常见情况。Google Maps影像是一个使用匿名CORS提供图像的绝佳示例,例如:

http://khm0.googleapis.com/kh?v=95&x=0&y=0&z=0

为了将其作为WebGL纹理使用CORS加载,我们在其上设置crossOrigin属性

var earthImage = new Image();
earthImage.crossOrigin = "anonymous";

现在我们像往常一样加载它

    earthImage.onload = function() {
      // whatever you usually to do load WebGL textures
    };
    earthImage.src = "http://khm0.googleapis.com/kh?v=95&x=0&y=0&z=0";

就是这样!除了设置crossOrigin属性之外,我们无需执行任何其他操作。这是一个完整的自包含示例

HTTP头

如果我们研究此图像的HTTP头(例如,使用Firefox的Web控制台),我们会发现请求头包含

Origin: null

这是在img元素上设置此crossOrigin属性的效果。并且响应头包含

Access-Control-Allow-Origin: null

这是服务器支持此文件CORS的效果。

在HTML中执行此操作

当然,也可以在HTML中设置此属性,在这种情况下,它不区分大小写

<img src="http://khm0.googleapis.com/kh?v=95&x=0&y=0&z=0" crossorigin="anonymous">

并且由于“anonymous”是crossorigin属性的缺失值默认值和无效值默认值,因此我们可以为其传递任何无效值,甚至可以省略其值

<img src="http://khm0.googleapis.com/kh?v=95&x=0&y=0&z=0" crossorigin>

即将推出:Canvas 2D drawImage的CORS批准

如果首先将CORS批准的跨域图像绘制到2D
画布上,然后使用该画布作为WebGL纹理的源?这
个好消息是,这将在Firefox 9中起作用,Firefox 9即将进入Beta
通道。此修复意味着像这样的演示将在Firefox 9中运行得非常
好。

关于Benoit Jacob

我是Mozilla Corp.的一名软件工程师,从事Gecko的工作,特别是图形和WebGL部分。我在Mozilla的多伦多办事处工作。

更多Benoit Jacob的文章……


6条评论

  1. Henri Astre

    在一个非常特殊的上下文中,我发现了一种解决方法,可以绕过sop限制:http://www.visual-experiments.com/2011/10/03/how-to-bypass-webgl-sop-restriction/

    您对此有何看法?

    2011年11月8日 14:34

  2. Benoit Jacob

    @Henri:我认为这很聪明!不过,希望我们能够设法让内容提供商支持CORS,这样将来就不需要这样做了。

    2011年11月8日 19:43

  3. Ben Adams

    这是个好消息!干得好!

    2011年11月10日 07:51

  4. Bill

    有没有办法禁用CORS检查以进行测试?如果您的实际应用程序和数据通常是从myhost.com提供的,但您想使用在localhost上运行的服务器在本地调试应用程序,那么能够暂时关闭安全检查非常方便。Chrome在启动时使用--disable-web-security标志执行此操作。

    2011年12月15日 18:20

    1. Benoit Jacob

      我不知道Firefox中是否有此功能。对于本地URI,有security.fileuri.strict_origin_policy=false,但我不了解远程URI。我认为值得提交一个错误(如果您这样做,请抄送我,:bjacob)

      2011年12月15日 21:01

  5. Henri Astre

    @Bill:对于本地调试,我使用一个使用curl扩展的php代理页面。我还更新并发布了绕过sop限制的解决方法的源代码(仅适用于chrome/firefox(?)扩展)。我的新解决方法比以前的解决方法快得多,以前的解决方法是在js中进行jpeg解码:http://www.visual-experiments.com/2011/12/05/how-to-bypass-webgl-sop-restriction-v2/

    2011年12月17日 15:55

本文评论已关闭。