0

Je travaille actuellement sur un projet qui visualisera des données sur le navigateur en rendant des quantités excessives de cercles caressés animés. J'ai commencé à évaluer des bibliothèques 3D et j'ai fini par essayer de créer une application de preuve de concept avec three.js. Il est capable d'animer et de restituer jusqu'à 150 000 points à 60 fps sur mon moniteur 1440p. Tout semble parfait jusqu'à ce que vous commenciez à regarder les détails. Il a deux problèmes de rendu:Problèmes de rendu de sprite avec three.js

  1. Il crée des lignes horizontales étranges, même lorsque vous mettez l'animation hors
  2. Lorsque vous mettez l'appareil photo, les zones transparentes de sprites points de chevauchement montrera la fond à la place des sprites de point sous-jacents

Voici la preuve d'application concept: https://jsfiddle.net/tcpvfbsd/1/

var renderer, scene, camera, controls; 
var points; 
var stats; 
var controls; 

var worldWidth = 200; 
var worldRadius = worldWidth/2; 
var patchSize = 10; 
var pointsAmount = 100000; 

function init() { 
    renderer = new THREE.WebGLRenderer(); 
    renderer.setSize(window.innerWidth, window.innerHeight); 
    document.body.appendChild(renderer.domElement); 

    scene = new THREE.Scene(); 
    scene.background = new THREE.Color(0x1d252d); 

    camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 1, 2000); 
    camera.position.set(0, worldWidth * 1.5, 0); 

    controls = new THREE.OrbitControls(camera, renderer.domElement); 
    controls.minDistance = 100; 
    controls.maxDistance = 1100; 

    scene.add(new THREE.GridHelper(2 * worldRadius, 2 * worldWidth/patchSize, 0x444444, 0x444444)); 



    var geometry = new THREE.BufferGeometry(); 
    var positions = new Float32Array(pointsAmount * 3); 
    var rotations = new Float32Array(pointsAmount * 1); 

    for (var i = 0; i < pointsAmount; i++) { 

    positions[i] = 0; 
    positions[i + 1] = 0; 
    positions[i + 2] = 0; 
    rotations[i] = 2 * Math.PI * Math.random(); 

    } 

    controls = new function() { 
    this.speed = 10; 
    this.amount = 10; 
    }; 

    var gui = new dat.GUI(); 
    gui.add(controls, 'speed', 0, 100); 
    //gui.add(controls, 'amount', 0, 10000).step(1);; 

    geometry.addAttribute('position', new THREE.BufferAttribute(positions, 3)); 
    geometry.addAttribute('rotation', new THREE.BufferAttribute(rotations, 1)); 

    var loader = new THREE.TextureLoader(); 
    loader.load('//i.imgur.com/AmQQnZc.png', function(texture) { 
    var material = new THREE.PointsMaterial({ 
     size: 5, 
     transparent: true, 
     map: texture 

    }); 

    points = new THREE.Points(geometry, material); 
    scene.add(points); 

    stats = new Stats(); 
    document.body.appendChild(stats.dom); 
    animate(); 
    }); 

} 

function animate() { 

    requestAnimationFrame(animate); 

    var position = points.geometry.attributes.position; 
    var count = position.count; 
    var rotation = points.geometry.attributes.rotation; 
    var speed = patchSize * controls.speed/100; 
    if (speed > 0) { 
    for (var i = 0; i < count; i++) { 

     var wiggle = Math.random() > 0.9 ? THREE.Math.randFloat(-0.1, 0.1) : 0; 
     var theta = rotation.getX(i) + wiggle; 
     let dx = speed * Math.cos(theta); 
     let dz = speed * Math.sin(theta); 
     var x0 = position.getX(i); 
     var z0 = position.getZ(i); 
     var x = THREE.Math.clamp(x0 + dx, -worldRadius, worldRadius); 
     var z = THREE.Math.clamp(z0 + dz, -worldRadius, worldRadius); 
     if (Math.abs(x) === worldRadius) dx = -dx; 
     if (Math.abs(z) === worldRadius) dz = -dz; 
     position.setX(i, x); 
     position.setZ(i, z); 
     position.setY(i, 1); 
     rotation.setX(i, Math.atan2(dz, dx)); 

    } 
    } 

    position.needsUpdate = true; 

    stats.update(); 

    renderer.render(scene, camera); 

} 
init(); 

La meilleure façon de voir les problèmes est d'attendre quelques secondes pour que le point sprites de se propager dans la zone, utilisez le contrôle de la vitesse sur coin supérieur droit pour mettre en pause l'animation et utilisez le bouton gauche de la souris pour tourner et faire pivoter la caméra.

+1

Essayez un sprite avec un arrière-plan complètement transparent et dans votre ensemble de matériaux 'transparent: false, alphaTest: 0.5'. – WestLangley

+0

Merci WestLangley! Ce problème fixe # 2. Cependant le problème n ° 1 est toujours présent. – user1937459

Répondre

0
  1. En utilisant alphatest avec une valeur de 0,5 clipsé les coins hors des cercles sans affecter le rendu d'autres cercles
  2. Réglage de la valeur transparente false supprimé l'effet de fondu buggy qui est venu après avoir réglé alphatest à 0,5
  3. Ajout fading à la texture elle-même fait les frontières de cercles lisses même pensé le réglage transparent qui a provoqué l'effet de fondu a été désactivée
  4. randomiser la position sur l'axe y par 0,01 unité a enlevé les lignes horizontales étranges