首页 > 解决方案 > ThreeJS不同形状的对象纹理不起作用

问题描述

我在threejs上使用动态纹理。当我使用不同形状的对象时,纹理无法正常工作。但是,当我使用 boxGeometry 时,它工作正常。

setCanvas =()=>{
    this.canvas = window.document.getElementById("canvas");
    var ctx = this.canvas.getContext("2d");
    ctx.font = "20pt Arial";
    ctx.fillStyle = "red";
    ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
    ctx.fillStyle = "white";
    ctx.fillRect(10, 10, this.canvas.width - 20, this.canvas.height - 20);
    ctx.fillStyle = "yellow";
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
    ctx.fillText("asdasdasd", this.canvas.width / 2, this.canvas.height / 2);
  }

不同形状的对象创建者

threeObjectCreator(mesh, position, color) {

    const object = this.objectLoader.parse(mesh);
    object.position.set(position.x, position.z, position.y);

    object.rotation.x = Math.PI / 2;
    let texture = new THREE.Texture(this.canvas);
    object.material = new THREE.MeshPhongMaterial({
      color,
      side: THREE.DoubleSide,
      shininess: 30,
      //flatShading: THREE.FlatShading,
      transparent: false,
      map:texture
    });
    texture.needsUpdate = true;
    return object;
  }

在此处输入图像描述

带盒几何

let geometry = new THREE.BoxGeometry( 200, 200, 200 );
    let mesh = new THREE.Mesh(geometry, material);
    this.scene.add(mesh);

在此处输入图像描述

我怎么解决这个问题 ?

标签: javascriptreactjsthree.js

解决方案


在 OpenGL 中使用纹理时(ThreeJS 通过 WebGL 使用它),正确设置面部的 UV 参数很重要。

这些 UV 参数说明如何将 2d 纹理变形和转换为 3d 空间。

让我们看看我们的简单盒子模型 ( ) 上的 UV 参数new THREE.BoxGeometry()

[[
    [{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
    [{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
    [{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
    [{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
    [{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
    [{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
    [{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
    [{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
    [{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
    [{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
    [{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
    [{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}]
]]

这看起来很吓人

要理解这些坐标,您必须了解我们的盒子由 12 个“面”或三角形组成,在这种情况下,每边 2 个三角形。

当我们修改 UV 网格中的 1 个坐标时会发生有趣的事情:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );

var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

var geometry = new THREE.BoxGeometry( 3,3,3 );
var material = new THREE.MeshBasicMaterial( { color: 0xffffff } );

new THREE.TextureLoader().load( "https://threejs.org/examples/textures/uv_grid_opengl.jpg", (texture) => {     
    material.map = texture;
    renderer.render( scene, camera );
});

geometry.faceVertexUvs = 
    [[
        [{"x":0,"y":1},{"x":0,"y":-1},{"x":2,"y":1}],
        [{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
        [{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
        [{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
        [{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
        [{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
        [{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
        [{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
        [{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
        [{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
        [{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
        [{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}]
    ]]


var cube = new THREE.Mesh( geometry, material );
cube.rotation.x = Math.PI / 3
cube.rotation.y = 0
cube.rotation.z = Math.PI / 3
scene.add( cube );

camera.position.z = 5;
body { margin: 0; font-size: 0; }
			canvas { width: 100%; height: 100% }
<script src="https://threejs.org/build/three.js"></script>

注意纹理是如何变化的?这就是 UV 坐标如何帮助您将 2d 纹理应用到任何 3d 表面。(尝试同时使用Texture.wrapS

问题

目前,在您的代码中,您正在从外部源加载对象,很可能是 OBJ 文件(基于您使用 ObjectLoader 的事实),并且由于不存在 MAT 文件,因此不存在信息关于材料的特性。

这意味着您尝试渲染到屏幕的对象没有任何“纹理坐标”,我们需要以某种方式“提供”这些信息。

虽然可以手工制作这些数据,但这并不总是那么可销售,所以我们必须回退到另一种选择,根据物品的位置生成这些数据。

生成 UV 坐标是一个复杂的话题,因为有许多不同的映射,我建议您找到并使用“THREE.js 生成 UV 坐标 - StackOverflow”中的解决方案之一。


推荐阅读