是否可以将纹理加载到PlaneGeometry
对象的特定面?我想要做的是将单独的纹理映射到PlaneGeometry
对象的特定2个三角形。
以下是一些示例,为PlaneGeometry
个对象的每个2个三角形着色并使用某种颜色,并且它可以正常工作:
<!DOCTYPE html>
<html lang="en">
<head>
<title>title</title>
<meta charset="utf-8">
<style>
body {
font-family: Monospace;
background-color: #f0f0f0;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/87/three.min.js"></script>
<script>
var camera, scene, renderer, geometry, material, mesh;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 500;
scene.add(camera);
// geometry
var thumbnail_width = 32;
var thumbnail_height = 32;
var width_segments = 10;
var height_segments = 10;
var plane_geometry_width = width_segments * thumbnail_width;
var plane_geometry_height = height_segments * thumbnail_height;
var geometry = new THREE.PlaneGeometry(plane_geometry_width, plane_geometry_height, width_segments, height_segments); // faces.length = widthSegments*heightSegments*2
//Draw grid with static colors
// materials
var materials = [];
materials.push(new THREE.MeshBasicMaterial({
color: 0xff0000, side:THREE.DoubleSide
}));
materials.push(new THREE.MeshBasicMaterial({
color: 0x00ff00, side:THREE.DoubleSide
}));
materials.push(new THREE.MeshBasicMaterial({
color: 0x0000ff, side:THREE.DoubleSide
}));
// Add materialIndex to face
var l = geometry.faces.length / 2;
for (var i = 0; i < l; i++) {
var j = 2 * i;
geometry.faces[j].materialIndex = i % 3;
geometry.faces[j + 1].materialIndex = i % 3;
}
// mesh
mesh = new THREE.Mesh(geometry, materials);
scene.add(mesh);
// WebGL renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
renderer.render(scene, camera);
}
</script>
</body>
然而,当我尝试以相同的方式映射纹理时,它会映射到所有三角形,这不是我想要的:
<!DOCTYPE html>
<html lang="en">
<head>
<title>title</title>
<meta charset="utf-8">
<style>
body {
font-family: Monospace;
background-color: #f0f0f0;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/87/three.min.js"></script>
<script>
var camera, scene, renderer, geometry, material, mesh;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 500;
scene.add(camera);
// geometry
var thumbnail_width = 32;
var thumbnail_height = 32;
var width_segments = 10;
var height_segments = 10;
var plane_geometry_width = width_segments * thumbnail_width;
var plane_geometry_height = height_segments * thumbnail_height;
var geometry = new THREE.PlaneGeometry(plane_geometry_width, plane_geometry_height, width_segments, height_segments); // faces.length = widthSegments*heightSegments*2
var texture = new THREE.TextureLoader().load("image_small/item_1.png")
var materials = [];
materials.push(new THREE.MeshBasicMaterial({map : texture, side: THREE.DoubleSide}));
materials.push(new THREE.MeshBasicMaterial({color: 0xff0000, side:THREE.DoubleSide}));
materials.push(new THREE.MeshBasicMaterial({color: 0x00ff00, side:THREE.DoubleSide}));
// Add materialIndex to face
var l = geometry.faces.length / 2;
for (var i = 0; i < l; i++) {
var j = 2 * i;
geometry.faces[j].materialIndex = i % 3;
geometry.faces[j + 1].materialIndex = i % 3;
}
// mesh
mesh = new THREE.Mesh(geometry, materials);
scene.add(mesh);
// WebGL renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
renderer.render(scene, camera);
}
</script>
</body>
更新
@WestLangley建议的第二个解决方案的部分代码
var texture = new THREE.TextureLoader().load("image_small/item_1.png")
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set( 10, 10 );
var materials = [];
materials.push(new THREE.MeshBasicMaterial({map : texture, side: THREE.DoubleSide}));
materials.push(new THREE.MeshBasicMaterial({color: 0xff0000, side:THREE.DoubleSide}));
materials.push(new THREE.MeshBasicMaterial({color: 0x00ff00, side:THREE.DoubleSide}));
// Add materialIndex to face
var l = geometry.faces.length / 2;
for (var i = 0; i < l; i++) {
var j = 2 * i;
geometry.faces[j].materialIndex = i % 3;
geometry.faces[j + 1].materialIndex = i % 3;
}
geometry.sortFacesByMaterialIndex();
// Mesh
mesh = new THREE.Mesh(geometry, materials);
scene.add(mesh);
// WebGL renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
UPDATE2:
var texture = new THREE.TextureLoader().load("image_small/item_1.png")
texture.flipY = true
var materials = [];
materials.push(new THREE.MeshBasicMaterial({map : texture, side: THREE.DoubleSide}));
for (var i = 0; i < geometry.faces.length; i++) {
geometry.faces[i].materialIndex = 0;
}
var uvs = geometry.faceVertexUvs[ 0 ]; // widthSegments*heightSegments*2
//UV
// (0,1) (1,1)
// (0,0) (1,0)
// For THREE.PlaneGeometry, UV ( 0, 0 ) is located at the bottom left, and ( 1, 1 ) the top right.
for (var i = 0; i < uvs.length; i++) {
if(i % 2 == 0)
{
// (0,1)[2] x
// (0,0)[1] (1,0)[3]
uvs[i][0].x = 0.0;
uvs[i][0].y = 0.0;
uvs[i][1].x = 0.0;
uvs[i][1].y = 1.0;
uvs[i][2].x = 1.0;
uvs[i][2].y = 0.0;
}
else
{
// (0,1)[1] (1,1)[2]
// x (1,0)[3]
uvs[i][0].x = 0.0;
uvs[i][0].y = 1.0;
uvs[i][1].x = 1.0;
uvs[i][1].y = 1.0;
uvs[i][2].x = 1.0;
uvs[i][2].y = 0.0;
}
}
var mesh = new THREE.Mesh(geometry, materials);
scene.add(mesh);
// WebGL renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
答案 0 :(得分:4)
您有两种选择。
一种是更改几何体的UV,使每个正方形的UV从左下角(0,0)到右上角(1,1)。
另一个解决方案是设置纹理的repeat
:
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set( 10, 10 );
BTW,在控制台中键入renderer.info
,您将看到正在生成100个绘制调用。
在设置材质索引后,将以下内容添加到代码中:
geometry.sortFacesByMaterialIndex();
您现在应该只看到3个绘制调用。
three.js r.89