загрузить текстуру из пользовательской загрузки в геометрию в three.js - PullRequest
0 голосов
/ 20 мая 2018

Я новичок в three.js и javascript (кодирование вообще), но мне очень интересно экспериментировать с возможностями, и я создал несколько небольших сцен Three.js со светом, пользовательской геометрией из 3D-моделей JSONчтобы развить свои навыки, чтобы справиться с моей конечной целью создания 3D-сайта.

В настоящее время я полностью застрял в вопросе о разрешении пользователю загружать файл изображения из тега HTML «входной» файл HTML.и чтобы это изображение появилось в сетке PlaneGeometry, которая уже существует в сцене с фиктивной текстурой, уже загруженной в материал.

Я могу иметь изображение текстуры, отображаемое на плоскости без проблем, и у меня есть HTMLНа экране появляется кнопка «Ввод», я могу нажать на нее, и она загрузит изображение, но оно не связано ни с чем в three.js, и вот где я застрял, я не понимаю, как действовать.

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

<body>
<!-- three.js container -->
<input id="userImage" type="file" />
<div id="container"></div>
<script type="x-shader/x-vertex" id="vertexShader">
    varying vec2 vUv;

    void main() {
        vUv = uv;
        gl_Position = vec4(uv * 2. - vec2(1, 1), 0., 1.);
    }
</script>
<script type="x-shader/x-fragment" id="fragmentShader">
    precision highp float;

    varying vec2 vUv;
    uniform sampler2D texture1;
    void main() {
        gl_FragColor = texture2D(texture1, vUv.xy);
    }
</script>
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/three.min.js"></script>
<script>

    init()

    function init(){
        $("#userImage").change(function () {
            var image = document.createElement( 'img' );
            var texture = new THREE.Texture( image );
            image.onload = function()  {
                texture.needsUpdate = true;
        };

        userImage = $("#userImage")[0];
        if (userImage.files && userImage.files[0]) {
            var reader = new FileReader();

            reader.onload = function (e) {
                image.src = e.target.result;
            };

            reader.readAsDataURL(userImage.files[0]);
        }

        camera = new THREE.OrthographicCamera();
        renderer = new THREE.WebGLRenderer({
            antialias: false
        });
        renderer.setSize(window.innerWidth, window.innerHeight);
        shader = new THREE.ShaderMaterial({
            vertexShader: document.getElementById('vertexShader').textContent,
            fragmentShader: document.getElementById('fragmentShader').textContent,
            uniforms: {
                texture1: {
                    type: "t",
                    value: texture
                }
            }
        });
        scene = new THREE.Scene();
        scene.add(new THREE.Mesh(new THREE.PlaneGeometry(1), shader));

        $('#container').append(renderer.domElement);

            animate();

        function animate() {
            requestAnimationFrame(animate);

            renderer.render(scene, camera);
        }
    }); 
    }
</script>

Кто-нибудь возражал бы поделиться примером того, как они будут разрешать загрузку загруженной пользователем текстуры на уже существующую текстуру, материал иобъект ??

изображение текущего результата three.js с загрузчиком HTML вверху

Ответы [ 2 ]

0 голосов
/ 21 августа 2018

Это бы сработало:

shader.uniforms.texture1.value = texture

Это было бы внутри метода onChange файла и по существу заменяет исходную текстуру загруженной текстурой.

Примерно так:

fileUpload(e) {
    let userImage = e.target.files[0];     
    let userImageURL = URL.createObjectURL( userImage );

    let loader = new THREE.TextureLoader();
    loader.setCrossOrigin("");
    let texture = loader.load(userImageURL);

    // update texture
    shader.uniforms.texture1.value = texture;
}

Запустите этот метод fileUpload с помощью ввода onChange.Таким образом, вам не нужно повторно инициировать сцену каждый раз, когда изображение загружается.

Убедитесь, что shader - это переменная, к которой можно получить доступ из метода fileUpload.

0 голосов
/ 20 мая 2018

Используйте addEventListener, чтобы добавить событие "изменения" в "файл" input:

document.getElementById('userImage').addEventListener('change', function(e) {
     .....  
} );

Новый файл можно получить с помощью свойства target.files[0]аргумента события:

var userImage = e.target.files[0];     

Используйте URL.createObjectURL для создания DOMString, содержащего URL:

var userImageURL = URL.createObjectURL( userImage );

Я рекомендую использовать THREE.TextureLoader для загрузки текстуры:

var loader = new THREE.TextureLoader();
loader.setCrossOrigin("");
var texture = loader.load(userImageURL);

См. Пример, основанный на коде вашего вопроса:

init()
  
function init(){
    document.getElementById('userImage').addEventListener('change', function(e) {

    var userImage = e.target.files[0];     
    var userImageURL = URL.createObjectURL( userImage );

    container = document.getElementById('container');      
    camera = new THREE.OrthographicCamera();
    renderer = new THREE.WebGLRenderer({ antialias: false });
    renderer.setSize(window.innerWidth, window.innerHeight);
    container.appendChild(renderer.domElement);

    var loader = new THREE.TextureLoader();
    loader.setCrossOrigin("");
    var texture = loader.load(userImageURL);

    shader = new THREE.ShaderMaterial({
        vertexShader: document.getElementById('vertexShader').textContent,
        fragmentShader: document.getElementById('fragmentShader').textContent,
        uniforms: {
            texture1: { type: "t", value: texture }
        }
    });
    scene = new THREE.Scene();
    scene.add(new THREE.Mesh(new THREE.PlaneGeometry(1), shader));

    animate();
    function animate() {
        requestAnimationFrame(animate);

        renderer.render(scene, camera);
    }
    } ); 
}
<input id="userImage" type="file" />
<div id="container"></div>
<script type="x-shader/x-vertex" id="vertexShader">
    varying vec2 vUv;

    void main() {
        vUv = uv;
        gl_Position = vec4(uv * 2. - vec2(1, 1), 0., 1.);
    }
</script>
<script type="x-shader/x-fragment" id="fragmentShader">
    precision highp float;

    varying vec2 vUv;
    uniform sampler2D texture1;
    void main() {
        gl_FragColor = texture2D(texture1, vUv.xy);
    }
</script>
<script type="text/javascript" src="https://threejs.org/build/three.min.js"></script>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...