4 Stimmen

Ist ein imageData CanvasPixelArray direkt verfügbar, um eine Leinwand WebGL-Kontext?

Ich verwende Three.js, um 3D-Modelle auf einem Webgl-Canvas-Renderer über einfache DOM-Elemente zu zeichnen, und ich brauche, um Kollisionserkennung zwischen ihnen zu tun. Meine derzeit funktionierende Methode ist Renderer.domElement.toDataURL() zu verwenden, laden Sie diese als ein imageData-Objekt dann zeichnen Sie diese auf einen separaten 2D-Canvas-Kontext, dann ziehen Sie die getImageData() Pixel-Array und iterieren durch mit diese geniale Pixelkollisionsfunktion .

Dies ist unglaublich langsam und drückt meine Bildrate auf fast unspielbare ~5-8 FPS. Ohne diese Hit Detection bekomme ich etwa 40-50 FPS.

Ich vermute, dass der Grund für die Verlangsamung die unglaublich unhandliche toDataURL()->load image->drawImage()->getImageData() .

Meine Frage ist: Gibt es einen besseren Weg, um die abgeflachten 2D-Pixeldaten auf der WebGL Leinwand zugreifen? oder vielleicht eine bessere Methode zur Extrapolation meiner 3D-Objektkoordinaten ohne Parallaxe? Ehrlich gesagt, jede Möglichkeit, eine Art von Kollisionserkennung schneller als ich es derzeit tun wird immens nützlich sein.

エディトリアル : die Funktion WebGL context.readPixels() großartig und ist superschnell im Vergleich zu meiner vorherigen Lösung. Es sollte jedoch beachtet werden, dass das Datenfeld von oben nach unten gespiegelt wird, verglichen mit einem normalen Bildpixel-Datenfeld. Ich habe einfach meine Kollisionsroutine Y-Wert-Prüfung umgedreht und dies zum Funktionieren gebracht, obwohl andere möglicherweise auf kompliziertere Weise gestolpert werden. Viel Erfolg!

4voto

Toji Punkte 32827

Sie können verwenden gl.readPixels :

// Render your scene first then...
var left = 0;
var top = 0;
var width = canvas.width;
var height = canvas.height;
var pixelData = new Uint8Array(width * height * 4);
gl.readPixels(left, top, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixelData);

pixelData enthält nun die Pixeldaten der Szene in Form von Bytes ohne Vorzeichen (0-255), die wie folgt angeordnet sind [R, G, B, A, R, G, B, A...] Es sollten die gleichen Daten sein wie getImageData aber zu wesentlich geringeren Kosten.

[ EDIT : ]

Ich habe vergessen zu erwähnen, dass Sie Ihren WebGL-Kontext mit der Option preserveDrawingBuffer Option, etwa so:

var gl = canvas.getContext("experimental-webgl", {preserveDrawingBuffer: true});

Dadurch wird verhindert, dass das Innenleben von WebGL den Puffer löscht, bevor Sie ihn erreichen (was dazu führen würde, dass Sie eine ganze Menge leerer Pixel lesen). Aktivieren Sie diese Option hat das Potenzial, Ihre Rendering zu verlangsamen, aber es sollte immer noch Lasten schneller als 5-8 FPS sein!)

0voto

Ashkan Ghodrat Punkte 3094
 renderer = new THREE.WebGLRenderer({ antialias: true, preserveDrawingBuffer:true });

 var gl = renderer.getContext()
 var buf = new Uint8Array(200 * 200 * 4);
 gl.readPixels(0, 0, 200, 200, gl.RGBA, gl.UNSIGNED_BYTE, buf);

console.log(buf);

das funktioniert gut.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X