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

Aktuelle Zeit: Sa Jul 12, 2025 23:02

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



Ein neues Thema erstellen Auf das Thema antworten  [ 10 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Render-Vorgang optimieren
BeitragVerfasst: Mi Apr 22, 2009 14:30 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Okt 03, 2007 14:22
Beiträge: 388
Hi,

in der folgenden Renderprozedur wird eine dreidimensionale Animation gezeichnet und darüber eine zweidimensionale GUI. Sie macht auf mich aber einen schlechten Eindruck - gluPerspective gehört eigentlich nicht in die Renderprozedur selbst, sondern davor. Kann man das optimieren ?
Code:
  1. glColor3f(1.0 , 1.0, 1.0);
  2.  
  3. glMatrixMode(GL_PROJECTION);
  4.   glLoadIdentity;
  5.   glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 128);
  6. glMatrixMode(GL_MODELVIEW);
  7.  
  8. glLoadIdentity;
  9. glTranslatef(0, 0, 0);
  10.  
  11. // GUI zeichnen
  12. b.Draw;
  13. m.Draw;
  14. s.Draw;
  15.  
  16. glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
  17. glMatrixMode(GL_PROJECTION);
  18. glLoadIdentity;
  19. gluPerspective(45.0, SCREEN_WIDTH/SCREEN_HEIGHT, 0.1, 300.0);
  20. glTranslatef(0, 0, -175);
  21. glRotatef(90, 0.0, 1.0, 0.0);
  22. glRotatef(-90, 1.0, 0.0, 0.0);
  23. glMatrixMode(GL_MODELVIEW);
  24. glLoadIdentity;
  25.  
  26. // Aktuellen Frame der Animation rendern
  27. Animation.Render(Trunc(Time/33.333));


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Apr 22, 2009 14:50 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Du setzt die Matrix nur einmal pro Frame neu, das fällt nicht weiter auf. Vielleicht ist gluPerspective langsam, aber nicht so langsam das du das nicht jedes Frame einmal aufrufen könntest. Optimiere lieber an den Stellen wo du mehr rausholen kannst ;)

Wenn du unbedingt optimieren willst, und die Matrix immer gleich ist, kannst du die Matrix einmal am Anfang setzen und dann via glGetFloat(GL_PROJECTION_MATRIX, ....) auslesen. Später kannst du die Matrix dann mit glLoadMatrix wieder laden. Ich verwende eigentlich nur glLoadMatrix da ich meine eigenen Matrix- und Vektorklassen habe. Das ermöglicht wesentlich bessere Kontrolle darüber wann was berechnet wird.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Apr 23, 2009 01:55 
Offline
DGL Member
Benutzeravatar

Registriert: Di Mai 18, 2004 16:45
Beiträge: 2623
Wohnort: Berlin
Programmiersprache: Go, C/C++
Wenn du unbedingt das gluPerspective raus haben willst, dann benutzt glPushMatrix und glPopMatrix.
Das ist GPU seitig und da geht nicht noch was vom RAM über den Bus in den VRAM.
Der gluPerspective Befehl kommt dann in das Resize Event, welches ja beim erstellen von einem Fenster sowieso aufgerufen wird.

Code:
  1. void TKar_ViewportOGL::BeginOrtho()
  2. {
  3.   if (glIsEnabled(GL_DEPTH_TEST))
  4.   {
  5.     glDisable(GL_DEPTH_TEST);
  6.     DepthTestEnabled=true;
  7.   } else
  8.     DepthTestEnabled=false;
  9.   glMatrixMode(GL_PROJECTION);
  10.   glPushMatrix();
  11.   glLoadIdentity();
  12.   glOrtho( 0, Width-Left, Height-Top,0, -1, 1 );
  13.   glMatrixMode(GL_MODELVIEW);
  14.   glPushMatrix();
  15.   glLoadIdentity();
  16. }
  17.  
  18. void TKar_ViewportOGL::EndOrtho()
  19. {
  20.   if (DepthTestEnabled)
  21.     glEnable(GL_DEPTH_TEST);
  22.   glMatrixMode(GL_PROJECTION);
  23.   glPopMatrix();
  24.   glMatrixMode(GL_MODELVIEW);
  25.   glPopMatrix();
  26. }


Da hast du noch ein bischen c++ Code, der den ich in der Karmarama Engine verwende.

_________________
"Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren"
Benjamin Franklin

Projekte: https://github.com/tak2004


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Apr 23, 2009 10:18 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Zitat:
Das ist GPU seitig und da geht nicht noch was vom RAM über den Bus in den VRAM.

Da DirectX keine derartigen Funktionen hat würde ich das mal bezweifeln. Das dürfte genauso wenig auf der GPU laufen wie glTranslate, glRotate und ähnliches. Der Treiber bzw. OpenGL berechnet eine resultierende Matrix (bzw. einige Variationen davon) und schickt nur diese an die Grafikkarte.
Trotzdem ist der Matrixstack natürlich eine Option.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Apr 23, 2009 12:15 
Offline
DGL Member
Benutzeravatar

Registriert: Di Mai 18, 2004 16:45
Beiträge: 2623
Wohnort: Berlin
Programmiersprache: Go, C/C++
Da leider Khronos, OpenGL.org, DGL und Microsoft den gleichen nichts aussagenden Text verwenden, sowie NV und ATI kein Wort zu ihren Treibern verlieren kann man es leider nicht mit Gewissheit sagen welche von beiden Varianten die wirkliche ist.
Ich bin der Meinung, dass es im VRAM liegt und auch dort ausgeführt wird, da nichts anderes passiert als das die aktuelle Matrix durch eine aus dem Stack ausgetauscht wird bzw. auf den Stack hinterlegt wird.
Es wäre sehr ineffektiv die aktuelle Matrix jedes mal über den bus zu jagen, wenn ein Vertice berechnet werden soll bzw. die Matrizen(Projection, Modelview) miteinander verwendet werden.
Noch dazu wäre es sehr ineffektiv die ganze Matrizen Berechnung auf der CPU zu machen, da die GPU darauf optimiert ist.
Wäre ich der Treiber Entwickler, dann hätte ich ein 2KiloByte Bereich im Speicher reserviert, damit ich die 32Matrizen(der Stack darf maximal 32 Matrizen enthalten) unter bringen kann und die restlichen Matrizen, wie Modelview, Projection, inverse und so weiter auch in den VRAM gepackt, damit man diese dann sehr schnell in die Register der GPU bekommt.

_________________
"Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren"
Benjamin Franklin

Projekte: https://github.com/tak2004


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Apr 23, 2009 13:01 
Offline
DGL Member
Benutzeravatar

Registriert: So Jun 04, 2006 12:54
Beiträge: 263
Matrizen sind nichts anderes als Uniform Variablen. Da der Support eh deprecated ist, kann man davon ausgehen, das diese noch nie auf der Grafikkarte direkt gespeichert wurden.

_________________
Lumina plattform unabhängige GLSL IDE


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Apr 23, 2009 13:45 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Korrekt, das haben wir hier schon mal irgendwo diskutiert. Es wird nur die resultierende Matrix übertragen, immer dann wenn man etwas rendert.

Zitat:
Es wäre sehr ineffektiv die aktuelle Matrix jedes mal über den bus zu jagen, wenn ein Vertice berechnet werden soll bzw. die Matrizen(Projection, Modelview) miteinander verwendet werden.

Seit wann rendert man Vertices oder Dreiecke einzeln? Man rendert VBOs oder Displaylisten. Selbst im Immediate-Mode überträgst du die Daten gesammelt beim glEnd().

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Apr 23, 2009 13:47 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Zitat:
Noch dazu wäre es sehr ineffektiv die ganze Matrizen Berechnung auf der CPU zu machen, da die GPU darauf optimiert ist.

Die GPU ist absolut nicht darauf optimiert einzelne Matrizen zu multiplizieren. Die GPU ist ein Stream-Prozessor, ausgelegt für große, gleichförmige Datenmengen die sich parallel (!) verarbeiten lassen.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Apr 24, 2009 11:37 
Offline
DGL Member
Benutzeravatar

Registriert: Di Mai 18, 2004 16:45
Beiträge: 2623
Wohnort: Berlin
Programmiersprache: Go, C/C++
Zitat:
Matrizen sind nichts anderes als Uniform Variablen. Da der Support eh deprecated ist, kann man davon ausgehen, das diese noch nie auf der Grafikkarte direkt gespeichert wurden.

Das würde ja bedeuten, dass die ganzen Variablen gesync sein müssen, sobald man ein Zeichenaufruf durchführt. Wenn man dies zum Zeitpunkt eines Zeichenaufrufes macht, dann hat man ja locker 10 Variablen, die über den bus müssen und wenn man dann ein VBO mit mehreren Faces hat wäre das ein großer sich wiederholender mehraufwand.
Sollte man nur die sich veränderten schicken, dann wäre die Anzahl der Prüfungen, ob es sich verändert hat schon so groß, dass man auch einfach die States hätte schicken können.
Wenn man diese beim ändern der Variablen macht, dann sollte kein wiederholender mehraufwand entstehen aber dann müssen ja cpu und gpu ständig gesynct werden, wenn man die Matrizen und andere Uniform Variablen konfiguriert. Das lässt 2 verschiedene Optimierungsansätze zu, 1. die reduzierung von Zeichenaufrufen(durch z.B. Virtuelle Texturen) und 2. die reduzierung von Stateaufrufe(durch z.B. glPushMatrix,glLoadMatrix,glPopMatrix).
Wenn es deprecated ist, dann sollte es ja in den neuen OpenGL 3.1 specs ja schon raus sein und wie funktioniert es dann dort mit der Matrix multiplikation ?

Zitat:
Korrekt, das haben wir hier schon mal irgendwo diskutiert. Es wird nur die resultierende Matrix übertragen, immer dann wenn man etwas rendert.

Den Thread muss ich überlesen haben, wäre nett mal zu linken, da ich keinen Artikel im Netzt gefunden habe, wo ein Entwickler von AMD oder NVidia mal gesagt hat, was denn nun wirklich passiert.

Zitat:
Seit wann rendert man Vertices oder Dreiecke einzeln? Man rendert VBOs oder Displaylisten. Selbst im Immediate-Mode überträgst du die Daten gesammelt beim glEnd().

Das ist korrekt, ändert aber nichts daran, dass jedes Vertice eines VBOs oder einer Displayliste mit der resultierenden Matrix multiplizieren musst, sonnst würde man ja nicht die endgültige Bildschirmposition raus kommen.

Zitat:
Die GPU ist absolut nicht darauf optimiert einzelne Matrizen zu multiplizieren. Die GPU ist ein Stream-Prozessor, ausgelegt für große, gleichförmige Datenmengen die sich parallel (!) verarbeiten lassen.

Klar ist die GPU darauf optimiert, sie beherscht half(ka ob das die älteren Modelle auch schon konnten) und full float vektor rechnung und durch die Parallelisierung wird der Durchsatzt von Berechnungen beschleunigt. Um die Matrix kann auf Vektorrechnung runter reduziert werden und diese arbeitet wieder parallel. So ist eine Matrix multiplikation, mit einem Vektor(z.B. Position), schneller, da man die berechnung gut zerlegen und aufteilen kann. Die multiplikation von Matrix und Vertice ist eine sehr häufig auftretende Operation in der Render Pipeline(siehe multiplikation mit Modelview- und Projection-Matrix).

Ich hab mir überlegt, wenn man mit CodeAnalyst(Profieler von AMD für AMD CPUs) wärend einer Test Anwendung laufen lässt, sollte man das recht einfach raus bekommen, da Code Analyst neben den Prozess auch die restliche Aktivität des Prozessors verfolgt(um zu zeigen wieviel Anteil der Prozess an der Gesamtleistung hatte) und somit man ja die ganze Matrix Multiplikation wieder finden müsste.
Das werde ich mal am Wochenende in Angriff nehmen, dann hat man wenigstens was konkretes.

_________________
"Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren"
Benjamin Franklin

Projekte: https://github.com/tak2004


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Apr 24, 2009 12:13 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Zitat:
Das ist korrekt, ändert aber nichts daran, dass jedes Vertice eines VBOs oder einer Displayliste mit der resultierenden Matrix multiplizieren musst, sonnst würde man ja nicht die endgültige Bildschirmposition raus kommen.

Ich habe auch nichts anderes behauptet. In einer komplexen Szene verwendest du normalerweise mehrere Matrizen die miteinander multipliziert werden. Beispielsweise einmal Projektion, einmal glTranslate, einmal glRotate und nochmal glTranslate. Also vier Matrizen. Diese vier Matrizen werden von der CPU miteinander multipliziert und nur die resultierende Matrix (siehe gl_ModelViewProjectionMatrix im Shader) wird dann an die Grafikkarte geschickt. Die Grafikkarte nutzt dann diese Matrix um damit einzelne Vertices zu transformieren. Das ist viel schneller als jeden Vertex mit vier Matrizen zu transformieren.

Zitat:
Den Thread muss ich überlesen haben, wäre nett mal zu linken

viewtopic.php?p=69547#69547

_________________
Yeah! :mrgreen:


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


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 3 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:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.010s | 14 Queries | GZIP : On ]