2014-01-05 13 views
5

Ich arbeite an einer 2D-Schicht-basierten Anwendung, und ich würde gerne das Compositing mit WebGL machen. Die Schichten könnten relativ zueinander verschoben sein, und jeder Rahmen könnte nur einen kleinen (rechteckigen) Teil jeder Schicht ändern. Die Breite und Höhe dieses rechteckigen Teils können jedoch unvorhersehbar variieren. Ich möchte eine Leinwand (2D) und eine Textur pro Ebene verwenden, und jeder Rahmen zeichnet auf jeder Leinwand nur den Teil der Ebene, der verändert wurde, und lädt diesen kleinen Bereich einfach auf die GPU, um den entsprechenden Teil zu aktualisieren Textur, bevor die GPU das Compositing für mich macht. Allerdings habe ich keinen effizienten Weg gefunden, nur einen Teil eines Bildes in einen Teil einer Textur zu laden. Es scheint, dass texSubImage2D()kann aktualisieren einen Teil einer Textur, aber nur vollständige Bilder/Leinwände, und es scheint nicht möglich, einen rechteckigen Bereich des Bildes zu verwenden, um zu verwenden.WebGL: Gibt es eine effiziente Möglichkeit, nur einen Teil eines Bildes/Canvas als Textur hochzuladen?

Ich habe ein paar Möglichkeiten gedacht, dies zu tun, aber jeder scheint offensichtlich, Overhead zu haben:

  • Verwendung getImageData() + texSubImage2D() nur den Teil auf die GPU zu laden, die bei der Umwandlung der Leinwand Pixel ändert (Overhead Daten zu Imagedata)
  • Wieder laden die Leinwand ganze Schicht, die jeden Rahmen mit texImage2D()
  • oder erstellen/eine kleine Canvas2D auf die richtige Dimension die Größe perfekt für jede Schicht Modifikation zu passen, dann texSubImage2D() verwenden sie es zu senden, um die damit verbundenen aktualisieren Textur (Speicher r Aufbereitungs-Overhead)

Gibt es also eine Möglichkeit, einen Teil eines Bildes/einer Leinwand für die Textur anzugeben? Etwas wie texImagePart2D() und texSubImagePart2D, die beide vier weitere Parameter akzeptieren würden, sourceX, sourceY, sourceWidth und sourceHeight, um den Rect-Bereich des Bildes/Canvas zu spezifizieren?

+0

In den meisten eingebetteten GPUs atleast wird die TexSubImage2D API langsamer sein. Es könnte besser sein, TexImage2D selbst zu verwenden. – prabindh

+0

Es gibt also keinen schnelleren Weg als die gesamte Textur neu zu laden, auch wenn nur ein Teil davon verändert wurde? Aber ich verstehe nicht, warum wäre es langsamer, wenn es nur ein kleines Rect und nicht die ganze Textur hochlädt? Liegt es daran, dass das Ändern einer vorhandenen Textur langsam ist? – Jor

Antwort

4

Leider gibt es keine Möglichkeit, einen Teil einer Leinwand/eines Bildes hochzuladen.

OpenGL ES 2.0, auf dem WebGL basiert, bietet keine Möglichkeit, dies zu tun. OpenGL ES 3.0 bietet eine Möglichkeit, ein kleineres Rechteck der Quelle in eine Textur oder einen Teil einer Textur zu laden, also wird vielleicht die nächste Version von WebGL diese Funktion bereitstellen.

Für jetzt können Sie eine separate Leinwand zum Hochladen haben. Erste Größe der Leinwand, um das Spiel der Teil Sie

canvasForCopying.width = widthToCopy; 
canvasForCopying.height= heightToCopy; 

Kopieren Sie dann den Teil der Leinwand Sie auf die Leinwand kopieren wollte für das Kopieren von

canvasForCopying2DContext.drawImage(
    srcCanvas, srcX, srcY, widthToCopy, heightToCopy, 
    0, 0, widthToCopy, heightToCopy); 

dann verwenden, um auf die Upload hochladen möchten Textur, wo Sie es wollen.

gl.texSubImage2D(gl.TEXTURE_2D, 0, destX, destY, gl.RGBA, gl.UNSIGNED_BYTE, 
       canvasForCopying); 

getImageData wird wahrscheinlich langsamer sein, da der Browser readPixels-erhalten die Bilddaten zu nennen hat, und dass Ständen die Pipeline Grafiken. Der Browser muss dies nicht für drawImage tun.

Was, warum texImage2D kann manchmal schneller als texSubImage2D hängt es von dem Fahrer/GPU aber anscheinend manchmal kann texImage2D DMA implementiert werden, während texSubImage2D nicht.texImage2D kann auch pipelined werden, indem man eine neue Textur herstellt und die alte träge wegwirft, wo texSubImage2D nicht kann.

Persönlich würde ich nicht darum kümmern, aber wenn Sie überprüfen möchten, Zeit Zehntausende von Texturen unter Verwendung von sowohl texImage2D und texSubImage2D (nicht Zeit nur eine als Grafik Pipeline sind) hochladen. Sie werden wahrscheinlich finden texSubImage2D ist schneller, wenn Ihre Textur groß ist und der Teil, den Sie aktualisieren möchten, ist kleiner als 25% der Textur. Zumindest habe ich das letzte Mal gefunden, als ich nachgesehen habe. Die meisten aktuellen Treiber sind zumindest dahingehend optimiert, dass Sie, wenn Sie texSubImage2D anrufen und den gesamten Inhalt ersetzen, intern den Code texImage2D aufrufen.

+0

Vielen Dank für die ausführliche Antwort. Ich denke, dass ich die Problemumgehung drawImage/texSubImage2D verwenden werde. Grüße. – Jor

Verwandte Themen