我是three.js的新手,并修改了一些现有的代码。
现有代码使用“THREE.BufferGeometry”+“THREE.Points”呈现图形
var geometryPc = new THREE.BufferGeometry();
var materialPc = new THREE.ShaderMaterial({....});
this.mesh = new THREE.Points(geometryPc, materialPc);
我试图在与节点一起移动的每个节点上放置标签文本。
我试过了:
我尝试为每个节点创建“THREE.Sprite”,然后分配相对于该节点的位置。
let texture = new THREE.Texture(canvas);
let spriteMaterial = new THREE.SpriteMaterial({map: texture, useScreenCoordinates: false});
let sprite = new THREE.Sprite(spriteMaterial);
这似乎有效,但当节点数量相对较高时,UI变得太重了。
我更喜欢使用“BufferGeometry”来创建文本。但是找不到办法做到这一点。
有没有更好的方法将文字放在节点上?
答案 0 :(得分:2)
你的精灵方法,到目前为止最明显,不幸的是还不够。如果我理解正确的话,每个精灵都会创建自己的纹理,因此每个精灵都会产生一个单独的绘制调用。这种方法不具备可扩展性。
我这样做的方法是制作一个能够渲染图像不同部分的着色器,然后制作一个包含字母的图像(采用等宽字体)。然后,对于几何中的每个点(应该渲染标签的位置),我为每个呈现的字母传递一组参数(着色器属性):
positionX: this.position.x, //position of entire label
positionY: this.position.y,
positionZ: this.position.z,
colorR: this.color.r,
colorG: this.color.g,
colorB: this.color.b,
colorA: this.visible ? (this.finalAlpha) : 0,
scale: this.camera.zoom, //scale must depend on camera zoom
spriteNumber: this.getTextPosition(lines[i][j]), //see below ;p
offset: j + i * 32768, //this is for positioning one particular letter,
//x and y merged together because I ran out of parameters
size: this.size
我和j是" x"和" y"标签中的字母位置,着色器自行抵消;其他参数应该或多或少明显:)
ParticleLabel.prototype.getTextPosition = function(symbol){
switch(symbol){
case '0': return 1;
case '1': return 2;
case '2': return 3;
(...)
case 'A': return 20;
case 'B': return 21;
case 'C': return 22;
(...)
我无法显示整个代码,因为我是为商业解决方案制作的,但我会在codepen上做一个例子,或者稍后再展示一个有效的解决方案。