(gelöst)[D3D 9] Screenshot der Anwendung machen

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Benutzeravatar
Krishty
Establishment
Beiträge: 8350
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

(gelöst)[D3D 9] Screenshot der Anwendung machen

Beitrag 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ß
Zuletzt geändert von Krishty am 29.01.2013, 21:30, insgesamt 1-mal geändert.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
dot
Establishment
Beiträge: 1746
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [D3D 9] Screenshot der Anwendung machen

Beitrag 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... ;)
Benutzeravatar
Schrompf
Moderator
Beiträge: 5161
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas
Wohnort: Dresden
Kontaktdaten:

Re: [D3D 9] Screenshot der Anwendung machen

Beitrag 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.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
dot
Establishment
Beiträge: 1746
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [D3D 9] Screenshot der Anwendung machen

Beitrag 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? ;)
Benutzeravatar
Schrompf
Moderator
Beiträge: 5161
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas
Wohnort: Dresden
Kontaktdaten:

Re: [D3D 9] Screenshot der Anwendung machen

Beitrag 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?
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
dot
Establishment
Beiträge: 1746
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [D3D 9] Screenshot der Anwendung machen

Beitrag von dot »

Schrompf hat geschrieben:[edit] Vielleicht kommt das auch, wenn man GetBackBuffer() während invalidem Device macht?
gut möglich^^
Benutzeravatar
Krishty
Establishment
Beiträge: 8350
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [D3D 9] Screenshot der Anwendung machen

Beitrag von Krishty »

Nein; ich nutze kein Post Processing.
http://msdn.microsoft.com/de-de/library/windows/desktop/bb174388 hat geschrieben:IDirect3DDevice9::GetFrontBufferData method (Windows)
[…]
Remarks
[…]
This method is the only way to capture an antialiased screen shot.
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 …
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
dot
Establishment
Beiträge: 1746
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [D3D 9] Screenshot der Anwendung machen

Beitrag 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...
Benutzeravatar
Krishty
Establishment
Beiträge: 8350
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [D3D 9] Screenshot der Anwendung machen

Beitrag 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 …
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
dot
Establishment
Beiträge: 1746
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [D3D 9] Screenshot der Anwendung machen

Beitrag von dot »

Versuchs mal mit Level 0 einer Texture statt einer rohen Surface.
Benutzeravatar
Krishty
Establishment
Beiträge: 8350
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [D3D 9] Screenshot der Anwendung machen

Beitrag 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.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Antworten