Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi DirectX Textur aus TBitmap laden (https://www.delphipraxis.net/26789-directx-textur-aus-tbitmap-laden.html)

Reddog 29. Jul 2004 12:58


DirectX Textur aus TBitmap laden
 
Hallo,

weiß jemand, wie man in DirectX eine Textur aus einer TBitmap laden kann?
In meinem konkreten Fall lade ich ein Streifen, der einzelne Frames der Animation enthält von der Festplatte, zerschneide ihn dann in einzelne Frames und möchte die jetzt in DirectX als Texturen laden. Bis jetzt mach ich das auf eine seltsame Art und Weise, indem ich die Frames einzeln in eine temporäre Datei speichere und dann in eine Textur lade. Das ist aber schon ein "Umweg", es geht bestimmt irgendwie anders.

Danke,
Reddog.

igel457 10. Nov 2006 16:13

Re: DirectX Textur aus TBitmap laden
 
Auch wenn dieser Thread schon ein wenig älter ist, hole ich ihn nochmal aus der Versenkung... Ich habe nämlich das selbe Problem.

Und zwar möchte ich ein TBitmap direkt in eine Textur laden.
Bisher versuche ich dies so:

Delphi-Quellcode:
function LoadTextureFromBitmap(Appl:TAndorraApplication;ABitmap:Pointer):TAndorraTexture;
var Texture:IDirect3DTexture9;
    Format,size:cardinal;
    Cursor: pWord;
    d3dlr: TD3DLocked_Rect;
begin
  result := nil;
  with TAndorraApplicationItem(Appl) do
  begin
    with TBitmap(ABitmap) do
    begin

      case PixelFormat of
        pf16bit: begin Size := 2; Format := D3DFMT_R5G6B5; end;
        pf24bit: begin Size := 3; Format := D3DFMT_R8G8B8; end;
        pf32bit: begin Size := 4; Format := D3DFMT_A8R8G8B8 end;
      end;

      if D3DXCreateTexture(Direct3D9Device, Width, Height,0, 0, Format, D3DPOOL_MANAGED, Texture) = D3D_OK then
      begin
        Texture.LockRect(0, d3dlr, nil, 0);
        Cursor := d3dlr.Bits;
       
        //Hier will ich den Bitmapspeicher in den Texturspeicher kopieren, leider gibt es eine AV
        Move(ScanLine[0]^,Cursor,Size*AWidth*AHeight);

        Texture.UnlockRect(0);
      end;

      IDirect3DTexture9(Result) := Texture;
    end;
  end;
end;
Leider gibt es (wie im Quellcode verzeichnet) eine AV beim kopieren des Bitmapspeichers in den Texturspeicher.
Bekomme ich mit "Scanline[0]" überhaupt den Pointer auf die erste Speicherstelle des Bitmaps? Ist meine Berrechnung von "Size" richtig? Mache ich sonst was falsch?

Danke für eure Antworten!
Andreas alias Igel457

[Edit]Einen "kleinen" Fehler selbst gefunden und im Code korrigiert...[/Edit]

igel457 10. Nov 2006 19:17

Re: DirectX Textur aus TBitmap laden
 
Also ich habe es geschafft. Ist zwar nicht so einfach, wie ich mir es vorgestellt habe, aber so geht es:
Delphi-Quellcode:
function LoadTextureFromBitmap(Appl:TAndorraApplication;ABitmap:Pointer;AColorDepth:byte):TAndorraTexture;
var Texture:IDirect3DTexture9;
    Format:cardinal;
    d3dlr: TD3DLocked_Rect;
    Cursor32: pLongWord;
    Cursor16: pWord;
    BitCur: PRGBRec;
    x,y:integer;

    //Convert a 8 Bit Color to a 4 Bit Color
    function R8ToR4(r:byte):byte;
    begin
      result := (r div 16);
    end;

    //Converts a R8G8B8 Value to a A4R4G4B4
    function RGBTo16Bit(r,g,b:byte):Word;
    begin
      Result := (R8ToR4(255) shl 12) or (R8ToR4(r) shl 8)
                            or (R8ToR4(g) shl 4)
                            or R8ToR4(b);
    end;
begin
  //Set Result to nil
  result := nil;

  with TAndorraApplicationItem(Appl) do
  begin
    with TBitmap(ABitmap) do
    begin

      //Set the Textures Pixel Format
      case AColorDepth of
        16: Format := D3DFMT_A4R4G4B4;
        24: Format := D3DFMT_A8R8G8B8;
        32: Format := D3DFMT_A8R8G8B8;
      else
        Format := D3DFMT_A8R8G8B8;
      end;

      //Set the Pixel Format of the Bitmap to 24 Bit
      PixelFormat := pf24Bit;

      //Create the Texture
      if D3DXCreateTexture(Direct3D9Device, Width, Height, 0, 0, Format, D3DPOOL_MANAGED, Texture) = D3D_OK then
      begin
        Texture.LockRect(0, d3dlr, nil, 0);

        if Format = D3DFMT_A8R8G8B8 then
        begin
          Cursor32 := d3dlr.Bits;

          for y := 0 to Height-1 do
          begin
            BitCur := Scanline[y];
            for x := 0 to Width-1 do
            begin
              Cursor32^ := D3DColor_ARGB(255,BitCur^.b,BitCur^.g,BitCur^.r);
              inc(BitCur);
              inc(Cursor32);
            end;
          end;
        end;
        if Format = D3DFMT_A4R4G4B4 then
        begin
          Cursor16 := d3dlr.Bits;
          for y := 0 to Height-1 do
          begin
            BitCur := Scanline[y];
            for x := 0 to Width-1 do
            begin
              Cursor16^ := RGBTo16Bit(BitCur^.b,BitCur^.g,BitCur^.r);
              inc(BitCur);
              inc(Cursor16);
            end;
          end;
        end;
      end;

      Texture.UnlockRect(0);
      IDirect3DTexture9(Result) := Texture;
    end;
  end;
end;
Einige werden jetzt vielleicht fragen, warum ich AColorDepth als Parameter übergebe, wenn ich es doch aus dem PixelFormat auslesen kann.
Die Antwort ist einfach: Bei mir hat das interne Konvertieren von 24 zu 16 Bit Bildern nicht richtig geklappt (Die Farben waren total verfälscht...), deshalb kann man die Farbtiefe übergeben um dennoch 16 Bit nutzen zu können...

Ich hoffe, dass noch andere den Code vielleicht nützlich finden könnten.

Wenn jemand eine kürzere Lösung hat, neheme ich diese auch gerne entgegen...

[Edit]Ein paar Schlechtschreibfehler entfernt...[/Edit]


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:10 Uhr.

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