2013-07-01 8 views
5

Ich benutze eine BufferGeometry, um Tausende von Würfeln zu zeichnen, die das Gelände ausmachen, aber es ist schwer herauszufinden, wie man die Geometrie aktualisiert, wenn ich die Position eines der Würfel ändern muss. Zum Beispiel, ich habe diesen Code meine Geometrie zu initialisieren: (Ich mache meinen Tests auf einer aktualisierten Version von this example)Wie schnell eine große BufferGeometry zu aktualisieren?

// 12 triangles per cube (6 quads) 
var triangles = 12 * 150000; 

var geometry = new THREE.BufferGeometry(); 
geometry.attributes = { 

    position: { 
     itemSize: 3, 
     array: new Float32Array(triangles * 3 * 3), 
     numItems: triangles * 3 * 3 
    }, 

    normal: { 
     itemSize: 3, 
     array: new Float32Array(triangles * 3 * 3), 
     numItems: triangles * 3 * 3 
    }, 

    color: { 
     itemSize: 3, 
     array: new Float32Array(triangles * 3 * 3), 
     numItems: triangles * 3 * 3 
    } 
} 

positions = geometry.attributes.position.array; 
normals = geometry.attributes.normal.array; 
colors = geometry.attributes.color.array; 

Wenn ich einen Würfel bewegen, wird es nicht bewegt zu werden scheinen, bis ich tun :

geometry.attributes.position.needsUpdate = true; 

Dies bewirkt, dass der FPS während der Aktualisierung abfällt. Kann ich das anders machen? Scheint ein bisschen unnötig, wenn ich nur einen Würfel (12 Dreiecke/36 Eckpunkte) ändere. Obwohl es sein könnte - ich habe nicht überprüft, was needsUpdate tatsächlich tut. Wenn Sie es erraten, wird das Array erneut an den Shader gesendet.

Ich dachte, ich könnte die Geometrie in separate kleinere BufferGeometries aufteilen, aber ich bin mir nicht sicher, ob das die Leistung insgesamt helfen würde. Von dem, was ich verstehe, mehr Geometrien = weniger FPS.

Wenn jemand irgendwelche Ideen hat, wie ich das tun würde, würde es geschätzt werden! :) Neben dem Update-Problem scheint BufferGeometry genau das zu sein, was ich brauche. Vielen Dank!

Antwort

7

Ich hatte das gleiche Problem mit einer sehr großen BufferGeometry beim Aktualisieren einiger Eckpunkte darin.

Eine Lösung besteht darin, _gl.bufferSubData anstelle von _gl.bufferData zu verwenden, um nur einen Teil des Puffers zu aktualisieren. (Drei js verwendet nur _gl.bufferData).

Also, wenn Sie die Positionen aktualisieren werden Sie tun:

// Erstellen Sie eine Sicht auf die Daten aus dem Index offsetSub zu aktualisieren, um die Puffer für die Positionen offsetSubEnd

var view = geometry.attributes.position.array.subarray(offsetSub, offsetSubEnd);

// bind (holen Sie sich die gl Zusammenhang mit webglrenderer)

_gl.bindBuffer(_gl.ARRAY_BUFFER, geometry.attributes.position.buffer);

// Setzen Sie die neue Wert in gutem Index in gpu-Puffer (offsetGeometry ist in Byte)

_gl.bufferSubData(_gl.ARRAY_BUFFER, offsetGeometry,view);

Beachten Sie, dass diese Lösung langsamer sein kann, wenn man einen großen Teil des Puffer Eckpunkten im Vergleich zu _gl.bufferData ändern.

6

Ab r71 unterstützt threejs bufferSubData.

Verwenden Sie ein DynamicBufferAttribute, (oder einen Satz nur updateRange richtig)

var positionAttr = geometry.attributes.position 
// if not using DynamicBufferAttribute initialize updateRange: 
// positionAttr.updateRange = {}; 
positionAttr.updateRange.offset = 0; // where to start updating 
positionAttr.updateRange.count = 1; // how many vertices to update 
positionAttr.needsUpdate = true; 
+2

nicht sicher, welche Version es geändert wurde, aber als der 'r81' dies in verschmolzen wurde [' BufferAttribute'] (https: // github.com/mrdoob/three.js/blob/r81/src/core/BufferAttribute.js#L27). – Jay

Verwandte Themen