Seite 1 von 1
(gelöst)[D3D 9] Screenshot der Anwendung machen
Verfasst: 28.01.2013, 19:34
von Krishty
Hi,
Ich möchte innerhalb meines Programms einen Schnappschuss des Bildes machen, das just gezeichnet wurde. Wie mache ich das am besten? (Das Antialiasing soll nicht leiden; und sowohl Vollbild als auch Fenstermodus sollen funktionieren!)
Soweit ich das sehe, ist das viel Gefrickel mit GetBackBuffer() und Hin- und Herkopieren. Einfacher ist es mit GetFrontBufferData(), aber da bekomme ich einen Schnappschuss des kompletten Desktops und muss mein Fenster darin erstmal finden (und ich denke, falls es verdeckt ist, wird die Verdeckung mit auf dem Bild landen).
Wie macht man es richtig / falsch?
Gruß
Re: [D3D 9] Screenshot der Anwendung machen
Verfasst: 29.01.2013, 12:06
von dot
Ich würde sagen, das hängt konkret von deiner Renderpipeline ab. Evtl. hast du den Frame sowieso schon in einem Buffer, den du einfach kopieren könntest oder evtl. könntest du einfach das Postprocessing in einen anderen Buffer umleiten? Ansonsten würd ich GetBackBuffer() verwenden; dass das mit dem Herumkopieren bei GPUs nunmal eine fact of life ist, is dir klar, denk ich... ;)
Re: [D3D 9] Screenshot der Anwendung machen
Verfasst: 29.01.2013, 12:50
von Schrompf
Ich mach das über GetBackBuffer(). Allerdings noch DX9, und es ist mir manchmal schon passiert, dass meine Screenshots dann einheitlich lila oder grün waren, also die D3D-DebugRuntime-Leerfarben. Ist mir aber schon lange nicht mehr begegnet, vielleicht 2007 das letzte Mal. Vielleicht war es nur eine Treiberungenauigkeit.
Zu AntiAliasing kann ich Dir da aber keine Informationen geben. Aber ich vermute, die Details dazu sähen bei DX11 eh anders aus.
Re: [D3D 9] Screenshot der Anwendung machen
Verfasst: 29.01.2013, 13:06
von dot
Schrompf hat geschrieben:Ich mach das über GetBackBuffer(). Allerdings noch DX9, und es ist mir manchmal schon passiert, dass meine Screenshots dann einheitlich lila oder grün waren, also die D3D-DebugRuntime-Leerfarben.
Kanns sein, dass du die Screenshots damals einfach nach dem Present() gemacht hast? ;)
Re: [D3D 9] Screenshot der Anwendung machen
Verfasst: 29.01.2013, 13:13
von Schrompf
Die Idee ist gut, aber: nein :-) Es ist statischer Code, der schon seit ~2004 nicht mehr verändert wurde. Und der halt nur aller x Monate mal benutzt wurde. Und irgendwann zwischendurch gab es mal ein paar Bilder, die einfarbig lila/grün rauskamen.
[edit] Vielleicht kommt das auch, wenn man GetBackBuffer() während invalidem Device macht?
Re: [D3D 9] Screenshot der Anwendung machen
Verfasst: 29.01.2013, 13:15
von dot
Schrompf hat geschrieben:[edit] Vielleicht kommt das auch, wenn man GetBackBuffer() während invalidem Device macht?
gut möglich^^
Re: [D3D 9] Screenshot der Anwendung machen
Verfasst: 29.01.2013, 18:11
von Krishty
Nein; ich nutze kein Post Processing.
Unterscheidet die Dokumentation zwischen Screen Shot und einem Speichern des Back Buffers? Oder ist AA wirklich nur damit möglich? Hat damit einer Erfahrungen?
Der offensichtliche Nachteil von
GetFrontBufferData() ist nämlich, dass ich einen Schnappschuss des kompletten Desktops kriege. Verdeckt im Augenblick des Speicherns ein anderes Fenster meine Anwendung, ist eben
das auf dem gespeicherten Bild …
Re: [D3D 9] Screenshot der Anwendung machen
Verfasst: 29.01.2013, 18:23
von dot
Hast du einen multisampled BackBuffer? Falls ja, dann eben den Inhalt per StretchRect() kopieren, das sollte auf jeden Fall resolven. Alles andere würd mich zumindest extrem wundern...
Re: [D3D 9] Screenshot der Anwendung machen
Verfasst: 29.01.2013, 18:57
von Krishty
Direct3D9: (ERROR) :If the destination surface is an offscreen plain surface, the source must also be an offscreen plain. StretchRect failed
Wie muss ich das Ziel denn sonst anlegen? Sonst sehe ich nur CreateDepthStencilSurface(), und das kann es ja schlecht sein …
Re: [D3D 9] Screenshot der Anwendung machen
Verfasst: 29.01.2013, 19:28
von dot
Versuchs mal mit Level 0 einer Texture statt einer rohen Surface.
Re: [D3D 9] Screenshot der Anwendung machen
Verfasst: 29.01.2013, 19:39
von Krishty
Ich habe es dank der Katze!
Aaaaaaaalso:
- Via CreateRenderTarget() eine temporäre Render-Target-Textur anlegen (ohne AA und in dem Format, das man haben will). Das ist das einzige, wo StretchRect() den Back Buffer reinkopieren kann.
- Via StretchRect() den Back Buffer in das temporäre Render Target kopieren. Dabei wird das Antialiasing aufgelöst.
- Via CreateOffscreenPlainSurface() einen Systemspeicherpuffer anlegen. Muss unbedingt im D3DPOOL_SYSTEMMEM liegen, weil GetRenderTargetData() nur dorthin kopieren kann; und dasselbe Format haben wie das temporäre Render Target.
- Via GetRenderTargetData() das temporäre Render Target in den Systemspeicherpuffer kopieren.
- Lock() benutzen, um auf die Daten zuzugreifen.
War doch ganz einfach! Ich gehe jetzt heulen.