使用 fabric js canvas 作为 threejs 3d 模型纹理

use fabric js canvas as a threejs 3d model texture

juste 开始学习 threejs 并决定结合 fabric js 构建一个 T 恤配置器。我的目标是用户可以将图片上传到 canvas (cnvs),这将映射到 t 恤的 gltf 模型问题是纹理不显示。 代码:

var canvas2 = new fabric.Canvas('cnvs', {
backgroundColor: 'red'
});
fabric.Image.fromURL('eo.png', function(myImg) {
//i create an extra var for to change some image properties
var img1 = myImg.set({ left: 0, top: 0 ,width:150,height:150});
canvas2.add(img1); 
canvas2.renderAll();
});

var canvasTexture = new THREE.CanvasTexture(canvas2);
canvasTexture.wrapS = THREE.RepeatWrapping;
canvasTexture.wrapT = THREE.RepeatWrapping;

const gltfLoader2 = new GLTFLoader();
gltfLoader2.load('tshirt2.gltf', (gltf2) => {
model = gltf2.scene;
model.traverse(child => {
 console.log(child.material);
if (child.material && child.material.name === 'Pattern2D_13095') {
// Pattern2D_13095
child.material.map = new TextureLoader().load(  new THREE.MeshStandardMaterial({
  map: canvasTexture,
  
}));
}
});
canvas2.on("after:render", function() {
model.material.map.needsUpdate = true;
});

canvas2.on('mouse:down',function(event){
if(canvas2.getActiveObject()){
 alert(event.target);
 }

})


scene.add(model);
model.rotation.x = 1.5;
model.position.y=310;
model.position.x=-300;
model.position.z=-100;
model.scale.set(1000,1000,1000);
});


});


function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}






function render() {

if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}

renderer.render(scene, camera);

requestAnimationFrame(render);
}





function animate(){
requestAnimationFrame(animate);
cloudParticles.forEach(p => {
    p.rotation.z -= 0.001;
 
   
 });


root.rotation.z -= 0.01;

renderer.render(scene, camera);  
model.material.needsUpdate = true;


}
animate();

lights/camera:

 let cloudParticles = [];
let root;
let model;
const scene = new THREE.Scene();

const camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.1, 
1000 );
camera.position.z = 2;
camera.rotation.x = 1.16;
camera.rotation.y = -0.12;
camera.rotation.z = 0;
const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({canvas});
scene.fog = new THREE.FogExp2(0x11111f, 0.002);
renderer.setClearColor(scene.fog.color);
renderer.setSize(window.innerWidth, window.innerHeight);


document.body.appendChild( renderer.domElement );

let directionalLight = new THREE.DirectionalLight(0xff8c19);
directionalLight.position.set(0,0,1);
scene.add(directionalLight);
let orangeLight = new THREE.PointLight(0xcc6600,50,450,1.7);
orangeLight.position.set(200,300,100);
scene.add(orangeLight);
let redLight = new THREE.PointLight(0xd8547e,50,450,1.7);
redLight.position.set(100,300,100);
scene.add(redLight);
let blueLight = new THREE.PointLight(0x3677ac,50,450,1.7);
blueLight.position.set(300,300,200);
scene.add(blueLight);

let directionalLight2 = new THREE.DirectionalLight(0xffffff);
directionalLight2.position.set(-110,-110,-120);
scene.add(directionalLight2);

HTML:

<div class="cnvscon">
<canvas id="cnvs" height="256" width="256" ></canvas></div>       
<canvas id="c"></canvas>

这是结果的 img(网格是黑色的): result gltfviewer

child.material.map = new TextureLoader().load( new THREE.MeshStandardMaterial({ map: canvasTexture }));

恐怕此代码不正确。将 canvasTexture 分配给相应的 map 属性 应该就足够了。含义:

child.material.map = canvasTexture;