I'm currently entirely stuck on the issue of allowing a user to upload an image file from an HTML 'input' file tag, and have that image appear on a PlaneGeometry mesh that already exists in the scene with a dummy texture already loaded into the material.
I can have the texture image appear on the plane without issue, and I have the HTML 'input' file button appearing onscreen, I can click it and it will load an image but it's not linked to anything in three.js and that's where I get stuck, I don't understand how to proceed.
I found this JSFIDDLE EXAMPLE that I can see works but I can't figure out how to use it to add a custom texture to a geometry and material that already exist.
<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>
image of current three.js result with HTML loader at the top
Use addEventListener to add a "change" event
to the "file" input: 
document.getElementById('userImage').addEventListener('change', function(e) {
     .....  
} );
The new file can be get by the target.files[0] property of the event argument:
var userImage = e.target.files[0];     
Use URL.createObjectURL to create a DOMString containing a URL:
var userImageURL = URL.createObjectURL( userImage );
I recommend to use THREE.TextureLoader for loading a texture:
var loader = new THREE.TextureLoader();
loader.setCrossOrigin("");
var texture = loader.load(userImageURL);
See the example, which is based on the code of your question:
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With