javascript - 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);
我怎么解决这个问题 ?
解决方案
在 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”中的解决方案之一。
推荐阅读
- android - 错误:EISDIR:对目录的非法操作,在 Object.readSync 处读取
- google-sheets - 谷歌表格自动填充公式
- flutter - Flutter:避免将`forEach`与函数文字一起使用
- python-3.x - 如何根据 Python 中的条件将一个数据框中的列值添加到第二个数据框中的另一列?
- android-studio - 消费者被配置为查找与 Java 11 兼容的库的运行时,打包为 jar,其依赖项在外部声明,但是:
- scala - 如何在 Scala 中使用将函数作为参数的方法?
- face-detection - 使用 open cv 进行人脸检测
- python - 尝试从脚本执行二进制文件时,pkexec“找不到这样的文件或目录”
- rust - 如何从 Rust 获得自动转换为特征?
- python - 使用 cryptography.fernet 的元组解密问题