Three.js和加载跨域图片 [英] Three.js and loading a cross-domain image

查看:56
本文介绍了Three.js和加载跨域图片的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道以前有人问过这个问题,我读过我能找到的所有问题和答案,但没有任何效果.

I know this has been asked before, and I've read ever question and answer I've been able to find, but nothing works.

我在本地服务器 (IIS) 上运行它.我正在尝试从 imgur 加载图像,然后使用代码将其用作对象的纹理:

I'm running this on a local server (IIS). I'm trying to load an image from imgur and then use that as texture for an object using the code:

var savedImage = /[^?]*$/.exec(location.search)[0];
if (savedImage != "") { savedImageLoad("http://i.imgur.com/" + savedImage + ".jpg"); };

    function savedImageLoad(image) {
        var mapOverlay = new THREE.ImageUtils.loadTexture(image);
        sphere.material = new THREE.MeshBasicMaterial({map: mapOverlay, needsUpdate: true});;
        sphere.geometry.buffersNeedUpdate = true;
        sphere.geometry.uvsNeedUpdate = true;
    }

但它给出了错误:

Uncaught SecurityError: Failed to execute 'texImage2D' on 'WebGLRenderingContext': The cross-origin image at http://i.imgur.com/uBD0g95.jpg may not be loaded.

我尝试将 THREE.ImageUtils.crossOrigin = "anonymous"; 或一些变体放置在我的代码的开头、结尾和其他不同的位置.我添加了一个 web.config

I've tried placing THREE.ImageUtils.crossOrigin = "anonymous";, or some variation of, at the beginning of my code, at the end, and at other various points. I've added a web.config with

<?xml version="1.0" encoding="utf-8"?>
<configuration>
 <system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="Access-Control-Allow-Origin" value="*" />
      <add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS" />
      <add name="Access-Control-Allow-Headers" value="Content-Type" />
    </customHeaders>
  </httpProtocol>
 </system.webServer>
</configuration>

但这没有用.这也不适用于托管在 bitbucket.org 上的网站,这对我来说是说我的代码中缺少某些内容.

but that didn't work. This also doesn't work on a site hosted on bitbucket.org, which to me says I'm missing something in my code.

它似乎在 sphere.material = new THREE.MeshBasicMaterial({map: mapOverlay, needsUpdate: true});; 行失败,好像我注释掉那样就没有错误(但随后网格未更新).

It seems to be failing at the sphere.material = new THREE.MeshBasicMaterial({map: mapOverlay, needsUpdate: true});; line, as if I comment that out then there's no error (but then the mesh isn't updated).

我真的不知道还有什么可以在这里尝试的,任何帮助将不胜感激.

I'm really at a loss of what else to try here and any help would be appreciated.

推荐答案

更新

在较新版本的 THREE.js 中,默认处理跨源图像.THREE.ImageUtils.loadTexture 已弃用.通常使用 TextureLoader

const loader = new THREE.TextureLoader();
const mapOverlay = loader.load('http://i.imgur.com/3tU4Vig.jpg');

原答案

这有效

THREE.ImageUtils.crossOrigin = '';
var mapOverlay = THREE.ImageUtils.loadTexture('http://i.imgur.com/3tU4Vig.jpg');

这是一个示例

var canvas = document.getElementById("c");
var renderer = new THREE.WebGLRenderer({canvas: canvas});

var camera = new THREE.PerspectiveCamera( 20, 1, 1, 10000 );
var scene = new THREE.Scene();
var sphereGeo = new THREE.SphereGeometry(40, 16, 8);

var light = new THREE.DirectionalLight(0xE0E0FF, 1);
light.position.set(200, 500, 200);
scene.add(light);
var light = new THREE.DirectionalLight(0xFFE0E0, 0.5);
light.position.set(-200, -500, -200);
scene.add(light);

camera.position.z = 300;

THREE.ImageUtils.crossOrigin = '';
var texture = THREE.ImageUtils.loadTexture('http://i.imgur.com/3tU4Vig.jpg');
var material = new THREE.MeshPhongMaterial({
    map: texture,
    specular: 0xFFFFFF,
    shininess: 30,
    shading: THREE.FlatShading,
});
var mesh = new THREE.Mesh(sphereGeo, material);
scene.add(mesh);

function resize() {
    var width = canvas.clientWidth;
    var height = canvas.clientHeight;
    if (canvas.width != width ||
        canvas.height != height) {
          renderer.setSize(canvas.clientWidth, canvas.clientHeight, false);  // don't update the style. Why does three.js fight CSS? It should respect CSS :(
        
        camera.aspect = canvas.clientWidth / canvas.clientHeight;
        camera.updateProjectionMatrix();
    }
}

function render(time) {
    time *= 0.001;  // seconds
    resize();
    mesh.rotation.y = time;
    renderer.render(scene, camera);
    requestAnimationFrame(render);
}
requestAnimationFrame(render);

body {
    margin: 0;
}

#c {
    width: 100vw;
    height: 100vh;
    display: block;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/84/three.min.js"></script>
<canvas id="c"></canvas>

注意:不要将 newTHREE.ImageUtils.loadTexture

为了将图像跨域加载到 WebGL 中,发送图像的服务器必须以正确的标头进行响应.仅仅说要使用图像跨域是不够的.所做的只是告诉服务器您正在请求使用该图像的权限.

In order to load an image cross-origin into WebGL the server that's sending the image has to respond with the correct headers. It's not enough for you to say you want to use the image cross-origin. All that does is tell the server you're requesting permission to use the image.

您可以将 img.crossOrigin 或在三种情况下的 THREE.ImageUtils.crossOrigin 设置为 '', '匿名''' 相同,或者您可以将其设置为 'use-credentials' 以向服务器发送更多信息.浏览器看到您设置了 crossOrigin 并将某些标头发送到服务器.服务器读取这些标题,决定您的域是否有权使用该图像,如果您有权限,它会将某些标题发送回浏览器.浏览器,如果它看到这些标题,就会让你使用图像.

You can set img.crossOrigin, or in THREE's case THREE.ImageUtils.crossOrigin, to either '', 'anonymous' which is the same as '', or you can set it to 'use-credentials' which sends even more info to the server. The browser sees you set crossOrigin and sends certain headers to the server. The server reads those headers, decides if your domain has permission to use the image and if you do have permission it sends certain headers back to the browser. The browser, if it sees those headers will then let you use the image.

最重要的一点是服务器必须发送标头.大多数服务器不发送这些标头.imgur.com 显然确实如此.我怀疑 bitlocker 没有,尽管我没有测试过它.

The biggest point to take away from the above is the server has to send the headers. Most servers don't send those headers. imgur.com does apparently. I suspect bitlocker does not though I didn't test it.

您还必须设置crossOrigin.如果您不这样做,即使服务器发送正确的标头,浏览器也不会允许您以您不应该使用的方式使用 img.

Also you have to set crossOrigin. If you don't the browser won't allow you to use the img in ways your not supposed to be able to even if the server sends the correct header.

这篇关于Three.js和加载跨域图片的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆