Spektrum-Analyzing-Monitor: Qual der Wahl
-
Das ganze ließe sich noch erheblich beschleunigen, wenn man nicht die einzelnen Farbkomponenten einzeln setzt. Oder unnötige Aufrufe von calcColorForPixel vermeidet. Bzw. , wenn man sich überlegt, ob man überhaupt pixelweise Zeichnen muss. Jedes Bildbearbeitungsprogramm muss pixelsweise Zeichnen. Viele werden sicher auch die GDI-Schnittstelle nutzen. Aber alle sind in der Lage, dies schnell zu machen.
-
Nun, wenn es um rohe Performance geht ist Direct3D/Direct2D natürlich die erste Wahl. Nur wär ich mir nicht so sicher ob ihr das braucht. Einzelne Pixel auf der CPU zu manipulieren ist, wie schon gesagt wurde, meistens nicht so der Burner (in Zeiten von GPUs noch weniger als je zuvor), warum denkt ihr denn dass ihr das tun müsst? Wenn ihr WinForms verwenden wollt: Die WinForms Controls unterstützen DoubleBuffering. Ich würde euch WPF empfehlen, einfach weil es die aktuelle Technologie ist, wenn man weiß wie kann man damit auch ziemlich performant (hardwarebeschleunigt) zeichnen.
-
@rewerwerwerwerwrwer:
Wir haben das so ähnlich umgesetzt, also das Bitmap in ein Byte-Array zerlegt und dann bearbeitet. Jedoch erreichten wir auch damit nicht die gewünschte "Flüssigkeit" in GDI+ (in GDI war das ganze schneller, aber ich denke das liegt daran, dass wir das Bitmap mit C in die Komponente gezeichnet haben). Tut mir leid, ich hätte das vielleicht noch erwähnen sollen.
Btw: Gibt es einen Unterschied zwischen unsafe code und wenn man z.B. mit IntPtr und Marshal.AllocHGlobal usw. arbeitet? Wir hatten es mit der 2. Variante versucht.
@dot:
Bei Direct2D/3D haben wir einfach das Problem, dass wir von dieser Technologie nicht wirklich viel verstehen. Dieser Themenbereich ist riesig, und ich denke, wenn man einmal damit beginnt, sollte man sich intensiv damit beschäftigen. Jedoch ist es fraglich, ob sich Zeitaufwand / Zweck diesbezüglich ausgleichen (bez. Overkill..)
WPF klingt sehr interessant, ich wollte mich schon länger einmal damit beschäftigen. Ich dachte jedoch, dass es sich dabei eher für die Entwicklung von Komponenten eignet... Kann man damit auch "zeichnen"?
Danke nochmals für eure Antworten!
mfg PapaNoah
-
PapaNoah schrieb:
Kann man damit auch "zeichnen"?
Ja klar, WPF ist ein kompletter Ersatz für die normalen WinForms (die am Ende ja nur ein Wrapper für die herkömmliche WinAPI GUI sind) und GDI. Das ganze Rendering wird von WPF dabei intern mit Direct3D erledigt.
http://msdn.microsoft.com/en-us/library/ms748373.aspx
http://msdn.microsoft.com/en-us/library/ms747393.aspx
http://msdn.microsoft.com/en-us/library/bb613591.aspx
http://msdn.microsoft.com/en-us/library/ms742254.aspx
-
dot schrieb:
PapaNoah schrieb:
Kann man damit auch "zeichnen"?
Ja klar, WPF ist ein kompletter Ersatz für die normalen WinForms (die am Ende ja nur ein Wrapper für die herkömmliche WinAPI GUI sind) und GDI. Das ganze Rendering wird von WPF dabei intern mit Direct3D erledigt.
http://msdn.microsoft.com/en-us/library/ms748373.aspx
http://msdn.microsoft.com/en-us/library/ms747393.aspx
http://msdn.microsoft.com/en-us/library/bb613591.aspx
http://msdn.microsoft.com/en-us/library/ms742254.aspxWow das sieht echt vielversprechend aus!
Werde mich da bei Gelegenheit gleich einmal reinarbeitenTipps sind natürlich weiterhin willkommen
mfg PapaNoah
-
PapaNoah schrieb:
Wir haben das so ähnlich umgesetzt, also das Bitmap in ein Byte-Array zerlegt und dann bearbeitet.
Jedoch erreichten wir auch damit nicht die gewünschte "Flüssigkeit" in GDI+Wenn Du ein fertiges Bitmap in Form eines "Byte-Array" lieferst, hat die verwendete API nur geringen Einfluss auf die Performance.
Beim Wasserfalldiagramm (Beispiel) hast Du aber verhaeltnismaessig viel Overdraw wenn Du von hinten nach vorne zeichnest.
Wenn Du andersrum vorgehst und Dir dabei fuer jede Spalte merkst, bis wohin Dein Bildschirm bereits gefuellt ist, waerst Du um ein Vielfaches schneller...
-
hellihjb schrieb:
PapaNoah schrieb:
Wir haben das so ähnlich umgesetzt, also das Bitmap in ein Byte-Array zerlegt und dann bearbeitet.
Jedoch erreichten wir auch damit nicht die gewünschte "Flüssigkeit" in GDI+Wenn Du ein fertiges Bitmap in Form eines "Byte-Array" lieferst, hat die verwendete API nur geringen Einfluss auf die Performance.
Beim Wasserfalldiagramm (Beispiel) hast Du aber verhaeltnismaessig viel Overdraw wenn Du von hinten nach vorne zeichnest.
Wenn Du andersrum vorgehst und Dir dabei fuer jede Spalte merkst, bis wohin Dein Bildschirm bereits gefuellt ist, waerst Du um ein Vielfaches schneller...Ich befürchte, ich verstehe nicht ganz was du meinst. Könntest du das vielleicht ein wenig genauer erklären?
So sieht z.B. unser Ergebnis in XNA aus:
Wir haben das Diagramm mit Zufallsdaten gefüttert, und einen Average-Filter darüber gelegt.
-
PapaNoah schrieb:
Ich befürchte, ich verstehe nicht ganz was du meinst. Könntest du das vielleicht ein wenig genauer erklären?
Er dacht du meinst mit Wasserfalldiagramm ein Wasserfalldiagramm, und nicht ein flaches Time/Frequency Diagramm wie in deinem Screenshot.
-
Grüsse an alle
Ich bin der am Anfang erwähnte Arbeitskollege.
Wollte nochmal die wichtigsten Punkte zusammenfassen.
Was wir brauchen:
- Eine Oberfläche mit 1024x1024 pixeln
- mit einer Framerate von mindestens 40 fps
- Wir müssen jeden Frame die ganze Oberfläche neu zeichnen.
- Wir müssen jeden Pixel manipulieren können.Wofür wir es brauchen:
- Time/Frequency-Diagramm, nach unten fliessend, NICHT Sonar-Style zur Dastellung eines
- Frequenzbandes (horizontal) über einen Zeitraum (vertikal) komplett mit
- Skalierungslinien und Beschreibungen (z.Bsp. Bandbreite 40Hz<->80Hz horizontal, Zeitfenster von 1.2 Sek vertikal, Skalierungslinien alle 10Hz oder 0.1Sek)
- Wird kontinuirlich mit Daten gefüttert, fliesst also.
- Das Ganze in 2D (ohne Perspektive / Ortho)Algorithmen, die wir einstetzen wollen:
- Interpolation: Wenn das Zeitfenster so kurz ist, dass nicht für jede Pixelreihe ein Datensatz zur Verfügung steht, muss interpoliert werden
- ??: Wenn das Zeitfenster so gross ist, das mehr Daten als Pixelreihen vorhanden sind. (wie heisst das noch mal?)
Techniken, die wir ausprobiert haben:
- XNA mit Texture2D.SetData<Color>(...)
- Directx mit Surface.LockRectangle(...)
- GDI mit Bitmap.LockBits(...)Wir haben unabhängig von der Renderingtechnik verschiedene Dinge ausprobiert:
z. Bsp.Teile Bild in Reihen auf
Für jede Reihe eine Textur 1024x1
Alle Texturen in einer ListeIm FeedCycle:
1. Textur am Ende der Liste herausholen, Referenz aus Liste entfernen
2. Textur mit neuen Daten übermalen
3. Textur am Anfang der Liste wieder einfügenIm DrawCycle;
1. Alle Texturen der Liste zeichnen.Natürlich Threadsafe
Ich hoffe, ich konnte euch einen Überblick verschaffen
-
Ich versteh noch immer nicht warum genau ihr Pixel manipulieren müsst. Wenn du mich fragst müsst ihr Linien zeichnen...
-
Ich sehe auch keine Notwendigkeit für mindestens 40fps. Ihr meintet wohl maximal 30fps? Wenn der Analyserechner nicht mehr berechnen kann, dann muss es auch laufen. Das scheint mir ja eine praktische Anwendung zu sein und kein Showroom für BWLer. Ich kenne mich da nicht wirklich aus, aber ich vermute die 3D-Schnittstellen holen ihre Performance auch damit, dass nicht so detailreich sind. Für eine akkurate Darstellung wäre dann GDI wohl unerlässlich. Ich hab aber schon weitaus höhere Auflösungen vor Jahren flüssig umsetzen können. Dabei handelte es sich um Video-Daten, sie mussten also auch pixelweise gezeichnet und vorher dekomprimiert werden. Und trotzdem lief die CPU nicht auf Anschlag.
-
tut nichts zur sache schrieb:
Ich kenne mich da nicht wirklich aus, aber ich vermute die 3D-Schnittstellen holen ihre Performance auch damit, dass nicht so detailreich sind.
Nein die holen ihre Performance daher dass die GPU arbeitet und eben gerade nicht die CPU jeden Pixel einzeln manipuliert...
-
Nitroxleecher schrieb:
Teile Bild in Reihen auf
Für jede Reihe eine Textur 1024x1
Alle Texturen in einer ListeWie wär's mit ein paar Texturen die z.B. je 1024x64 sind? Und halt immer hinten ne neue Zeile dranmalen - man kann ja durchaus nur Teilbereiche einer Textur locken und updaten.
-
Verstehe ich das jetzt richtig, dass jeweils nur eine neue Bildzeile dazu kommt und der Rest des Bildes lediglich verschoben werden muss?
-
Warum nicht QT mit einem OpenGL Kontext oder wxWidgets (lizenztechnisch eventuell sicherer)?
Gerade QT schimpft sich doch High Performance Toolkit :D. Spaß beiseite, aber grade in der Industrie sollte doch OpenGL verbreiteter sein als DirectX. Wobei ich nicht weiss was die Zielrechner sind auf denen das laufen soll.
Nur ein ansatz. Platformunabhängigkeit ist zwar kein Kriterium, aber das kannst dann dem Kunden als gratis Mehrwert präsentieren :p.
rya.
-
Für Windows würde ich auch ganz klar WPF empfehlen. Hardwareunterstützung ist bei Echtzeitgrafik doch ein Muss! Ansonsten wäre sicher auch vtk einen Blick wert, evtl. gibts da schon was passendes. Dafür gibts auch einige Bindings, bin mir aber nicht sicher, ob auch für C#.
-
hellihjb schrieb:
Verstehe ich das jetzt richtig, dass jeweils nur eine neue Bildzeile dazu kommt und der Rest des Bildes lediglich verschoben werden muss?
ja
-
dot schrieb:
Ich versteh noch immer nicht warum genau ihr Pixel manipulieren müsst. Wenn du mich fragst müsst ihr Linien zeichnen...
Wir müssen jeden Pixel der "Linie" mit einer dem empfangenen Wert entsprechenden Farbe versehen, damit zum Schluss eine Art Verlauf entsteht (durch die Kombination von vorhergehend empfangenen Linien).
-
hustbaer schrieb:
hellihjb schrieb:
Verstehe ich das jetzt richtig, dass jeweils nur eine neue Bildzeile dazu kommt und der Rest des Bildes lediglich verschoben werden muss?
ja
Dann verstehe ich nicht, wie man dabei Performanceprobleme haben kann.
-
Ok ich hatte etwas falsch verstanden was ihr wollt, aber nachdem ich mir euren Testscreenshot angeschaut hab isses mir klar denk ich. Ihr wollt also nicht sowas sondern sowas.
Nun, natürlich könnte man die FFT direkt auf der GPU rechnen, was performancemäßig vielleicht auch interessant sein könnte, aber ich nehme mal an ihr wollt das aus bestimmten Gründen auf der CPU lassen. D.h. ihr braucht einen Weg einfach immer nur unten in das Bild eine neue Zeile zu bekommen.
Für eine effiziente Implementierung in Direct3D9 würde ich folgendes vorschlagen: Baut euch eine Art Ringbuffer. D.h. das ganze Bild kommt in eine Textur, gerendert wird indem diese Textur auf ein Quad gespannt wird das über den ganzen Viewport geht.
Ihr braucht dazu zwei Texturen, eine im SystemMemory Pool und eine im Default Pool. Die sysmem Textur ist jener Buffer in den die CPU schreibt. Wenn eine neue Zeile aufgebaut wird, wird immer die entsprechende Zeile der sysmem Textur gelocked und die Werte reingeschrieben. Ist die Zeile fertig so wird die Textur kurz geunlocked und per UpdateTexture() die Default Pool Textur geupdated. Nach dem UpdateTexture() kann die CPU gleich die nächste Zeile angehen während die Grafikkarte unter Verwendung der Default Pool Textur (die liegt im VRAM der Grafikkarte) das Bild rendert. Der Trick ist nun dass, wenn ihr in der letzten Zeile angelangt seid, ihr einfach wieder in der ersten Zeile anfangen könnt (damit überschreibt ihr immer die ältesten Werte). Um die neue Zeile immer unten im Bild zu halten müsst ihr einfach nur die Texturkoordinaten so wählen dass der untere Rand des Quad die Texturkoordinaten der aktuellen Zeile hat und die v-Koordinate des oberen Randes entsprechend die des unteren - 1 ist. Die Grafikhardware macht automatisch die notwendige Modulo Operation sodass die beiden Enden der Textur "verklebt" werden.
Das Verfahren erlaubt es CPU und GPU weitgehend autonom zu arbeiten (die Framerate ist relativ entkoppelt von der Geschwindigkeit mit der die FFT berechnet wird, das UpdateTexture() ist praktisch der einzige Synchronisationspunkt) und kommt ohne unnötiges kopieren und mit minimalem Datenstransfer zwischen CPU und GPU aus. Man könnte den Datentransfer und die Last auf der CPU Seite sogar noch weiter verringern indem man z.B. in der Textur gar keine Farbdaten sondern nur direkt die FFT Werte ablegt und dann die Färbung in einem PixelShader direkt beim Rendern von der GPU berechnen lässt. Von einer einfachen Lookup Table bis hin zu irgendwelchen komplexeren Berechnungen, Animationen, etc. ist da alles möglich ohne dass die CPU auch nur einen Takt dafür verschwendet.Das klingt jetzt am Anfang alles vielleicht ziemlich kompliziert aber das ist es in Wirklichkeit nicht. Wenn ihr direkt in C# mit Direct3D arbeiten wollt empfehle ich SlimDX.