有没有办法将Sprites合并为Three.js中的Geometries?

时间:2014-05-23 18:23:00

标签: javascript three.js sprite

在我的情况下,我想在地形上放置一些带有某些城市名​​称的标签。但是当我放十个以上时,fps会下降很多。

我已按照此处编写的代码http://stemkoski.github.io/Three.js/Sprite-Text-Labels.html

我的代码是这样的:

var canvas = document.createElement('canvas');
var sizeCanvas = 250;
canvas.width = sizeCanvas;
canvas.height = sizeCanvas;
var context = canvas.getContext('2d');
context.font = "Bold " + size + "px " + font;
context.textAlign = 'center';

contexto.fillStyle = "rgba(10, 10, 10, 1.0)";

contexto.fillText(text, sizeCanvas / 2, sizeCanvas / 2);

var texture = new THREE.Texture(canvas);
texture.needsUpdate = true;

var labelMaterial = new THREE.SpriteMaterial(
        {map: texture, useScreenCoordinates: false});
var label = new THREE.Sprite(labelMaterial);

label.position.x = this._vector.x;
label.position.y = this._vector.y;
label.position.z = this._vector.z;

etiqueta.scale.set(10, 10, 1.0);

scene.add(label);

我认为合并精灵的主要麻烦在于每个标签的不同纹理。

感谢您的建议!

2 个答案:

答案 0 :(得分:2)

为了获得最终的性能提升(比@raphaelRauwolf所建议的更多的工作,在这里谈论数十万)你必须使用ParticleSystem(使用GL_POINT渲染)和使用子映像动态分配的TextureAtlas({{3}根据相机的最近邻居(https://github.com/mrdoob/three.js/pull/4661)。对于不在相机周围的其他名牌,您可以使用第二个带有较小预览铭牌的TextureAtlas。

如果你只有大约1&000;你可以做同样的事情,没有最近的邻居和子成像。只需使用所有铭牌创建TextureAtlas并使用THREE.ParticleSystem渲染它们:)

如果你对这两种方法中的一种感兴趣,请告诉我,我会详细说明。

答案 1 :(得分:1)

基本上,您为每个标签创建一个画布对象。你可以做的是,你将Base64编码的图像从画布传递给纹理,并将下一个标签写入同一个画布。这应该会给你带来性能提升。例如:

// create the canvas once
var canvas = document.createElement('canvas');

// set the size of the canvas
var sizeCanvas = 250;
canvas.width = sizeCanvas;
canvas.height = sizeCanvas;

// get the context and set the styles
var context = canvas.getContext('2d');
context.font = "Bold " + size + "px " + font;
context.textAlign = 'center';
context.fillStyle = "rgba(10, 10, 10, 1.0)";

// iterate through your labels
for(var i = 0, j = myLabels.length; i < j; i++){
  contex.fillText(myLabels[i].text, sizeCanvas / 2, sizeCanvas / 2);

  // create the texture
  var texture = new THREE.Texture(canvas.toDataURL());
  texture.needsUpdate = true; // don't know if this is needed

  // put the texture into the material
  var labelMaterial = new THREE.SpriteMaterial({map: texture, useScreenCoordinates: false});

  var label = new THREE.Sprite(labelMaterial);

  // set the label position to the vector, maybe you should put the vector into myLabels aswell
  label.position = this._vector.clone();

  // add the label to the scene
  scene.add(label);

  // clear the canvas for the new text
  context.clearRect(0,0,sizeCanvas,sizeCanvas);
}

etiqueta.scale.set(10, 10, 1.0);