Подтвердить что ты не робот

Three.js и загрузка междоменного изображения

Я знаю, что это было задано раньше, и я прочитал все вопросы и ответы, которые мне удалось найти, но ничего не работает.

Я запускаю это на локальном сервере (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"; или некоторые изменения в начале моего кода в конце и в других разных точках. Я добавил web.config с

<?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});;, как если бы я прокомментировал это, тогда нет ошибки (но тогда сетка не обновляется).

Я действительно в недоумении, что еще попробовать здесь, и любая помощь будет оценена.

4b9b3361

Ответ 1

Обновить

В более новых версиях 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>

Ответ 2

UPDATE: устаревший метод

Я столкнулся с этой проблемой и применил решение из ответа, чтобы найти его не работающим из-за устаревшего метода в более новых версиях 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 ) {}
);

Ответ 3

Я нашел решение для изображений и моделей JSON в соответствии с проблемой междоменного доступа. Это всегда работает, также на Localhost.

В моем случае, я загружаю игру из NodeJS на порт 3001, чтобы работать с Socket.io. Я хочу, чтобы 3d модели с порта 80.

Предположим, что все модели находятся в каталоге: 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 );
    });

Удачи!

Ответ 4

Снимок экрана с ошибкой

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/[email protected]/build/three.min.js:127:99)
    at dg.r [as setTexture2D] (https://unpkg.com/[email protected]/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/[email protected]/build/three.min.js"></script>
+ <script src="https://unpkg.com/[email protected]/build/three.min.js"></script><!-- >=0.87 (img.crossorigin) -->

Ответ 5

Вы можете использовать переменную изображения там?

что-то вроде

var myImage = new Image();

myImage.src = "//i.imgur.com/ADBTaLw.jpg";
var mapOverlay = new THREE.ImageUtils.loadTexture(myImage.src);