Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Mo Jun 17, 2024 10:34

Foren-Übersicht » Programmierung » Einsteiger-Fragen
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 6 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: drawArrays Performance in Webgl
BeitragVerfasst: Do Sep 02, 2010 21:08 
Offline
DGL Member

Registriert: Fr Jul 16, 2010 18:28
Beiträge: 40
Hallo,
man bekommt häufig zu hören, dass drawArrays oder allgemein draw-Aufrufe viele Performanceverluste bedeuten. Aber, dass sie schon bei einer Menge von ca.250 Aufrufen lediglich 2-3 FPS auf dem Bildschirm zaubern, finde ich dann doch sehr merkwürdig. Erst ab unter 50 drawArrays-Aufrufen (oder auch drawElements) habe ich flüssige Bildersequenzen. Ich kann mir so auf dem ersten Blick nicht erklären, warum ein solches Ruckeln bei vergleichsweise so wenigen draws auftritt. Dies kann nichts anderes bedeuten, als dass ich etwas falsch mache. Ich skizzier mal kurz den Aufbau meines Programmes:

In meiner Szene befinden sich einige oder viele Elemente/Modelle. Jedes dieser Elemente wird durch ein Javascript-Objekt repräsentiert, das eine zeichnen-Methode besitzt. Nach dem initialisieren von VBOS, wird jedes Objekt mit Hilfe seiner zeichnen-Methode gezeichnet. Hier mal der Code von zeichnen():

Code:
objects.prototype.zeichnen=function(){
   mvPushMatrix();
      
   mvTranslate([...]);
   mvTranslate([...]);
      ...
   multMatrix(rotationMatrix);           
   mvTranslate(alleObjekte.initialTranslation);        
   setMatrixUniforms();
      
   if(this.zeichneBuffer){        //nur beim ersten Aufruf Buffer erstellen
        this.erstelleVerticesBuffer();  //hier wird this.positionBuffer erstellt und mit Daten gefüllt
             this.erstelleNormalenBuffer();
  }
  this.farbeUniform();   
      
   gl.bindBuffer(gl.ARRAY_BUFFER, this.positionBuffer);
   gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
   gl.bindBuffer(gl.ARRAY_BUFFER, this.normalBuffer);
   gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute, 3, gl.FLOAT, false, 0, 0);
         
   gl.bindFramebuffer(gl.FRAMEBUFFER,null);
       
        gl.drawArrays(gl.TRIANGLES, 0, this.vertices.length/3);
        mvPopMatrix();
}


Ich habe heraufgefunden, dass neben dem Hauptsündenbock drawArrays auch die Matrizenfunktionen extrem viel Rechenleistung beanspruchen. Woran genau das liegt (sprich, ob es an den Funtkionen oder Matrixoperationen), weiß ich nicht.

Hier mal ein paar Matrix-Funktionen (nach http://learningwebgl.com/blog/ )

Code:
  function mvTranslate(v) {
    var m = Matrix.Translation($V([v[0], v[1], v[2]])).ensure4x4();
    multMatrix(m);
  }

 function mvPushMatrix(m) {
    if (m) {
      mvMatrixStack.push(m.dup());
      mvMatrix = m.dup();
    } else {
      mvMatrixStack.push(mvMatrix.dup());
    }
  }

  function mvPopMatrix() {
    if (mvMatrixStack.length == 0) {
      throw "Invalid popMatrix!";
    }
    mvMatrix = mvMatrixStack.pop();
    return mvMatrix;
  }

Matrixoperationen basieren auf dem Matrizenframework: http://sylvester.jcoglan.com/


Ich wäre für jeden Tipp der Performancesteigerung sehr dankbar..denn ich muss schon manchmal mehr als 50 Objekte auf dem Bildschirm bringen. Die Objektstruktur brauche ich, weil einzelne Objekte z.B. im nachhinein auf einfach Art anders eingefärbt werden sollen oder es sollen Einzeltransformationen möglich sein (ein Objekt darf verschoben werden und der Rest der Szene nicht) etc..


Grüße


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: drawArrays Performance in Webgl
BeitragVerfasst: Do Sep 02, 2010 21:38 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Ähm, du benutzt WebGL, also JavaScript. Da das ganze im Browser läuft ist das im Vergleich zu compiliertem C++ oder Delphi verdammt langsam.

Also wenn ich mir anschaue wie diese Sylvester-Lib implementiert ist wunder mich nicht das das langsam ist. Schauen wir uns z.B. die einfache Addition von zwei Vektoren an:

Code:
add: function(vector) {
    var V = vector.elements || vector;
    if (this.elements.length != V.length) { return null; }
    return this.map(function(x, i) { return x + V[i-1]; });
  },
map: function(fn) {
    var elements = [];
    this.each(function(x, i) {
      elements.push(fn(x, i));
    });
    return Vector.create(elements);
  },
 setElements: function(els) {
    this.elements = (els.elements || els).slice();
    return this;
  }

// ...

Vector.create = function(elements) {
  var V = new Vector();
  return V.setElements(elements);
};


WTF? Z.B. werden da Arrays benutzt. In Java-Script sind Arrays unter Umständen (je nach Browser) keine richtgen Arrays sondern eigentlich eine Map die den Index auf den Wert abbildet. Der Index wird zuerst in einen String umgewandelt von dem ein Hashwert berechnet wird und dieser wird dann in einer Hashmap gesucht. Das hat zwar den Vorteil das man "alles" als Index benutzen kann ist aber auch im Vergleich verdammt lahm.
So wäre es doch viel einfacher:
Code:
this.x += vector.x;
this.y += vector.y;
this.z += vector.z;

Ich denke du bist gut beraten dir da selbst was zu implementieren. Alternativ schlage ich vor mein WGT als Grundlage zu benutzen. Das hat obendrein den Vorteil das GoogleWebToolkit den Code nochmal gezielt für jeden Browser optimiert.

Des weiteren solltest du überlegen ob du wirklich jedes Frame die Objekt-Matrix neu berechnen musst. Insbesondere für unbewegliche Objekte reicht es doch die Matrix einmal auszurechnen und dann nur noch mit der Camera/Projektion zu multiplizieren.

Dann scheinst du da mehrere VBOs für ein Objekt zu benutzen. Du kannst Position und Normalen auch in einen Buffer tun. Das spart dir langsame API-Aufrufe und oben drein muss sich die Grafikkarte die Daten nicht erst zusammensuchen.

Außerdem sehe ich da deinen gl.bindFramebuffer-Aufruf. Ist der notwendig. Ein Framebuffer-Wechsel ist langsam und ich weiß nicht ob die Funktion so schlau ist zu merken wenn "null" bereits gebunden ist.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: drawArrays Performance in Webgl
BeitragVerfasst: Do Sep 02, 2010 22:08 
Offline
DGL Member

Registriert: Fr Jul 16, 2010 18:28
Beiträge: 40
Erstmal danke für die schnelle Antwort 8)
Coolcat hat geschrieben:
Also wenn ich mir anschaue wie diese Sylvester-Lib implementiert ist wunder mich nicht das das langsam ist.
...
WTF?
...
Ich denke du bist gut beraten dir da selbst was zu implementieren. Alternativ schlage ich vor mein WGT als Grundlage zu benutzen. Das hat obendrein den Vorteil das GoogleWebToolkit den Code nochmal gezielt für jeden Browser optimiert.

Gut, ich mach mich auf die Suche nach etwas Schnellerem oder bastel mir was Einfaches.

Zitat:
Des weiteren solltest du überlegen ob du wirklich jedes Frame die Objekt-Matrix neu berechnen musst. Insbesondere für unbewegliche Objekte reicht es doch die Matrix einmal auszurechnen und dann nur noch mit der Camera/Projektion zu multiplizieren.

Stimmt, werde ich so machen. Generell lässt sich sagen, dass sich das Matrizenproblem ganz gut bearbeiten lässt, jedoch nicht die drawArrays Angelegenheit.

Zitat:
Dann scheinst du da mehrere VBOs für ein Objekt zu benutzen. Du kannst Position und Normalen auch in einen Buffer tun. Das spart dir langsame API-Aufrufe und oben drein muss sich die Grafikkarte die Daten nicht erst zusammensuchen.

Meinst du ein Interleaved-VBO? Derzeit beinhalten meine Objekte die Vertices und Normalen als Objektattribut (Array). Das bedeutet, dass ich aus diesen beiden Arrays ein drittes erstellen müsste um das Misch-VBO zu benutzen (ist ja kein Problem, wenn Javascript schnell auf Arrays operieren kann). Ich guck mal was es für Geschwindigkeitsvorteile mit sich bringt.

Zitat:
Außerdem sehe ich da deinen gl.bindFramebuffer-Aufruf. Ist der notwendig. Ein Framebuffer-Wechsel ist langsam und ich weiß nicht ob die Funktion so schlau ist zu merken wenn "null" bereits gebunden ist.

Das kommt auch weg oder in eine if-Abfrage..


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: drawArrays Performance in Webgl
BeitragVerfasst: Fr Sep 03, 2010 08:22 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Zitat:
(ist ja kein Problem, wenn Javascript schnell auf Arrays operieren kann). Ich guck mal was es für Geschwindigkeitsvorteile mit sich bringt.

JavaScript kann nicht sonderlich schnell auf Arrays arbeiten. Warum erstellst du den Buffer nicht von vornherein als Interleaved-Buffer? Nach meinen Experimenten habe ich festgestellt das es am schnellsten ist direkt Meshes aus JSON-Dateien zu laden, weil das der Browser nativ parsen kann.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: drawArrays Performance in Webgl
BeitragVerfasst: Sa Okt 02, 2010 23:58 
Offline
DGL Member

Registriert: Fr Jul 16, 2010 18:28
Beiträge: 40
Hi, ich habe mal nahezu alle hier genannten Vorschläge in die Tat umgesetzt und spüre einen deutlichen Performancegewinn. Besonders nach dem Wechsel zur http://code.google.com/p/glmatrix/ Matrixbibliothek gab es einige FPS-Gewinne. Ein interleaved VBO für Vertices und Normalen benutze ich auch, was aber kaum Unterschiede brachte. Wichtiger war es auf das böse bindBuffer und createBuffer zu achten..

Nun bekomme ich auch bei ca. 250 Aufrufen eine halbwegs gute Geschwindigkeit (ca. 15fps), wobei da schon die CPU und der Browserspeicher ordentlich zu kämpfen haben.
Eine höhe ANzahl von drawArrays führt leider zu unangenehmen Rucklern; das Bild ist nicht mehr flüssig.
Meine Fragen:

1.) ist es generell so, dass schon mit vergleichsweise wenigen draw-Aufrufen eine so grottenschlechte Performance üblich ist oder mache ich irgendwo einen Fehler? Meine Szene wird nicht nur maximal ~500 Objekte, sondern viel mehr darstellen müssen.

2.) Wie macht man es denn normalerweise mit derart vielen Einzelobjekten, die nach dem Zeichnen z.B. durch Colorpicking identifiziert werden und individuell manipulierbar sein sollen?
Mit ist halt nur die Idee mit dem VBO pro Objekt gekommen.

grüße


Zuletzt geändert von m.sirin am So Okt 03, 2010 10:09, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: drawArrays Performance in Webgl
BeitragVerfasst: So Okt 03, 2010 08:46 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Zitat:
1.) ist es generell so, dass schon mit vergleichsweise wenigen draw-Aufrufen eine so grottenschlechte Performance üblich ist oder mache ich irgendwo einen Fehler? Meine Szene wird nicht nur maximal ~500Objekte, sondern viel mehr darstellen müssen.

Ich denke du kannst davon ausgehen das alles was du auf der CPU machst um den Faktor 20 (mindestens!) langsamer ist als wenn du das in C++ oder Delphi machen würdest. Die Grafikkarte läuft natürlich nicht langsamer. Bei Verwendung von WebGL der Browser bzw. JavaScript der limitierende Faktor.

Zitat:
2.) Wie macht man es denn normalerweise mit derart vielen Einzelobjekten, die nach dem Zeichnen z.B. durch Colorpicking identifiziert werden und individuell manipuliert sein sollen? Mit ist halt nur die Idee mit dem VBO pro Objekt gekommen.

Sind alle Objekte sichtbar? Wenn nicht, kannst du eine Baumstruktur aufbauen so das du mit wenigen Tests viele Objekte vom rendern ausschließen kannst?
Da du ja offensichtlich Colorpicking machst musst du zweimal rendern. Mache den Sichtbarkeitstest nicht zweimal sondern erstelle eine Liste/Array der sichbaren Objekte und rendere diese zweimal.
Kannst du Berechnungen in den Vertexshader auslagern? Du könntest etwa jedes Objekt mit einem zusätzlichen Attribut pro Vertex markieren. Der Vertexshader kann dann anhand dieses Zusatz-Attributes entscheiden welche Transformationsmatrix ernehmen soll, etc...

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 6 Beiträge ] 
Foren-Übersicht » Programmierung » Einsteiger-Fragen


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 43 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.245s | 17 Queries | GZIP : On ]