精灵不显示

Sprite not showing

我在 https://jsfiddle.net/72mnd2yt/1/ that doesn't display the sprite I'm trying to draw. I tried to follow the code over at https://stemkoski.github.io/Three.js/Sprite-Text-Labels.html 有一些代码,我一行一行地看了,但我不确定哪里错了。有人介意看一下吗?

这里是一些相关的代码:

// picture
var getPicture = function(message){
  var canvas = document.createElement('canvas');
  canvas.width = "100%";
  canvas.height = "100%";

  var context = canvas.getContext('2d');
  context.font = "10px";
  context.fillText(message, 0, 10);
  var picture = canvas.toDataURL();
  // return picture;
  return canvas;
};

// let there be light and so forth...
var getScene = function(){
  var scene = new THREE.Scene();
  var camera = new THREE.PerspectiveCamera(
    70, 
    $('body').width(), 
    $('body').height(),
    1,
    1000
  );

  var light = new THREE.PointLight(0xeeeeee);
  scene.add(camera);
  scene.add(light);

  var renderer = new THREE.WebGLRenderer();
  renderer.setClearColor(0xefefef);
  renderer.setSize($('body').width(), $('body').height());

  camera.position.z = -10;
  camera.lookAt(new THREE.Vector3(0, 0, 0));

  return [scene, renderer, camera];
};

// now for the meat
var getLabel = function(message){
  var texture = new THREE.Texture(getPicture(message));
  var spriteMaterial = new THREE.SpriteMaterial(
    {map: texture }
  );
  var sprite = new THREE.Sprite(spriteMaterial);
  //sprite.scale.set(100, 50, 1.0);
  return sprite
};

var setup = function(){
  var scene;
  var renderer;
  var camera;
  [scene, renderer, camera] = getScene();
  $('body').append(renderer.domElement);

  var label = getLabel("Hello, World!");
  scene.add(label);

  var animate = function(){
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
  };

  animate();
};


setup();

几点:

1) canvas.width = "100%" 应为 canvas.width = "100"(canvas 大小假定为 px)。与 canvas.height.

相同

2) $('body').height() 为 0,因此渲染器 canvas 不可见(您可以在开发工具中查看它,它在元素树中但被压缩到 0px 高)。我对 jQuery 一无所知,所以不确定这是为什么,但我还是建议使用 window.innerHeightwindow.innerWidth。所以renderer.setSize(window.innerWidth, window.innerHeight)。您还需要在相机初始化中进行此更改。

3) 说到相机初始化,您将宽度和高度作为单独的参数传递,而实际上应该只有纵横比参数。 See the docs。所以
var camera = new THREE.PerspectiveCamera(70, window.innerWidth, window.innerHeight, 1, 1000)
变成
var camera = new THREE.PerspectiveCamera(70, window.innerWidth/window.innerHeight, 1, 1000)

4) 因为假定纹理是静态的,所以你需要在这部分添加一些东西:

var texture = new THREE.Texture(getPicture(message))
texture.needsUpdate = true // this signals that the texture has changed

这是一次性标志,因此如果您想要动态纹理,则需要在每次 canvas 更改时设置它。您不必每次都创建一个新的 THREE.Texture ,只需在渲染循环中添加 texture.needsUpdate (或者在仅在您想要更改纹理时触发的事件中,如果您要效率)。 See the docs,在 .needsUpdate.


此时,它应该可以工作了。以下是一些需要考虑的其他事项:

5) 您可以使用 CanvasTexture 而不是 Texture,它会为您设置 .needsUpdate。您发布的 fiddle 使用的是 Three.js r71,它没有,但较新的版本有。看起来像这样:

var texture = new THREE.CanvasTexture(getPicture(message));
// no needsUpdate necessary

6) 根据注释掉的 return picture,您似乎已经在这条路径上了,但您可以使用 canvas 元素,或从 url 生成的数据canvas 用于纹理。如果getPicture现在returns一个数据url,试试这个:

var texture = new THREE.TextureLoader().load(getPicture(message))

您也可以间接使用数据 url 和 Texture:

var img = document.createElement('img')
var img = new Image()
img.src = getPicture(message)
var texture = new THREE.Texture(img);
texture.needsUpdate = true

如果不是,请坚持使用 TextureCanvasTexture,两者都需要一个 canvas 元素。 Texture 可以通过传入 src 设置为数据 url.

的图像元素来间接获取 url

Fiddle 以及概述的修复: https://jsfiddle.net/jbjw/x0uL1kbh/