2D Vektrografik auf Direct3D und/oder OpenGL



  • Hallo Leute,
    im Win32-Forum hat sich schon angedeutet, dass Direct2D für mich keine Option ist. Leider basiert Direct2D zwar auf Direct3D, aber in einer opaken Art und Weise, was einfach schade ist, um es mal so auszudrücken. Folglich habe ich die letzten Tage abends etwas rumgebastelt, um mal abzuschätzen, wieviel Aufwand es wohl so wäre, etwas halbwegs vernünftiges auf Basis von Direct3D umzusetzen. Ich jetzt etwas hard-coded Zeug zum Triangulieren und Rendern da und bastele derzeit an einfachen Brushes auf Basis von Pixelshadern. Linienzüge kann ich leider auch noch nicht meshen, aber da habe ich mir schon einen Plan zurecht gelegt. Das Font-Problem ist noch ungelöst, bislang habe ich keine bessere Idee, als irgendwie mit DirectWrite in eine Bitmap zu rendern und die anschließend zu verwenden. Und überhaupt muss ich mir erst in Direct3D reinarbeiten (Meine 3D-Erfahrungen stammen aus Fixed-Function-OpenGL-Zeiten) und verschwende meine Zeit deshalb auch auf am Ende unpraktikable Ansätze.
    Wie dem auch sei, das alles ist auf jeden Fall eine Menge Arbeit, wie man sich wohl vorstellen kann. Deshalb habe ich mal rumgeschaut, was es noch so für Alternativen gibt. Dabei bin ich vor allem auf Cairo gestoßen, aber dessen OpenGL-Backend ist "experimental" und ansonsten setzt es GDI ein oder eine große Auswahl von Linux-Krams, außerdem hat es so direkt auch keinen Font-Support. Da die Linux-Welt nicht so meine Welt ist und die Bibliothek hauptsächlich Linux bedient, ist das für mich irgendwie auch nicht so "sexy". Ich stelle mir im Moment vor, dass man außer OpenGL und Direct3D eigentlich keine anderen "Backends" benötigt. Eigentlich genügte ja OpenGL, aber da ist es mit der Treibersituation zuweilen etwas hakelig, wenn ich dem glauben schenken darf, was man so über Intel-GPUs usw. liest.
    Ansonsten habe ich noch einige Blog-Einträge gefunden, die einige Ansätze besprechen, aber da kommt am Ende halt nie etwas Bibliothekartiges heraus. Das soll keine Kritik sein, aber es bleibt festzustellen, dass ein paar dahingeschriebene Funktionen und Klassen eben noch keine schöne 2D-Abstraktions-Bibliothek machen.

    Habt ihr in der Richtung noch andere Vorschläge?
    Wenn nicht, hat jemand Lust in der Richtung was zu starten? Wenn es die Erfahrungslage gebietet, würde ich mich zu diesem Zweck auch als Code-Affe anbieten 😃

    Viele Grüße,
    Deci



  • Was genau starten? Einen 2D-Layer über Direct3D(11?) legen? Der was genau kann? Text rendern, Sprites (Texturen) rendern, ..noch mehr? Kreise dynamisch aus Position + Radius generieren?



  • Und beliebige Polygone mit allen möglichen Brushes. Direkte und polygonale Linienzüge (vielleicht auch dashed?). Alles mögliche halt, was einem so in den Sinn kommt. Stencil basiertes Clipping? Vielleicht auch berechnetes Clipping für statische Geometrien.
    Also zu tun gibt's da einiges, wie ich finde, je nach Anspruch 😃



  • Wieso genau kannst du Direct2D nicht verwenden? Etwas Äquivalentes selbst zu basteln ist unglaublich viel Aufwand. Insbesondere wenn es auch Text rendern soll.
    Cairo hast du ja schon gefunden und NVIDIA hat auch was: https://developer.nvidia.com/nv-path-rendering



  • Hallo dot! Im Windows-API-Forum steht's geschrieben, warum Direct2D ausfällt. Zu Cairo habe ich auch meine Bedenken dargestellt, vielleicht kannst Du die ja noch irgendwie entkräftigen, hast Du damit und den experimentellen OpenGL-Backend Erfahrungen? Eine NV-Erweiterung nützt mir leider allerhöchstens als Optimierung etwas 😞



  • Dass Direct2D so langsam ist, kann eigentlich gar nicht sein. Zugegeben, ich konnte den Grund auch nicht finden, aber es kann eigentlich nur dein Fehler sein. Das wäre einfach zu peinlich für Microsoft. Hast du mal versucht deine Frage auf Stackoverflow zu stellen? Vielleicht weiß dort ja jemand Rat, ich habe das Gefühl die Direct2D-Erfahrung in diesem Forum ist eher gering. (Oder dot hat deinen Thread einfach noch nicht gesehen. 🤡)



  • Alles ist mein Fehler, ich bin immer schuld 😞



  • Hrmmm, naja, eine Nacht drüber geschlafen: ich werde in meiner Freizeit einfach stur weitermachen 😃
    Ich war grad am überlegen, dass ich zum Rendern von dynamischen Polygonen ja auch einfach den Stencil-Buffer so benutzen kann, dass das Polygon im ersten Pass als Fan gerendert wird, ich linksswendig inkrementiere und rechtswendig dekrementiere. Danach müsste man ja bei einer 1 landen, wo das Polygon gefüllt gehört und könnte einfach ein Quad drüberrendern. Ab einer gewissen Komplexität könnte das doch effizienter sein, als die Polygone auf der CPU zu tesselieren? Fragt sich nur, wie man den Stencil-Buffer hinterher wieder für's nächste Polygon freibekommt. Da müsste man das Quad ja nochmal drüberrendern... Hrmmm. Kreise und sowas könnte man ja auch direkt im Shader umsetzen, wobei ich keine Ahnung hab, wie man da am besten effizient die Fallunterscheidungen der Geometrietypen bewerkstelligt 😞 Wird wohl kaum effizient sein, für ein Polygon mehrmals den Shader wechseln zu müssen.
    Naja, ich hatte halt gehofft, dass vielleicht jemand, der im Gegensatz zu mir den Eindruck erweckt, er wisse was er tut, Interesse an solch einer Sache hat. Aber ist halt alles nicht so sexy wie 3D mit Global Illumination und Physics Engine 😃

    Ich habe auch einmal auf Stackoverflow bezüglich D2D eine Frage gestellt, aber ganz offenbar habe ich sie viel zu vage gestellt und es ist wohl auch nicht förderlich, wenn die Leute dort erst ein Beispielprojekt runterladen müssen, was sie mit aller Wahrscheinlichkeit nicht tun. Ich weiß nicht, wie ich ausdrücken soll, wie schlecht die Performance ist, außer zu sagen, dass ich CPU-limitiert bin und habe auch keinen "Erwartungswert".



  • Hrmmmm, also ich habe mal etwas rumprobiert, Kreissegmente und quadratische Bezier-Kurven per discard oder anderen Farben zu im Pixelshader auszuwerten. Das klappt auch hervorragend, aber im Moment sehe ich noch das Problem, dass ich mir nur schwerlich vorstellen kann, so Anti-Aliasing zu bekommen. Meinem Verständnis nach funktioniert "modernes optimiertes"-Anti-Aliasing so, dass Pixel-Shader nur einmal ausgewertet werden, aber die Geometrie selber mehrfach gesampelt wird. So kann man natürlich keine Shader filtern...
    Welche Optionen habe ich hier zur Verfügung?

    Edit: Also mir sind jetzt 2 Möglichkeiten eingefallen:
    1. Ich benutze eine Textur mit Rampe und frage die entsprechend der Nähe zum Rand ab.
    2. Ich antialiase im Shader per Hand 😃

    Beides stelle ich mir nur schwerlich als effizient vor...


  • Mod

    eine 'alte' moeglichkeit nennt sich alpha-to-coverage (A2C), dabei gibst du einen alpha wert aus anhand dessen die hardware dann eine gewisse anzahl punkt setzt in alehnung an den anti-aliasing modus. wenn du z.b. 16x AA hast und du gibst einen alpha wert von 0.49 aus, bekommst du 7 subsamples gesetzt. dabei sind die punkte relativ zufaellig angeordnet, sodass ueber die menge der punkt eine art weiche kante entsteht.

    moeglichkeit 2. ist die gaengige heutzutage. dabei berechnest du shading etc. nur einmal, gibst aber eine coverage mask aus (also wie das obere A2C, jedoch bestimmst du selbst welches pattern die maske hat), so kannst du z.b. die konturen einer pflanze genau abtasten und die maske generieren, waehrend du beleuchtung + schadden + texture sampling fuer die pflanze nur einmal machst.

    AMD nennt das "Transparency Anti-Aliasing", demos/samples findest du entsprechend bei http://amddevcentral.com/tools/gpu/RadeonSDKSamplesDocuments/Pages/default.aspx
    geht ab directX 10.1



  • Danke Dir Rapso, das wird Bettlektüre! 😃



  • Eine Frage hätte ich noch...
    Warum zum Teufel benutzt D3D zur Beschreibung von Eingabetypen von Shadern die DXGI-Farbtypen? Mir stellen sich irgendwie die Fußnägel auf, wenn ich einen 2-Komponentenvektor durch DXGI_R32G32_FLOAT beschreibe...


  • Mod

    zur einheitlichkeit, verschiedene datentypen fuer ein und dasselbe sind irgendwie redundant.



  • Ich bin vielleicht einfach zu pedantisch für solche Abkürzungen. Jetzt stellt sich ja die Frage, ob DXGI_B32G32R32_FLOAT dafür sorgt, dass die Vektoren "geflippt" werden, bevor sie an den Shader gelangen usw... Oder ob man so auch gleich die Farbumrechnungen zwischen den Farbräumen erledigt bekommt und ob sich das mit SV_POSITION-Semantiken verträgt... Naja, ich hab mir jetzt einfach meine enums drumgebastelt, ist ja keine Aufregung wert 😃


  • Mod

    Decimad schrieb:

    Ich bin vielleicht einfach zu pedantisch für solche Abkürzungen.

    dem wird wohl so sein, aber ist eine typische programmierer krankheit 😉
    wenn man es geschaft hat zu akzeptieren, dass es viele loesungen gibt und keine 'die richtige' ist, hat man schonmal einen grossen schritt geleistet aus dem junior dasein herauszukommen, zumindestens in der firma in der ich arbeite.
    (sonst haette jeder programmierer seine eigene style guide, lol).

    Jetzt stellt sich ja die Frage, ob DXGI_B32G32R32_FLOAT dafür sorgt, dass die Vektoren "geflippt" werden, bevor sie an den Shader gelangen usw... Oder ob man so auch gleich die Farbumrechnungen zwischen den Farbräumen erledigt bekommt und ob sich das mit SV_POSITION-Semantiken verträgt...

    es ist eine deklaration, sie deklariert wie du die daten hinlegst, da wird nichts geflippt.

    Naja, ich hab mir jetzt einfach meine enums drumgebastelt, ist ja keine Aufregung wert 😃

    so jung und unbedarft, erfrischend sowas immer wieder zu sehen :).



  • Ich würde ja nix mehr mit DirectX und Windows only anfangen. Immer weniger Leute nutzen und spielen nur auf einem Microsoftsystem und das wird auch noch weiter zunehmen. OpenGL funktioniert wenigstens überall.



  • Ich brauche länger, das funktionierende Drumherum zu erstellen, als es kosten wird, das ganze auf OpenGL umzufrickeln, denke ich. Und im Moment erwarte ich für mein Zielsystem eine bessere Direct3D-Treiberqualität, außerdem hat VS echt coole eingebaute Debug-Möglichkeiten zur Einarbeitung.



  • useOGL schrieb:

    Ich würde ja nix mehr mit DirectX und Windows only anfangen. Immer weniger Leute nutzen und spielen nur auf einem Microsoftsystem und das wird auch noch weiter zunehmen. OpenGL funktioniert wenigstens überall.

    sag ich auch immer ...

    das Performanceproblem von GDI/Direct2D haben andere Leute auch schon festgestellt, da muß man nicht lange suchen

    http://www.google.de/#hl=de&sclient=psy-ab&q=direct2d+gdi+opengl+performance

    ich habe im industriellen Umfeld eine 2D Zeichenbibliothek mit OpenGL 2.1 implementiert. dieses etwas ältere 2.1 läuft auch auf älterer und embedded Hardware stabil (WinXP emb.) und reicht für 2D Zeichenfunktionen eigentlich aus. Anti-Aliasing war bei meiner Implementierung nicht erwünscht, da Messwerte immer pixelgenau angezeigt werden sollen

    bei Interesse kann ich für das 2D OpenGL 2.1 auch ein paar Tipps geben, z.B. wie man am schnellsten einen Kreis füllt

    http://www.humus.name/index.php?page=News&ID=228



  • Danke Dir, das behalte ich im Hinterkopf für den Tesselierer der primitiven Geometrien!
    Im Moment bin ich noch mit der impliziten Darstellung dieser Geometrien beschäftig (also für's Rendern von dynamischen Geometrien). Für statisches kommt dann ein genereller Mesher und für primitive Geometrien dann sowas!

    Ich gehe im Moment davon aus, dass ich alles, was ich so mit Direct3D mache, praktisch 1:1 auch in OpenGL umsetzen kann? Die APIs bestehen doch jetzt eigentlich nur noch aus Ressourcen-Puffern, bissl deklarativem Anteil und dann den Shadern?



  • der Funktionsumfang von Direct3D und OpenGL ist sehr ähnlich. wenn man aber mal eine gewisse Codebasis hat, kann man schlecht auf die andere Seite wechseln

    bei dyn. Geometrien mußt du zunächst mal überlegen, ob du das auf der CPU oder auf der GPU rechnen möchtest. in einem Shader kann man das z.B. mit Texturkoordinaten ohne Textur machen

    We use a shader program to determine if pixels are on the inside or outside of a closed region. Before getting to this shader, we must assign [u v] coordinates to the vertices of the triangles that contain curves. An example is shown in Figure 25-2. When these triangles are rendered under an arbitrary 3D projective transform, the GPU will perform perspective-correct interpolation of these coordinates and provide the resulting [uv] values to a pixel shader program. Instead of looking up a color value as in texture mapping, we use the [u v] coordinate to evaluate a procedural texture.

    http://http.developer.nvidia.com/GPUGems3/gpugems3_ch25.html


Log in to reply