Текстура в трехjs не обновляет

Я использую редактор threejs в качестве базы для работы с тремяjjs. Я пытаюсь показать некоторые подсказки, когда пользователь зависает над определенными элементами. Для этого я использую холст, который отображается как текстура на спрайте.

// create a canvas element
var canvas1 = document.createElement('canvas');
var context1 = canvas1.getContext('2d');
context1.font = "Bold 20px Arial";
context1.fillStyle = "rgba(0,0,0,0.95)";
context1.fillText('Hello, world!', 0, 20);

// canvas contents will be used for a texture
var texture1 = new THREE.Texture(canvas1)
texture1.needsUpdate = true;

// use the texture as material
var spriteMaterial = new THREE.SpriteMaterial({
    map: texture1,
    useScreenCoordinates: false
});

// create the sprite and add it tho the scene
var sprite1 = new THREE.Sprite(spriteMaterial);
sprite1.scale.set(1000, 500, 1.0);
sprite1.position.set(50, 50, 0);
scene.add(sprite1);

var i = 0;
// change the canvas' content
setInterval(function () {
    context1.clearRect(0, 0, canvas1.width, canvas1.height);
    var message = 'test' + i++;
    context1.fillText(message, 4, 20);
    texture1.needsUpdate = true;
}, 1000)

«test0» отображается, но спрайт не обновляется. Как обновить текст спрайта? Не хватает ли здесь недействительности кэша?

введите описание изображения здесь

javascript,canvas,three.js,textures,sprite,

0

Ответов: 3


1 принят

Зачем делать текстовое поле на трехмерном холсте? Было бы намного лучше, если бы IMO разместил ваш 2D-объект html, спроектировав позицию 3D-объекта в 2D-контексте вашей страницы.

Преимущество заключается в том, что не будет никакого снижения производительности рендеринга, и вы можете использовать обычный стиль CSS / HTML для своего информационного окна.

Посмотрите отличный пример того, как вы можете это сделать .

И еще один из этих ответов переполнения стека . Работает так просто:

var proj = toScreenPosition(divObj, camera);

divElem.style.left = proj.x + 'px';
divElem.style.top = proj.y + 'px';

Но если вы делаете какой-то поисковик, вы можете легко найти больше примеров ...

Здесь есть сценарий, в который нужно обманывать.


0

Я думаю, что он не работает, потому что вы не задали высоту и ширину холста.

canvas1.width = 256;
canvas1.height = 256;

Эта линия также была проблемой: context1.fillStyle = "rgba(0.0,0,0,0.95)";
я изменил ее на: context1.fillStyle = '#ff0000';для моей работы

Вот скрипка с реализованным кодом, просто добавленная высота и ширина к холсту и изменение fillStyle

Ответ Уилта, вероятно, является лучшей альтернативой, если он заполняет ваши потребности.


-1

EDIT: Я идиот. Этот вопрос составляет 2 года.

Кажется, это работает для меня ... Ты уверен, что не забываешь о некоторых ошибках в консоли? Вы поставили точку останова в свой setInterval, чтобы убедиться, что она вызвана?

Мне пришлось перенести обновление в renderloop, поскольку setInterval, по-видимому, не был определен для SO-фрагментов, но проверьте здесь:

var renderer = new THREE.WebGLRenderer();
var w = 300;
var h = 200;
renderer.setSize(w, h);
document.body.appendChild(renderer.domElement);

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
  45, // Field of view
  w / h, // Aspect ratio
  0.1, // Near
  10000 // Far
);
camera.position.set(15, 10, 15);
camera.lookAt(scene.position);
controls = new THREE.OrbitControls(camera, renderer.domElement);

var light = new THREE.PointLight(0xFFFF00);
light.position.set(20, 20, 20);
scene.add(light);
var light1 = new THREE.AmbientLight(0x808080);
light1.position.set(20, 20, 20);
scene.add(light1);

var sphereGeom = new THREE.SphereGeometry(5, 16, 16);
for (var i = 0; i < sphereGeom.vertices.length; i++) {
  var v = sphereGeom.vertices[i];
  if (v.y < 0) v.y = 0;
}
sphereGeom.verticesNeedUpdate = true;
sphereGeom.computeFaceNormals();
sphereGeom.computeVertexNormals();

var material = new THREE.MeshLambertMaterial({
  color: 0x808080
});
var mesh = new THREE.Mesh(sphereGeom, material);
scene.add(mesh);
renderer.setClearColor(0xdddddd, 1);

// create a canvas element
var canvas1 = document.createElement('canvas');
var context1 = canvas1.getContext('2d');
context1.font = "Bold 20px Arial";
context1.fillStyle = "rgba(0,0,0,0.95)";
context1.fillText('Hello, world!', 0, 20);

// canvas contents will be used for a texture
var texture1 = new THREE.Texture(canvas1)
texture1.needsUpdate = true;

// use the texture as material
var spriteMaterial = new THREE.SpriteMaterial({
  map: texture1,
  useScreenCoordinates: false
});

// create the sprite and add it tho the scene
var sprite1 = new THREE.Sprite(spriteMaterial);
sprite1.scale.set(40, 20, 1.0);
sprite1.position.set(-5, 0, -5);
scene.add(sprite1);

var i = 0;

(function animate() {
  requestAnimationFrame(animate);
  controls.update();
  renderer.render(scene, camera);



  context1.clearRect(0, 0, canvas1.width, canvas1.height);
  var message = 'test' + i++;
  context1.fillText(message, 4, 20);
  texture1.needsUpdate = true;

})();
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>

JavaScript, холст, Three.js, текстуры, спрайты,
Похожие вопросы