我知道以前曾经问过这个问题,而且我已经读过我能找到的问题和答案,但没有任何效果。
我在本地服务器(IIS)上运行它。我正在尝试从imgur加载图像,然后使用代码将其用作对象的纹理:
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";
或其中的一些变体。我添加了一个带有
<?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上托管的网站,对我来说,我在代码中遗漏了一些内容。
似乎在sphere.material = new THREE.MeshBasicMaterial({map: mapOverlay, needsUpdate: true});;
行失败了,就好像我发表评论那样没有错误(但网格没有更新)。
我真的不知道在这里尝试什么,任何帮助都会受到赞赏。
答案 0 :(得分:52)
在较新版本的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);
&#13;
body {
margin: 0;
}
#c {
width: 100vw;
height: 100vh;
display: block;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/84/three.min.js"></script>
<canvas id="c"></canvas>
&#13;
注意:您不能将new
与THREE.ImageUtils.loadTexture
为了将图像跨源加载到WebGL中,发送图像的服务器必须使用正确的标头进行响应。仅仅说你想要使用图像交叉来源是不够的。所有这一切都告诉服务器您要求使用该图像的权限。
您可以将img.crossOrigin
或三个案例THREE.ImageUtils.crossOrigin
设置为与''
相同的'anonymous'
,''
,或者您可以将其设置为'use-credentials'
,它会向服务器发送更多信息。浏览器会看到您设置crossOrigin
并将某些标头发送到服务器。服务器读取这些标头,决定您的域是否有权使用该图像,如果您有权限,它会将某些标头发送回浏览器。如果浏览器看到这些标题,则可以使用该图像。
最重要的一点是服务器必须发送标题。大多数服务器都不会发送这些标头。 imgur.com显然。我怀疑bitlocker没有,但我没有测试它。
您还必须设置crossOrigin
。如果您不是,浏览器不会允许您以您不应该使用的方式使用img,即使服务器发送了正确的标题。
答案 1 :(得分:25)
更新:不推荐的方法
我遇到了这个问题并从答案中应用了解决方案,因为THREE.js的新版本中已弃用的方法导致它无法正常工作。我发布这个答案,万一有人得到同样的问题。尽管弃用了,但是gman在原始答案中提供的信息是最有帮助的,我建议阅读它。
THREE.ImageUtils.loadTexture()
自原始问答以来,方法已被弃用。
加载纹理的当前方式:
// instantiate a loader
var loader = new THREE.TextureLoader();
//allow cross origin loading
loader.crossOrigin = '';
// load a resource
loader.load('textures/land_ocean_ice_cloud_2048.jpg',
// Function when resource is loaded
function ( texture ) {},
// Function called when download progresses
function ( xhr ) {},
// Function called when download errors
function ( xhr ) {}
);
答案 2 :(得分:0)
我根据跨域问题找到了图像和JSON模型的解决方案。 这总是有效,也在Localhost上。
在我的情况下,我正在从端口3001的NodeJS加载游戏,以使用Socket.io。 我想要80端口的3D模型。
假设所有模型都在目录中:game / dist / models / ** / *
我创建了一个PHP文件游戏/ dist / models / json.php:
<?php
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Methods: GET');
header('Access-Control-Allow-Origin: http://localhost:3001');
if (isset($_GET['file']))
{
switch($_GET['file'])
{
case 'house1':
header('Content-Type: application/json');
$file = 'houses/house1.json';
$json = json_decode(file_get_contents($file),TRUE);
echo json_encode($json, TRUE);
die();
break;
}
}
?>
ThreeJS:
var loader = new THREE.ObjectLoader();
loader.load(distPath+"models/json.php?file=house1",function ( obj ) {
scene.add( obj );
});
玩得开心!
答案 3 :(得分:0)
VM266 three.min.js:127 THREE.WebGLState: DOMException: Failed to execute 'texImage2D' on 'WebGLRenderingContext': The image element contains cross-origin data, and may not be loaded.
at Object.texImage2D (https://unpkg.com/three@0.86.0/build/three.min.js:127:99)
at dg.r [as setTexture2D] (https://unpkg.com/three@0.86.0/build/three.min.js:103:189)
在制作Codepen演示时遇到了同样的问题: https://codepen.io/fritx/project/editor/AoLRoy
通过将three.js从0.86升级到> = 0.87来解决
- <script src="https://unpkg.com/three@0.86.0/build/three.min.js"></script>
+ <script src="https://unpkg.com/three@0.87.0/build/three.min.js"></script><!-- >=0.87 (img.crossorigin) -->