Loading image Cross Origin

Hi,

I’m trying to load an image cross origin, but I’m getting an error. I found an old project from 2013 that shows how to do it, but I’ve tried that and I’m getting
Image from origin 'https://s3-eu-west-1.amazonaws.com' has been blocked from loading by Cross-Origin Resource Sharing policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://playcanvas.com' is therefore not allowed access.

Here is the code I’m using to load:

loadRemoteImage: function(url)
    {
        var material = this.entity.model.model.getMaterials()[0];
        var texture = new pc.Texture(app.graphicsDevice);
        var image = new Image();
        image.crossOrigin = "anonymous";
        image.src = 'https://s3-eu-west-1.amazonaws.com/motionlab-dartslive-images/5717f975c9326-1461188981.png';
        image.onload = function () {
            texture.setSource(image);
            material.setParameter("faceImage", texture);
            material.update();
        };
    },

Is there something I’ve missed or that needs configuring elsewhere?

Thanks

Personally I would load it using the regular resource loader rather than using the Image tag (though both are valid)

initialize: function () {
    // allow cross origin texture requests
    app.loader.getHandler("texture").crossOrigin = "anonymous";
},

loadRemoteImage: function (url) {
    var asset = new pc.Asset("faceImage", "texture", {
        url: url
    });
    app.assets.add(asset);
    asset.on("load", function (asset) {
        // do stuff
    });
    app.assets.load(asset);
}

Regarding your header issues. You need to set up your server (in this case S3) to add CORS headers. S3 has a setting for this in the bucket properties: http://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html

Hi Dave,

Thanks for the quick response. How does this line:

pc.Asset("faceImage"...)

work if there are multiple images? I can have up to 100 unique server images being loaded into a single scene. Will having them all called faceImage work, or will they override each other?

Also, once the asset has finished loading, I need to pass it to my customer shader to be rendered. How would that be done?

I’ve just tried:

var material = this.entity.model.model.getMaterials()[0];

        var asset = new pc.Asset("faceImage", "texture", {
            url: url
        });
        app.assets.add(asset);
        asset.on("load", function (asset) {
            
            material.setParameter("faceImage", app.assets.get(asset).resource);
            material.update();
        });
        app.assets.load(asset);

but that doesn’t work, I get a max callstack exceeded.

[edit] scratch that error, it was something else I’d left over. But it won’t attach the texture to the shader.

First argument in pc.Asset constructor is name: http://developer.playcanvas.com/en/api/pc.Asset.html#Asset
Which does not need to be unique.

Bear in mind, that load event will fire every time resource is changed.

assetTexture.on('load', function() {
    material.diffuseMap = this.resource;
    material.update();
});

Experimenting is always the best way to get some quick results and info :slight_smile:

Hi Dave,

Not had much chance to play with this, but something I noted you mentioned I had to set up some bucket properties… how would this work with a Facebook profile picture? I have no control over the configuration then and these give me the same error at the moment.

When using the Facebook API, I’ve found that they have a CORS header: access-control-allow-origin:* on all images I’ve accessed from the Graph API.

See our Facebook example project: https://playcanvas.com/project/390998/overview/tutorial-facebook-api