J'essaie de créer des étiquettes textuelles. J'ai besoin d'utiliser du matériau shader pour mieux contrôler l'étiquette pendant le rendu.three.js matériau de shader de gestion de la mémoire
J'ai remarqué que la mémoire ne cesse d'augmenter même si je nettoie les vieilles étiquettes.
J'ai créé un exemple jsFiddle qui est semblable à: https://threejs.org/examples/#webgl_test_memory
Le code suivant utilise un objet de toile pour générer une texture qui contient le texte à représenter comme une étiquette:
S'il vous plaît être Attention, ces calculs sont lourds et rendent l'onglet très insensible.
var container;
var camera, scene, renderer;
var labels; \t \t \t
var canvas;
init();
animate();
function init() {
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(60, window.innerWidth/window.innerHeight, 1, 10000);
camera.position.z = 200;
scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
labels = new THREE.Object3D();
canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
// get text metrics
var fontface = 'Arial';
var fontSize = 60;
context.font = fontSize + "px " + fontface;
var width = context.measureText(text).width;
// add text
var text = 'abcdef';
canvas.width = width;
canvas.height = fontSize*1.3;
context.textAlign = "center";
context.font = fontSize + "px " + fontface;
context.fillStyle = "white"; \t \t \t \t
context.fillText(text, canvas.width/2, canvas.height/2);
}
function createLabels() { \t \t \t \t \t \t \t
for(var i = 0; i < 10000 ; i++) {
createTextMesh();
}
scene.add(labels);
}
function createTextMesh() {
// canvas contents will be used for a texture
var texture = new THREE.Texture(canvas);
texture.needsUpdate = true;
var uniforms = {
text: {
type: 't',
value: texture
}
};
var material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: document.getElementById('vertex-shader').textContent,
fragmentShader: document.getElementById('fragment-shader').textContent
});
var geometry = new THREE.PlaneBufferGeometry(15, 15);
var label = new THREE.Mesh(geometry, material);
labels.add(label);
}
function clearLabels() {
for(var i = 0; i < labels.children.length; i++) {
var label = labels.children[i];
if(label.material.uniforms) {
label.material.uniforms.text.value.dispose();
}
label.material.dispose();
label.geometry.dispose();
labels.remove(label); \t \t \t \t \t
}
scene.remove(labels);
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
// build GL objects
createLabels();
renderer.render(scene, camera);
// clean up \t
clearLabels();
}
body {
margin:0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/85/three.min.js"></script> \t \t \t \t \t
<script id="fragment-shader" type="x-shader/x-fragment">
uniform sampler2D text;
varying vec2 vUv;
void main() {
vec4 finalColor = texture2D(text, vUv); \t \t \t
gl_FragColor = finalColor;
}
</script> \t \t
<script id="vertex-shader" type="x-shader/x-fragment">
varying vec2 vUv;
void main() {
vUv = uv;
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
gl_Position = projectionMatrix * mvPosition;
}
</script> \t \t \t
<canvas></canvas>
Vous pouvez utiliser les chromes de dev outils pour évaluer l'augmentation de l'utilisation de la mémoire perceptuelle.
Je vous recommande d'utiliser quelque chose comme le propre gestionnaire de tâches de Windows pour voir l'augmentation de la mémoire.
Vous pouvez réduire la vitesse de création d'étiquettes, bien que cela signifie naturellement que l'affichage de l'onglet prendra plus de temps. Est-ce que je fais le nettoyage de la ressource à tort?
Vive
@marques: qu'est-ce que vous voulez exactement? Pouvez-vous s'il vous plaît spécifier clairement. – spankajd
le problème que j'essaie de résoudre nécessite l'application pour mettre à jour plusieurs étiquettes de texte par minute. J'ai remarqué qu'après un certain temps l'onglet mourrait, mais je ne pouvais pas comprendre pourquoi. Je crois qu'il y a une fuite de mémoire quelque part et je l'ai réduit à cette fonctionnalité de three.js. – rmarques
Non, il y a un problème avec votre code. vous utilisez la fonction requestAnimationFrame qui appelle en continu la fonction animate et dans cette fonction, vous utilisez pour loop qui itère 1000 fois. – spankajd