最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Webgl Cross Origin Images don't work - Stack Overflow

programmeradmin1浏览0评论

I've got some problem with cross-origin image and I hope you can help.

Here the beahviour. I've got 2 domains, in example: - domain1 - domain2

On domain1 I put many html5 games. This domain is only a repository of games.

Domain2 is the real website (wordpress website) where users can play games hosted on domain1. To doing this I made a curl request for every game.

In domain1 nginx configuration file I put these lines of code for enabling Cross Origin Resource Sharing:


    location ~* \.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|json|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf|swf|mp3|xml|woff2)$ {
        add_header "Access-Control-Allow-Origin" "*";
        access_log off;
        log_not_found off;
        expires max;
    }

This resolved some issues for many games but some games are still not working and I get this js error:


    Uncaught DOMException: Failed to execute 'texImage2D' on 'WebGLRenderingContext': The cross-origin image at .png may not be loaded.
        at GLWrap_.loadTexture (.js:2618:16)
        at pluginProto.Type.typeProto.loadTextures (.js:18070:46)
        at pluginProto.Instance.instanceProto.onCreate (.js:18146:13)
        at Runtime.createInstanceFromInit (.js:4806:8)
        at Layer.createInitialInstances (.js:7541:25)
        at Layout.startRunning (.js:6715:10)
        at Runtime.go_loading_finished (.js:4067:36)
        at Runtime.go (.js:3966:9)
        at .js:4025:60

I made some research online and I found articles like these .html Drawing images to canvas with img.crossOrigin = "Anonymous" doesn't work

but they are not very helpful.

I wouldn't like to modify original game files. I'm looking for a server side solution if it exists. If not, have you got some idea for resolve my problem?

Is there some error in my configuration? Am I missing something?

Thank you for the help.

Valerio

I've got some problem with cross-origin image and I hope you can help.

Here the beahviour. I've got 2 domains, in example: - domain1. - domain2.

On domain1 I put many html5 games. This domain is only a repository of games.

Domain2 is the real website (wordpress website) where users can play games hosted on domain1. To doing this I made a curl request for every game.

In domain1 nginx configuration file I put these lines of code for enabling Cross Origin Resource Sharing:


    location ~* \.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|json|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf|swf|mp3|xml|woff2)$ {
        add_header "Access-Control-Allow-Origin" "*";
        access_log off;
        log_not_found off;
        expires max;
    }

This resolved some issues for many games but some games are still not working and I get this js error:


    Uncaught DOMException: Failed to execute 'texImage2D' on 'WebGLRenderingContext': The cross-origin image at http://domain1./html5-games/action/candy-match/images/loadingbarbackground-sheet0.png may not be loaded.
        at GLWrap_.loadTexture (http://domain1./html5-games/action/candy-match/c2runtime.js:2618:16)
        at pluginProto.Type.typeProto.loadTextures (http://domain1./html5-games/action/candy-match/c2runtime.js:18070:46)
        at pluginProto.Instance.instanceProto.onCreate (http://domain1./html5-games/action/candy-match/c2runtime.js:18146:13)
        at Runtime.createInstanceFromInit (http://domain1./html5-games/action/candy-match/c2runtime.js:4806:8)
        at Layer.createInitialInstances (http://domain1./html5-games/action/candy-match/c2runtime.js:7541:25)
        at Layout.startRunning (http://domain1./html5-games/action/candy-match/c2runtime.js:6715:10)
        at Runtime.go_loading_finished (http://domain1./html5-games/action/candy-match/c2runtime.js:4067:36)
        at Runtime.go (http://domain1./html5-games/action/candy-match/c2runtime.js:3966:9)
        at http://domain1./html5-games/action/candy-match/c2runtime.js:4025:60

I made some research online and I found articles like these https://webglfundamentals/webgl/lessons/webgl-cors-permission.html Drawing images to canvas with img.crossOrigin = "Anonymous" doesn't work

but they are not very helpful.

I wouldn't like to modify original game files. I'm looking for a server side solution if it exists. If not, have you got some idea for resolve my problem?

Is there some error in my configuration? Am I missing something?

Thank you for the help.

Valerio

Share Improve this question asked Sep 26, 2017 at 9:14 Valerio MontiValerio Monti 431 silver badge3 bronze badges 6
  • Have you checked via your browser dev tools, whether your server for domain1 actually returns the correct headers? – C3roe Commented Sep 26, 2017 at 9:28
  • Hi @CBroe apparently headers seems ok.HTTP/1.1 200 OK Server: nginx/1.6.2 Date: Tue, 26 Sep 2017 09:33:11 GMT Content-Type: text/html Content-Length: 4431 Last-Modified: Tue, 26 Sep 2017 08:00:45 GMT Connection: keep-alive ETag: "59ca092d-114f" Accept-Ranges: bytes – Valerio Monti Commented Sep 26, 2017 at 9:36
  • I meant for the images ... – C3roe Commented Sep 26, 2017 at 9:38
  • Uh sorry @CBroe , here headers i get for the image imgur./a/huxPq – Valerio Monti Commented Sep 26, 2017 at 10:07
  • 1 Try setting the access-control header to the actual domain instead of wildcard, also maybe try another browser for a more detailed error message. – LJᛃ Commented Sep 26, 2017 at 23:09
 |  Show 1 more ment

2 Answers 2

Reset to default 6

The games have to request cross origin images. Simply returning the correct headers is not enough. If the games themselves don't request cross origin images by setting the crossOrigin attribute then the browser will not allow the images to be used even if they have the correct headers.

Here's an example

const gl = document.createElement("canvas").getContext("webgl");
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);

loadImage('https://i.imgur./ZKMnXce.png', false);
loadImage('https://i.imgur./u6VI8xz.jpg', true);

function loadImage(url, crossOrigin) {
  const img = new Image();
  img.onload = () => { upload(img); };
  if (crossOrigin) {
    img.crossOrigin = '';
  }
  img.src = url;
}

function upload(img) {
  // trap for cors error
  try {
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
    log(img.src, "uploaded image");
  } catch (e) {
    log(img.src, e);
  }
}

function log(...args) {
  const elem = document.createElement("pre");
  elem.textContent = [...args].join(' ');
  document.body.appendChild(elem);
}
pre { margin: 0; }

And here you can see even those the first image returned the CORS headers it was not allowed to be used because crossOrigin was not set

The second image has the same headers but it works because we set the crossOrigin attribute

Note that you might be able to include a script like this before the game scripts to kind of hack in CORS support.

(function() {

function isSameOrigin(url) {
  return (new URL(url, window.location.href)).origin === window.location.origin;
}

function needsCORS(url) {
  // not sure all the URLs that should be checked for
  return !isSameOrigin(url) && !url.startsWith("blob:") && !url.startsWith("data:");
}

const srcSetFn = Object.getOwnPropertyDescriptor(HTMLImageElement.prototype, 'src').set; 

Object.defineProperty(HTMLImageElement.prototype, 'src', {
  enumerable: true,
  set: function(url) {
     if (needsCORS(url)) {
       // Set if not already set
       if (this.crossOrigin !== undefined) {
         this.crossOrigin = '';
       }
     } else {
       this.crossOrigin = undefined;
     }
     // Set the original attribute
     srcSetFn.call(this, url);
  },
});

}());

http://webgl-hooman.blogspot.ca/2018/01/cross-origin-image-cannot-be-loaded-in.html

CORS = Cross Origin Resource Sharing. It's a way for the webpage to ask the image server for permission to use the image.​ The cross origin is the security protection that is built in Google Chrome not allowing users to have access to local files (in this case your image/texture). Even in Safari, you will get "the operation is insecure" error. You have couple of options. The easiest way is to have your webgl application runs from a web server such as IIS or Apache. The other option is to open your webgl applications using Internet Explorer or Microsoft Edge browsers if you are using Windows. If you are running your webgl application from Mac using "FireFox" browser, add crossorigin="anonymous" to your image tag in HTML where your texture is getting loaded. But this won't work if you are using "Windows" operating system or any other browsers even in Mac! It only works with MAC+Firefox. So either change your image tag to this or simple add this var image = document.getElementById("texImage"); image.crossOrigin = ""; More on this, read: https://webglfundamentals/webgl/lessons/webgl-cors-permission.html

发布评论

评论列表(0)

  1. 暂无评论