我目前完全坚持允许用户从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>
image of current three.js result with HTML loader at the top
答案 0 :(得分:1)
使用addEventListener
添加“更改”事件
到“文件”input
:
document.getElementById('userImage').addEventListener('change', function(e) {
.....
} );
新文件可以通过事件参数的target.files[0]
属性获取:
var userImage = e.target.files[0];
使用URL.createObjectURL
创建包含URL的DOMString:
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>
答案 1 :(得分:0)
这可以解决问题:
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;
}
使用onChange输入运行该fileUpload
方法。这样,您无需在每次上传图像时都重新初始化场景。
确保shader
是一个可以从fileUpload
方法中访问的变量。