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

Posted

技术标签:

【中文标题】使用fabric js canvas作为threejs 3d模型纹理【英文标题】:use fabric js canvas as a threejs 3d model texture 【发布时间】:2021-09-16 15:31:55 【问题描述】:

刚开始学习threejs,因此决定结合fabric js构建一个T恤配置器。我的目标是用户可以将图片上传到画布(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();

灯光/相机:

 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"   ></canvas></div>       
<canvas id="c"></canvas>

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

【问题讨论】:

【参考方案1】:

child.material.map = new TextureLoader().load( new THREE.MeshStandardMaterial( 地图:canvasTexture ));

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

child.material.map = canvasTexture;

【讨论】:

感谢您的回复,我刚刚更换了它,但仍然无法正常工作,这是错误所在:console.log(model.material); //无法读取未定义的属性'material' canvas2.on("after:render", function() model.material.map.needsUpdate = true; //无法读取未定义的属性'map' ); 在遍历 glTF 资源时,必须检查当前对象是否真的有材质。 THREE.GroupTHREE.Bone 的实例没有这样的属性。 我想我正在使用这行代码:if (child.material &amp;&amp; child.material.name === 'Pattern2D_13095') 在搅拌机中,我需要更改纹理的集合的名称是“Pattern2D_13095”,如果我控制台日志 child.material 我做获取材料清单 所以我设法通过改变模型来解决这个问题,纹理确实发生了变化,但颜色是黑色的,并且没有光线折射,尝试改变金属度,但仍然没有改变这是我得到的错误: Failed to execute 'texImage2D' on 'WebGL2RenderingContext': Overload resolution failed.

以上是关于使用fabric js canvas作为threejs 3d模型纹理的主要内容,如果未能解决你的问题,请参考以下文章

canvas库fabric.js踩坑

在fabric.js中将Canvas下载为PNG,给出网络错误

Html5 Canvas + fabric.js 的独立堆肥

Fabric.js - 更改矩形填充

Three.js/WebGL 和 2D Canvas -- 将 getImageData() 数组传递给 Three.DataTexture()

使用fabric.js加载SVG中的错误图像大小