使用 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;
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;