Registriert: Mo Apr 11, 2005 15:56 Beiträge: 2 Wohnort: Berlin
Hallo!
Ich entwickle zur Zeit einen Raytracer. Nach diversen Optimierungen
(unter anderem mit SSE) möchte ich diesen nun per OpenGL Echtzeit-fähig
machen.
Die Ausgabe soll einfach über ein GL_QUADS mit einer Textur (die das
gerenderte Bild enthält) ablaufen.
Jetzt habe ich folgendes Problem:
Um die Textur zu verändern, also zu "refreshen", muss ich bei jedem Render-Vorgang
den Befehl glTexImage2D aufrufen. Und dieser schluckt mächtig Performance.
Ich vermute mal, das liegt daran, dass bei jedem Aufruf von glTexImage2D die
Textur in Hauptspeicher verschoben, dann verändert und dann wieder zurück
in VRAM verschoben wird.
Ich habe da mal ein kleines Beispielprogramm geschrieben, dass die
Problematik verdeutlichen soll (hat mit Raytracing nichts zu tun):
Code:
// Formular erstellen
var
Tex: GLUInt;
Data:arrayofarrayof[0..3]ofByte;
procedure TMainForm.FormCreate(Sender:TObject);
begin
{OpenGL Initializieren ... die üblichen Befehle halt}
Jetzt meine Frage: Kann man das Programm so umschreiben,
dass beim zeichnen nicht jedes mal die ganze Textur in den Hauptspeicher
verschoben wird, sondern direkt im Grafikspeicher verändert werden kann?
Oder: Gibt es eine völlig andere Variante (außer glDrawPixels) die noch
schneller ist?
Weitere Frage: Falls das funktioniert, kann
ich dann auch Farbwerte aus dem VRAM auslesen?
const int texWidth = 256; const int texHeight = 256; const int texsize = texWidth * texHeight * 4; void *pboMemory, *texData;
// Define texture level zero (without an image); notice the // explicit bind to the zero pixel unpack buffer object so that // pass NULL for the image data leaves the texture image // unspecified. glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texWidth, texHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
// Reset the contents of the texSize-sized buffer object glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, texSize, NULL, GL_STREAM_DRAW);
// Map the texture image buffer (the contents of which // are undefined due to the previous glBufferData) pboMemory = glMapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY);
// Modify (sub-)buffer data memcpy(pboMemory, texData, texsize);
// Unmap the texture image buffer glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB);
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Die Extension ARB_Pixel_buffer_object ist ja noch ziemlich neu. Von daher würde ich auf jeden Fall noch nach einer Alternativlösung ausschau halten.
So ein ähnliches Problem hatte ich vor ein paar Tage auch. Es ist wesentlich schneller, wenn du das Bild komplett neu erzeugst. Warum das so ist kann ich mir allerdings auch nicht erklären. Ich hatte das mal mit 512x512 ausprobiert und das ging halbwegs. Ich glaube, wenn dort auch noch ein Alphakanal mit dabei war dann war das auch noch mal schneller. Musste mal ein bisschen mit rumprobieren.
Registriert: Do Sep 25, 2003 15:56 Beiträge: 7810 Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Ich hatte gerade ne OpenGL-Vorlesung hier an der Uni, und da wurde ein beispiel gezeigt wo ein AVI in ordentlicher geschwindigkeit auf einem Würfel ausgegeben wurde. Das Funktionierte per SubImages und soll wohl irgendwie so funktionieren, dass die neuen Bilddaten in den Initialisierten Speicherbereich der GraKa kopiert wird.
_________________ Blog: kevin-fleischer.de und fbaingermany.com
glTexSubImage bzw. glCopyTexSubImage sollte man immer verwenden, damit der Speicher nicht neu belegt werden muß, wie das da in dem pbo Beispiel gemacht auch gemacht wird. Habe mal die Demo aus dem nvsdk ausprobiert und da war PBO+glTexSubImage 4x schnell als nur glTexSubImage.
Der Nachteil ist natürlich, daß es bislang trotz ARB Name nur mit GF Karten funktioniert. Das Prinzip ist, aber das gleiche wie bei den Vertex Buffern, man gibt bei den Texture Befehlen keinen Zeiger sondern einen Index in den gerade aktiven Buffer an und alles andere bleibt beim alten, so daß man diese Funktionalität leicht ein und ausschalten kann.
Registriert: Mo Apr 11, 2005 15:56 Beiträge: 2 Wohnort: Berlin
Puh. Erst mal danke für eure vielen nützlichen Tipps.
Ich hab das mit dem glTexSubImage2D mal ausprobiert und
erreiche jetzt 85 statt 70 fps. Immerhin schon eine Steigerung.
Wenn die Textur jedoch genauso groß wie der Bildschirm ist,
sollte man jedoch lieber die Funktion glDrawPixels verwenden.
Damit erreiche ich ca. 115 fps.
Ich hab den umgeschriebenen Sourcecode mal hier aufgeführt:
Code:
var
MainForm: TMainForm;
Tex: GLUInt;
Data:arrayofarray[0..3]ofByte;
RC : HGLRC;
DC : HDC;
const
TexSize =512;
// Formular erstellen
procedure TMainForm.FormCreate(Sender:TObject);
var
I:Integer;
begin
{OpenGL Initializieren ... die üblichen Befehle halt}
Ich hoffe, so ist es die schnellste Variante (wenn nicht, bitte antworten!).
Das in der ARB_pixel_buffer_object-Spezifikation genannte Beispiel mit dem
PBOMemory hat bei mir irgendwie nicht funktioniert. Vielleicht könnte jemand
mein Programm umschreiben, damit es so ähnlich wie das Beispiel arbeitet.
Jetzt hab schon wieder zwei neue Fragen:
1) Funktioniert die NVidia-Demo in der Spezifikation wirklich nur auf GeForce-Karten?
Ich nämlich ne Radeon 9800 Pro, wär ganz schön wenn ich das da auch mal ausprobieren könnte...
2) Wie verwende ich den von Lars Middendorf genannten Befehl \"glCopyTexSubImage\" ?[/pascal]
glCopyTexImage kopiert die Texture aus dem Framebuffer. Es gibt da wie auch bei glTexImage2d das schnellere Gegenstück glCopyTexSubImage, deshalb habe ich das mit angeführt. Für dich ist es eventuell weniger nützlich.
ATI unterstützt ARB_pixel_buffer_object leider noch nicht. Bei denen hat sich im Bereich OpenGL in letzter Zeit eh sehr wenig getan.
Noch eine Idee: Man kann auf den GF6 Karten mit ihren 65536 Befehlen im Fragmentshader den Raytracer auch auf der GPU laufen lassen. Die Koordinaten der ganzen Objekte kann man in Texturen speichern und dann ganz normal seinen Quelltext mit glsl schreiben. Es funktionieren auch if, for und while Anweisungen im Fragment Shader.
Mitglieder in diesem Forum: 0 Mitglieder und 4 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.