DirectX/Direct3D - Bild(er) darstellen

  • VB.NET

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von jvbsl.

    DirectX/Direct3D - Bild(er) darstellen

    Hallo Community!

    Habe mich vor ca. 4 Tagen an die Arbeit gemacht, mein neuestes Projekt (ein recht komplexes Spiel) neu zu schreiben und via DirectX rendern zu lassen, da GDI dazu viel zu CPU-lastig ist.
    Ich habe mir dazu einige Online-Tutorials durchgelesen, soweit auch alles verstanden und mein Grundgerüst für das Programm steht schon. Das ganze DirectX-Gefummel habe ich in eine eigene Klasse gepackt, um die Übersicht zu wahren und ich kann auch schon die Hintergrundfarbe des Fensters, in dem ich arbeite, via DirectX ändern.
    Mein Spiel benötigt das Rendern vieler Bitmaps in kurzer Zeit und wird nur in 2D dargestellt - und so frage ich mich:
    - Wie zur Hölle kann ich mit DirectX und Direct3D nun auf meiner Form Bitmaps darstellen?

    Habe dazu auch schon Google, Microsoft und das Board durchforstet und bin auf zwei Ergebnisse gekommen:
    - Die Verwendung von DirectDraw...
    - Ich habe keinen blassen Schimmer, wie ich dort dynamisch mit den Surfaces für mehrere Hundert Bitmaps in der Sekunde arbeiten kann - Außerdem habe ich gelesen, dass DirectDraw wohl in kommenden DX-Versionen nicht mehr unterstützt wird(?).

    - Die Verwendung der Helferklasse "Sprite"
    - Wenn ich versuche, in einer Klasse (die Verweis auf DirectX und Direct3D hat) ein Sprite-Objekt mit "Dim tSprite As New Sprite" zu deklarieren, wird mir angezeigt, dass diese Klasse nicht vorhanden sei...

    Ich bin für jede Antwort oder gar Hilfe dankbar! Verzweifle langsam an DirectX :/

    MfG,
    X-Zat / Momo
    Wird ja wohl ManagedDirectX sein...
    Alles was du in DirectDraw machen kannst, kann man auch direkt in Direct3D machen, welches - frag mich nicht warum - schneller ist als DirectDraw...

    Die Sprite-Klasse ist genau das richtige für dich, nun die Frage:
    Hast du Microsoft.DirectX.Direct3DX hinzugefügt(in der neusten Version und keine Alte)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Also ich habe nun Verweise auf:


    Microsoft.DirectX
    Microsoft.DirectX.Direct3D
    Microsoft.DirectX.Direct3DX


    Und Import-Anweisungen:


    Imports Microsoft.DirectX
    Imports Microsoft.DirectX.Direct3D
    Imports Microsoft.DirectX.Direct3D.D3DX

    Nun kann ich zwar Sprites erstellen, aber es stellen sich noch zwei Fragen:

    1) Wie weise ich Sprites eine Bitmap/Texture zu? Habe die Tage mal etwas gelesen vonwegen "TextureLoader" - Hat das etwas damit zu tun?
    2) Wie rendere ich nun die Sprites?

    Ich sollte öfters in den Objektkatalog schauen^^ Dort steht nämlich etwas interessantes zu der Draw-Methode der Klasse Sprite:

    - Ich benötige eine Texture alá DirectX. Da werde ich mich mal über TextureLoader schlau machen, wie ich aus Ressourcen bzw. Bitmap-Objekten eine Textur erstelle ;)...
    - Ich muss "center" und "position" als Vektoren angeben... Was sind bitte Vektoren? Kann man einen Vektor etwa mit einem Rectangle vergleichen? Oder wie muss man da weiterdenken?
    Spoiler anzeigen
    Ich sollte auch öfter bei Wikipedia vorbeischauen... Und erst recht, bevor ich etwas poste... *Asche auf's Haupt* - Wikipedia sagt, dass ein Vektor im Sinne der Geometrie eine Parallelverschiebung darstellt. Nur warum benötige ich bei DirectX eine Parallelverschiebung? Weil's im Dreidimensionalen Raum abspielt? Da ich auf 2D setze, muss ich prinzipiell nur auf die X-und Y-Koordinaten Acht geben, da die Z-Koordinate die Tiefe darstellt, oder? *Fragen über Fragen*

    - Außerdem wird "color" als Integer benötigt. Warum, wenn ich doch eine Bitmap habe?

    Vielen dank schonmal für die Antworten!
    @ jvbsl: Hast mich schon ein ganzes Stück weiter gebracht!
    @YaPh1|: ich möchte so wenig wie möglich mit externen Erweiterungen arbeiten, da ich durch dieses Projekt möglichst viel über DirectX lernen möchte - Wenn's aber nicht klappen sollte, schau ich mir die SlimDX-Lib einmal genauer an!

    MfG,
    X-Zat / Momo

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „X-Zat“ ()

    richtig nur X und Y Verschiebung...
    Der Vektor ist einfach eine Richtungsangabe, welche du hier oft aber auch als einfache Koordinaten betrachten kannst...

    DeineFarbe.ToArgb() liefert dir einen Integerwert, welchen du da übergeben kannst(im Normalfall wars meines Wissens 0 für Transparent), mit dieser Farbe kannst du das Bild sozusagen einfärben, wobei es durch Rot dann einen Rotstich erhält usw...

    SlimDX ist ebenso ein Wrapper wie ManagedDirectX welches du hier verwendest, mit dem Unterschied, dass MDX von Microsoft ist...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Superb! Habe es nun so in der Render-Routine des Devices geschrieben und es funktioniert einwandfrei!

    VB.NET-Quellcode

    1. Dim tSprite As New Sprite(mDxDevice)
    2. Dim tTexture As New Texture(mDxDevice, My.Resources.earth, Usage.SoftwareProcessing, Pool.Managed)
    3. tSprite.Begin(SpriteFlags.None)
    4. 'tSprite.Draw(tTexture, New Vector3(0, 0, 0), New Vector3(100, 100, 0), 16777215) 'Ein Test für den 3-dimensionalen Raum
    5. For i = 0 To 800 / 16
    6. For j = 0 To 600 / 16
    7. tSprite.Draw2D(tTexture, New Point(0, 0), 0, New Point(i * 16, j * 16), Color.Transparent.ToArgb) 'Hat sich als leichter herausgestellt ;)
    8. Next
    9. Next
    10. tSprite.End()
    11. tSprite.Dispose()
    12. tTexture.Dispose()


    Dies wird gefolgt vom Ende der Szene und Präsentieren der Szene.

    Ein Gefummel war das mit "tSprite.Begin(SpriteFlags.None)" - Hatte zuerst unwissend "AlphaBlending" eingestellt und hab mich eine halbe Stunde darüber gewundert, warum nichts angezeigt wurde...

    Ich erreiche folgende Werte bei den 2000 gerenderten Objekten (á 16x16 Pixel, alle 10 MS wird gerendert):
    CPU-Auslastung: 5-13%
    RAM: 28-29MB
    Abgesehen vom RAM ist DirectX hier wohl wirklich um einiges schneller als GDI. Bei GDI hatte ich bei 1024 Objekten eine CPU-Auslastung von >40%, obwohl die Zeichenroutine sehr ordentlich war...

    Nun ja, es scheint alles wunderbarst zu funzen :D Euch beiden noch ein dickes Dankeschön und ich denke wir sind fertig hier!
    Bilder
    • PM-DX.PNG

      49,05 kB, 806×627, 228 mal angesehen
    das kann man noch verbessern und zwar sicherlich um einiges...
    Das Sprite erstellst du direkt zu Beginn nachdem erstellen der Device, dort lädst du auch die Textur, diese sind nun Globale oder Private Variablen, auf welche du in der Render-Routine zugreifst(aber nicht disposen)...

    Außerdem kannst du AlphaBlending drinne lassen, dann musst du aber wohl Color.White.ToArgb angeben statt Transparent(war mir da halt nicht mehr so sicher)...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Sicher wird das verbessert ;) Ich wollte erstmal herausfinden, wie ich überhaupt Grafiken mit DirectX darstellen lassen kann, um dann meine GDI-"Engine" darauf umzuschreiben.
    Nur hätte ich da noch eine Frage bzgl. der Perfomance:
    Ist es performant und klug, ein einziges Sprite-Objekt global zu deklarieren (wie du sagtest) und in einer Auflistung angepasster Klassen einzelne Texture-Objekte als Properties zu speichern, um diese dann beim Rendern abzurufen und mit dem Sprite-Objekt darzustellen? Der objektorientierte Programmierer in mir schreit bei diesem Gedanken vor Begeisterung auf
    .
    Wenn es so einfach ginge, müsste ich nichteinmal mehr große Änderungen an meiner auf GDI basierenden Engine vornehmen... Ansonsten wird's noch etwas schwieriger.
    Ok, so wie ich deinen letzten Post verstanden habe, meintest du wohl genau das... Ja, ich sollte definitiv mehr nachdenken...


    MfG,
    X-Zat / Momo

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „X-Zat“ ()

    ja, das hab ich oben jetzt nicht gemeint, weil es sich ja zuerst um eine Textur handelte, aber dies wäre der nächste Schritt und natürlich nur einmal Sprite.Begin und End und dazwischen alle Texturen zeichnen lassen ;)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Werde ich mal ausprobieren ;)

    Und wenn ich nun eine Art "Beleuchtung" einfügen möchte, wie im Beispiel im Anhang, kann ich auch einfach das Bild mittels Integer-Wert der Farbe einfärben, oder? Prinzipiell müsste ich dann ja nur einen Grauton (irgendwas mit den selben Werten für R, G und B und definiertem Alpha-Wert) oder eine transparente Abstufung von Schwarz (Alpha, 255, 255, 255) drüber legen.
    Oder gibt's einen leichteren Weg als >2000 Objekte bei Änderung eines Elementes auf "manuelle" Beleuchtung zu prüfen? Könnte man vllt. eine Art Lichtquelle definieren, die umliegende Sprites beleuchtet?

    MfG,
    X-Zat / Momo
    Bilder
    • Beleuchtung.PNG

      6,6 kB, 313×365, 214 mal angesehen
    Lichtquellen gibt es meines Wissens nicht für Sprites(könntest ja noch flächen machen...xD) - aber solche Lichtquellen würden wohl auch nicht den von dir gewünschten Effekt erzielen...
    Das heißt so viel wie selber machen:
    Die Transparenz eines Objekts änderst du so Color.FromArgb(Alphawert,255,255,255), Alphawert natürlich zwischen 0 und 255...
    Der Farbwert ändert sich dann nicht, sondern nur die Transparenz(was für uns natürlich den Farbwert ändert^^)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---