我创建了一个bufferGeometry,它由5个平面(100x25)
组成,每个平面有两个三角形。
function createGeometry() {
var geometry = new THREE.PlaneGeometry(100, 25, 1);
return geometry;
}
function createScene() {
var bufferGeometry = new THREE.BufferGeometry();
var radius = 125;
var count = 5;
var positions = [];
var normals = [];
var colors = [];
var vector = new THREE.Vector3();
var color = new THREE.Color( 0xffffff );
var heartGeometry = createGeometry();
var geometry = new THREE.Geometry();
var step = 0;
for ( var i = 1, l = count; i <= l; i ++ ) {
geometry.copy( heartGeometry );
const y = i * 30
geometry.translate(-100, y, 0);
// color.setHSL( ( i / l ), 1.0, 0.7 );
geometry.faces.forEach( function ( face ) {
positions.push( geometry.vertices[ face.a ].x );
positions.push( geometry.vertices[ face.a ].y );
positions.push( geometry.vertices[ face.a ].z );
positions.push( geometry.vertices[ face.b ].x );
positions.push( geometry.vertices[ face.b ].y );
positions.push( geometry.vertices[ face.b ].z );
positions.push( geometry.vertices[ face.c ].x );
positions.push( geometry.vertices[ face.c ].y );
positions.push( geometry.vertices[ face.c ].z );
normals.push( face.normal.x );
normals.push( face.normal.y );
normals.push( face.normal.z );
normals.push( face.normal.x );
normals.push( face.normal.y );
normals.push( face.normal.z );
normals.push( face.normal.x );
normals.push( face.normal.y );
normals.push( face.normal.z );
colors.push( color.r );
colors.push( color.g );
colors.push( color.b );
colors.push( color.r );
colors.push( color.g );
colors.push( color.b );
colors.push( color.r );
colors.push( color.g );
colors.push( color.b );
});
}
bufferGeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) );
bufferGeometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) );
bufferGeometry.addAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
var material = new THREE.MeshBasicMaterial({
vertexColors: THREE.VertexColors,
side: THREE.FrontSide
});
var mesh = new THREE.Mesh( bufferGeometry, material );
scene.add( mesh );
}
现在,而不是为每个平面着色如何向每个平面添加文本。假设我只想在每个平面的中心显示1,2,3,4,5。
我知道要做的是添加纹理。
map:texture
将材料更改为“着色器材料” uv
添加到bufferGeometry。但是uv
和纹理之间是什么关系。
我具有纹理创建功能
//not sure for each character or one texture as a single texture
function createTexture(ch){
var fontSize = 20;
var c = document.createElement('canvas');
c.width = 100;
c.height = 25;
var ctx = c.getContext('2d');
ctx.font = fontSize+'px Monospace';
ctx.fillText(ch, c.width/2, c.height/2);
var texture = new THREE.Texture(c);
texture.flipY = false;
texture.needsUpdate = true;
return texture;
}
完整 DEMO Code
编辑
在本实验中,我认为性能是最高优先级。我们可以为每个文本添加每个网格,但这会增加屏幕中的网格数量并降低性能。我正在寻找像我的示例中那样具有单个网格的任何想法。
我找到的最接近的是this,但我不了解他们使用的确切技术。
答案 0 :(得分:3)
您必须从.faceVertexUvs
复制THREE.Geometry
属性的第一个uv通道,就像使用顶点坐标和法向矢量一样:
for ( var i = 1, l = count; i <= l; i ++ ) {
geometry.copy( heartGeometry );
const y = i * 30
geometry.translate(-100, y, 0);
geometry.faces.forEach( function ( face ) {
let f = [face.a, face.b, face.c];
for (let i=0; i < 3; ++i) {
positions.push( ...geometry.vertices[f[i]].toArray() );
normals.push( ...face.normal.toArray() );
colors.push( ...color.toArray() );
}
} );
geometry.faceVertexUvs[0].forEach( function ( faceUvs ) {
for (let i=0; i < 3; ++i) {
uv.push( ...faceUvs[i].toArray() );
}
} );
}
如果要为一个几何定义多个纹理,则必须为一个THREE.Material
使用多个THREE.Mesh
。
为.addGroup
定义组(请参见THREE.BufferGeometry
)。每个组都将一系列顶点与材料相关联。
var bufferGeometry = new THREE.BufferGeometry();
bufferGeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) );
bufferGeometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) );
bufferGeometry.addAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
bufferGeometry.addAttribute( 'uv', new THREE.Float32BufferAttribute( uv, 2 ) );
let materials = []
let v_per_group= positions.length / 3 / count;
for ( var i = 0; i < count; i ++ ) {
bufferGeometry.addGroup(i * v_per_group, v_per_group, i);
let material = new THREE.MeshBasicMaterial({
vertexColors: THREE.VertexColors,
side: THREE.FrontSide,
map : createTexture("button" + (i+1))
});
materials.push(material);
}
var mesh = new THREE.Mesh( bufferGeometry, materials );
scene.add( mesh );
var camera, scene, renderer, controls, stats;
init();
animate();
function init() {
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 45.0, window.innerWidth / window.innerHeight, 100, 1500.0 );
camera.position.z = 480.0;
scene.add( camera );
controls = new THREE.TrackballControls( camera, renderer.domElement );
controls.minDistance = 100.0;
controls.maxDistance = 800.0;
controls.dynamicDampingFactor = 0.1;
scene.add( new THREE.AmbientLight( 0xffffff, 1 ) );
createScene();
//stats = new Stats();
//document.body.appendChild( stats.dom );
window.addEventListener( 'resize', onWindowResize, false );
}
function createGeometry() {
var geometry = new THREE.PlaneGeometry(100, 25, 1);
return geometry;
}
function createTexture(ch){
var fontSize = 20;
var c = document.createElement('canvas');
c.width = 128;
c.height = 32;
var ctx = c.getContext('2d');
ctx.beginPath();
ctx.rect(0, 0, 128, 32);
ctx.fillStyle = "white";
ctx.fill();
ctx.fillStyle = "black";
ctx.font = fontSize+'px Monospace';
ctx.fillText(ch, 20, 24);
var texture = new THREE.Texture(c);
texture.flipY = true;
texture.needsUpdate = true;
return texture;
}
function createScene() {
var radius = 125;
var count = 5;
var vector = new THREE.Vector3();
var color = new THREE.Color( 0xffffff );
var heartGeometry = createGeometry();
var geometry = new THREE.Geometry();
var positions = [];
var normals = [];
var colors = [];
var uv = [];
for ( var i = 1, l = count; i <= l; i ++ ) {
geometry.copy( heartGeometry );
const y = i * 30
geometry.translate(-100, y, 0);
geometry.faces.forEach( function ( face ) {
let f = [face.a, face.b, face.c];
for (let i=0; i < 3; ++i) {
positions.push( ...geometry.vertices[f[i]].toArray() );
normals.push( ...face.normal.toArray() );
colors.push( ...color.toArray() );
}
} );
geometry.faceVertexUvs[0].forEach( function ( faceUvs ) {
for (let i=0; i < 3; ++i) {
uv.push( ...faceUvs[i].toArray() );
}
} );
}
var bufferGeometry = new THREE.BufferGeometry();
bufferGeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) );
bufferGeometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) );
bufferGeometry.addAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
bufferGeometry.addAttribute( 'uv', new THREE.Float32BufferAttribute( uv, 2 ) );
let materials = []
let v_per_group = positions.length / 3 / count;
for ( var i = 0; i < count; i ++ ) {
bufferGeometry.addGroup(i * v_per_group, v_per_group, i);
let material = new THREE.MeshBasicMaterial({
vertexColors: THREE.VertexColors,
side: THREE.FrontSide,
map : createTexture("button" + (i+1))
});
materials.push(material);
}
var mesh = new THREE.Mesh( bufferGeometry, materials );
scene.add( mesh );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
controls.update();
//stats.update();
renderer.render( scene, camera );
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/102/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/TrackballControls.js"></script>