Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Text in DirectX Spiel anzeigen (https://www.delphipraxis.net/87397-text-directx-spiel-anzeigen.html)

StefanG 28. Feb 2007 08:27


Text in DirectX Spiel anzeigen
 
Hallo zusammen,

ich habe folgendes Problem. Ich will in einem Spiel einen bestimmten Text anzeigen. Das Spiel nutzt DirectX und wenn ich einfach den Text mit GetDC und SetText setze, dann flackert die Schrift fürchterlich.

Wie man aber an Programmen wie Teamspeakoverlay oder Fraps sieht, geht das auch anders. Beim Nachforschen habe ich erfahren, dass man dafür API Hooks verwenden muss um über DirectX Methoden, den Text anzeigen zu lassen.

Weitere Suche führte mich zu der Funktion DrawText (in ID3DXFont). Die geeignete stelle, diesen Text zu setzen sollte wohl die DirectX-Funktion "Present" sein. Hier sage ich mal gleich, dass ich mich bis gestern noch garnicht mit DirectX oder OGL beschäftigt habe.

Nun denn, da Present keine Funktion ist, die aus der Dll exportiert wird, sondern ein Teil des IDirect3DDevice Interfaces ist, kann man die Adresse nicht einfach mit GetProcAddress bestimmen, man musste das Device haben. Also habe ich erst die Funktion Direct3DCreate9 gehookt um das IDirect3D9 Interface zu bekommen und damit CreateDevice9 hooken zu können.

Anschließend konnte ich mit dem erhaltenen IDirect3DDevice9 die Funktion Present hooken.
Soweit, so gut. Die Hooks scheinen soweit alle zu funktionieren. Zum Testen habe ich das Programm dxdiag verwendet.
Dass der Hook funktioniert merke ich daran, dass das Programm 1) nicht abstürzt, 2) keinen Bluescreen erzeugt ;-) und 3) von mir gesetzte MessageBoxen in den einzelnen Funktionen aufgerufen werden.

Das Problem liegt jetzt aber im Anzeigen von Text. Ich bin folgendermaßen vorgegangen :

In der Funktion CreateDevice9 erstelle ich den Font vom Typ ID3DXFont.

Delphi-Quellcode:
function CreateDevice9Callback(self, adapter, devType, wnd, flags, params, device: Pointer) : dword; stdcall;
begin
  font := nil;
  result := CreateDevice9Next(self, adapter, devType, wnd, flags, params, device);
  if font = nil then
  begin
    D3DXCreateFont(IDirect3DDevice9(device^),
                   20,
                   20,
                   0,
                   1,
                   false,
                   ANSI_CHARSET,
                   OUT_DEFAULT_PRECIS,
                   DEFAULT_QUALITY,
                   DEFAULT_PITCH,
                   'Arial',
                   font);
    myColor := D3DCOLOR_RGBA(255,0,0,255);
    font.PreloadCharacters(0,255);
  end;
  if result = 0 then begin
    if @PresentNext = nil then
    begin
      HookCode(GetInterfaceMethod(device^, 17), @PresentCallback, @PresentNext)
    end else
      RenewHook(@PresentNext);
  end;
end;
Die übergebene Farbe wird in einer Globalen Variable gespeichert....genauso wie eben der Font
Setzen will ich den Text jetzt in meiner Present Callback funktion :

Delphi-Quellcode:
function PresentCallback(self : Pointer; const SourceRect, DestRect : PRect; const DestWindowOverride : HWND; DirtyRegion : PRgnData) : HResult; stdcall;
begin
  messageBox(0,'Present','',MB_OK);
  result := PresentNext(self,SourceRect,DestRect,DestWindowOverride,DirtyRegion);
  ShowText(50,50,'test',myColor);
end;
die MessageBox wird ausgeführt. ShowText sieht folgendermaßen aus :

Delphi-Quellcode:
procedure ShowText(x,y: Integer; s: String; col: TD3DColor);
var
  rect : TRect;
begin
  messageBox(0,'ShowText','',MB_OK);
  rect.Top := y; rect.Left := x;
  rect.Bottom := y+1; rect.Right := x+1;
  if @font <> nil then
    font.DrawTextA(nil,PChar(s),Length(s),rect,DT_NOCLIP,myColor);
end;
Es gibt keinerlei Fehler und der Drehende Würfel (beim dxdiag test) wird angezeigt, aber ich sehe keinen Text
Ich habe jetzt schon viele Foren damit zur Verzweiflung getrieben, also hoffe ich einfach mal dass mir jemand von hier soweit folgen konnte und hoffentlich einen Rat hat, woran das liegen könnte.

JasonDX 28. Feb 2007 11:21

Re: Text in DirectX Spiel anzeigen
 
Hi

Mehrere Dinge, die mir beim Durchlesen aufgefallen sind:
  • Nach Present den Text zu zeichnen ist schlecht. Bringt nix, weil der BackBuffer anschliessend hoechstwahrscheinlich eh geloescht wird.
  • Render-Befehle muessen zwischen einen BeginScene-EndScene-Block stehen. Also entweder EndScene statt Present hooken oder nen neuen Block aufmachen (IDirect3DDevice9::BeginScene), Text zeichnen, und anschliessend wieder schliessen (EndScene). Bei beidem kanns Probleme geben:
    • EndScene Hooken: Es koennen mehrere BeginScene/EndScenes pro Frame aufgerufen werden. Es wird zwar davon abgeraten, aber das ist bei weiten keine Garantie dass dem so ist.
    • Present hooken: Wenn verschiedene Backbuffer verwendet werden, wird Present mehrmals pro Frame aufgerufen -> Du zeichnest den Text mehrmals -> doof
  • Das Rect beim Aufruf von DrawText. Du initialisierst es Folgendermassen:
    Delphi-Quellcode:
    rect.Top := y;
    rect.Left := x;
    rect.Bottom := y+1;
    rect.Right := x+1;
    Dein Text wird jetzt auf genau 1 Pixel gezeichnet. Da koennts schwer werden, einen Text zu finden :zwinker:
greetz
Mike

StefanG 28. Feb 2007 11:38

Re: Text in DirectX Spiel anzeigen
 
Hi Mike,

super Tipps danke

ich habe in der PresentCallback funktion einfach das ShowText vor das PresentNext gesetzt und das Rect ein wenig größer gemacht und siehe da, ich habe Text gesehen ;-) War auch wirklich ein blöder Fehler.

Jetzt habe ich aber das Problem, dass ich das bei einem Spiel ausprobieren wollte (in meinem Fall war es zu testzwecken "Wings of Fury" - die Demo kann man bei Chip.de runterladen)

Doch dort Stürzt das Spiel gleich beim Start mit einer AV ab.
Das liegt irgendwie am Aufruf von ShowText bzw DrawTextA, denn wenn ich das auskommentiere, läuft das Spiel fehlerfrei.

Hast du einen Tipp was man da machen kann?

JasonDX 28. Feb 2007 11:53

Re: Text in DirectX Spiel anzeigen
 
Zitat:

Zitat von StefanG
ich habe in der PresentCallback funktion einfach das ShowText vor das PresentNext gesetzt
[...]
Doch dort Stürzt das Spiel gleich beim Start mit einer AV ab.
Das liegt irgendwie am Aufruf von ShowText bzw DrawTextA, denn wenn ich das auskommentiere, läuft das Spiel fehlerfrei.

Hast du einen Tipp was man da machen kann?

Du musst DrawText vor dem Call von EndScene aufrufen, siehe Doku:
Im ersten Tutorial im MSDN steht
The IDirect3DDevice9::BeginScene and IDirect3DDevice9::EndScene methods signal to the system when rendering is beginning or is complete. You can call rendering methods only between calls to these methods.
oder meinen vorherigen Beitrag:

Zitat:

Zitat von JasonDX
  • Render-Befehle muessen zwischen einen BeginScene-EndScene-Block stehen. Also entweder EndScene statt Present hooken oder nen neuen Block aufmachen (IDirect3DDevice9::BeginScene), Text zeichnen, und anschliessend wieder schliessen (EndScene). Bei beidem kanns Probleme geben:
    • EndScene Hooken: Es koennen mehrere BeginScene/EndScenes pro Frame aufgerufen werden. Es wird zwar davon abgeraten, aber das ist bei weiten keine Garantie dass dem so ist.
    • Present hooken: Wenn verschiedene Backbuffer verwendet werden, wird Present mehrmals pro Frame aufgerufen -> Du zeichnest den Text mehrmals -> doof

;)

greetz
Mike

StefanG 28. Feb 2007 11:57

Re: Text in DirectX Spiel anzeigen
 
jo wie oben schon geschrieben, hatte ich das ShowText vor den Aufruf von Present gelegt.
Ich habe das ganze mal so umgebaut, dass D3DXCreateFont bei jedem Aufruf von ShowText neu aufgerufen wird. So geht es jetzt, aber ich weiss nicht wirklich warum...

Evtl wird zwischendurch ein neues Device erzeugt, wobei ich das ja mitbekommen müsste, denn diese Funktion habe ich ebenfalls gehookt.

Naja, die Frage ist jetzt jedenfalls beantwortet, vielen Dank nochmal :)

PS : oder evtl noch ne kurze Frage. Wie kann ich die Schriftgröße und Position an die aktuelle Fenstergröße anpassen?

Der_Ventilator 25. Sep 2007 10:40

Re: Text in DirectX Spiel anzeigen
 
Wie man Text in DirectX 3D Spielen anzeigt interessiert mich auch. Kannst du vielleicht nochmal deinen fehlerbereinigten Code posten, mit dem es letztendlich funktioniert hat?

Relicted 25. Sep 2007 11:47

Re: Text in DirectX Spiel anzeigen
 
*mich mal meinem vorredner anschließ*

wäre wirklich mal interessant... gerade für leute die sich nicht unbedingt mit directx befassen wollen wegen einem "einfachen" text zeichnen.

gruß
reli

Der_Ventilator 25. Sep 2007 12:40

Re: Text in DirectX Spiel anzeigen
 
Genau, ich hab jetzt alle Beiträge hier im Forum zu dem Thema gelesen, bin aber nicht so recht weitergekommen, weil das alles sehr kompliziert ist und mein Wissen wohl übersteigt, daher suche ich mehr oder weniger eine Art Komponente, die mir einfach ermöglicht ein beliebiges Canvas/Bitmap in Spiele zu zeichnen.

Das ist natürlich illusorisch, so zu finden, aber vielleicht kreig ichs letztendlich noch noch hin, mich da in die Materie einzuarbeiten :-)

Xcessive_ 27. Nov 2007 06:21

Re: Text in DirectX Spiel anzeigen
 
Hallo,

Ich beschäftige mich momentan auch mit diesem Problem, bin aber leider noch zu keinem Ergebnis gekommen. Jemand eine Idee?

Volle 6. Jan 2008 17:20

Re: Text in DirectX Spiel anzeigen
 
wäre auch sehr daran interessiert!

danke schonmal im vorraus


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:27 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz