Bitmap in Texture kopieren

Für Probleme bezüglich Grafik, Audio, GL, ACS, ...
Antworten
Scotty
Beiträge: 768
Registriert: Mo 4. Mai 2009, 13:24
OS, Lazarus, FPC: Arch Linux, Lazarus 1.3 r44426M FPC 2.6.4
CPU-Target: x86_64-linux-qt/gtk2
Kontaktdaten:

Bitmap in Texture kopieren

Beitrag von Scotty »

Folge ich den Beispielen, kann ich leicht eine Texture auf ein OpenGL-Objekt legen. Dabei wird aber das Bitmap aber aus einer Datei gelesen; ich will es aber zur Laufzeit erzeugen. Weder Bitmap.Canvas.Pixels[x,y] noch das aktuelle Vorgehen liefern mir das richtige Ergebnis. Zum Ausprobieren schiebe ich ein 64x64 großes, rot gefülltes Bitmap in die Funktion (per SaveToFile geprüft), raus kommt Pixel Zufall. Was mache ich falsch?

Code: Alles auswählen

type
 TGlTexture = class
  public
    Width,Height: longint;
    Data        : pbyte;
    destructor Destroy; override;
  end;
 
procedure Bmp2Tex(aBitmap:TBitmap; var aTexture:TglTexture);
type
  TRawImage = packed record
     p:array[0..0] of byte;
   end;
  PRawImage = ^TRawImage;
var x,y:integer;
    t: TLazIntfImage;
    aColor:TFPColor;
begin
  aTexture.Width:=aBitmap.Width;
  aTexture.Height:=aBitmap.Height;
  t:=aBitmap.CreateIntfImage;
 
  GetMem(aTexture.Data,aTexture.Width*aTexture.Height*3);
  for y:=0 to aTexture.Height-1 do
   for x:=0 to aTexture.Width-1 do
   begin
     with PRawImage(aTexture.Data)^ do
     begin
       aColor:=t.Colors[x,y];
       p[y*aTexture.Height+x*3+0]:=aColor.red div 256;//Ergebnis gleich, ob mit oder ohne div 256
       p[y*aTexture.Height+x*3+1]:=aColor.green div 256;
       p[y*aTexture.Height+x*3+2]:=aColor.blue div 256;
     end;
   end;
end;

lrlr
Beiträge: 127
Registriert: Di 3. Nov 2009, 09:48

Re: Bitmap in Texture kopieren

Beitrag von lrlr »

[y*aTexture.Height+x*3+0]

schaut komisch aus

hätte ich eher auf (y*aTexture.Width*3)+x*3 usw. getippt..

Benutzeravatar
theo
Beiträge: 10871
Registriert: Mo 11. Sep 2006, 19:01

Re: Bitmap in Texture kopieren

Beitrag von theo »

Eine TFPColor besteht aus 4 words! D.h. jeder Farbanteil aus 16 bit.

carli
Beiträge: 657
Registriert: Sa 9. Jan 2010, 17:32
OS, Lazarus, FPC: Linux 2.6.x, SVN-Lazarus, FPC 2.4.0-2
CPU-Target: 64Bit

Re: Bitmap in Texture kopieren

Beitrag von carli »

außerdem erzeugt der Code bööööse Memlecks.
Man kann den Speicher übrigens freigeben, sobald die Textur hochgeladen ist.

Scotty
Beiträge: 768
Registriert: Mo 4. Mai 2009, 13:24
OS, Lazarus, FPC: Arch Linux, Lazarus 1.3 r44426M FPC 2.6.4
CPU-Target: x86_64-linux-qt/gtk2
Kontaktdaten:

Re: Bitmap in Texture kopieren

Beitrag von Scotty »

theo hat geschrieben:Eine TFPColor besteht aus 4 words! D.h. jeder Farbanteil aus 16 bit.
Was bedeutet das für mich?
carli hat geschrieben:...außerdem erzeugt der Code bööööse Memlecks.
FreeMem() gibt es natürlich, aber anderswo.

Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1619
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: Bitmap in Texture kopieren

Beitrag von corpsman »

Das stammt aus meiner noch nicht veröffentlichten OpenGLGraphikEngine.pas, evtl hilft es dir ja ein bischen ;)

Code: Alles auswählen

Function TGraphikEngine.LoadGraphik(Const Graphik: TBitmap; name: String; Stretch: TStretchmode = smNone): Integer; overload; // Laden einer Graphik ohne Alphakanal
Var
  OpenGLData: Array Of Array[0..2] Of Byte;
  Data: String;
  b, b2: Tbitmap;
{$IFDEF FPC}
  IntfImg1: TLazIntfImage;
  CurColor: TFPColor;
{$ELSE}
  p: PBGR;
 
{$ENDIF}
  c, j, i: Integer;
  bool: {$IFDEF USE_GL}Byte{$ELSE}Boolean{$ENDIF};
  ow, oh, nw, nh: Integer;
Begin
  Data := LowerCase(name);
  // Graphik bereits geladen
  For i := 0 To high(Fimages) Do
    If Fimages[i].Name = Data Then Begin
      result := Fimages[i].Image;
      exit;
    End;
  // Graphik mus geladen werden
  b := Graphik;
  b.PixelFormat := pf24bit;
{$IFDEF FPC}
  // create the raw image
  IntfImg1 := TLazIntfImage.Create(0, 0);
{$ENDIF}
  nw := b.width;
  nh := b.height;
  ow := b.width;
  oh := b.height;
  Case Stretch Of
    smNone: Begin
      End;
    smStretch: Begin
        nw := GetNextPowerOfTwo(b.width);
        nh := GetNextPowerOfTwo(b.height);
        If (nw <> b.width) Or (nh <> b.height) Then Begin
          b2 := TBitmap.create;
          b2.PixelFormat := pf24bit;
          b2.width := nw;
          b2.height := nh;
          b2.canvas.StretchDraw(rect(0, 0, nw, nh), b);
          b.Width := nw;
          b.height := nh;
          b.canvas.draw(0, 0, b2);
          b2.free;
        End;
      End;
    smClamp: Begin
        nw := GetNextPowerOfTwo(b.width);
        nh := GetNextPowerOfTwo(b.height);
        If (nw <> b.width) Or (nh <> b.height) Then Begin
          b2 := TBitmap.create;
          b2.PixelFormat := pf24bit;
          b2.width := nw;
          b2.height := nh;
          b2.canvas.Draw(0, 0, b);
          b.Width := nw;
          b.height := nh;
          b.canvas.draw(0, 0, b2);
          b2.free;
        End;
      End;
  End;
{$IFDEF FPC}
  // load the raw image from the bitmap handles
  IntfImg1.LoadFromBitmap(B.Handle, B.MaskHandle);
{$ENDIF}
  If IsPowerOfTwo(b.width) And IsPowerOfTwo(b.Height) Then Begin
    // Laden der Graphikdaten
    setlength(opengldata, b.width * b.height);
    c := 0;
    For j := 0 To b.height - 1 Do Begin
{$IFNDEF FPC}
      p := b.ScanLine[j];
{$ENDIF}
      For i := 0 To b.width - 1 Do Begin
{$IFNDEF FPC}
        OpenGLData[c, 0] := p^.r;
        OpenGLData[c, 1] := p^.g;
        OpenGLData[c, 2] := p^.b;
        inc(p);
{$ELSE}
        CurColor := IntfImg1.Colors[i, j];
        OpenGLData[c, 0] := CurColor.Red Div 256;
        OpenGLData[c, 1] := CurColor.green Div 256;
        OpenGLData[c, 2] := CurColor.blue Div 256;
{$ENDIF}
        inc(c);
      End;
    End;
    // Übergeben an OpenGL
    glGenTextures(1, @Result);
    bool := glIsEnabled(GL_TEXTURE_2D);
    If Not (Bool{$IFDEF USE_GL} = 1{$ENDIF}) Then
      glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, result);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexImage2D(GL_TEXTURE_2D, 0, gl_RGB, b.width, b.height, 0, GL_RGB, GL_UNSIGNED_BYTE, @OpenGLData[0]);
    If Not (Bool{$IFDEF USE_GL} = 1{$ENDIF}) Then
      gldisable(GL_TEXTURE_2D);
{$IFDEF FPC}
    IntfImg1.free;
    b := Nil;
{$ENDIF}
    // Übernehmen in die Engine
    setlength(Fimages, high(Fimages) + 2);
    Fimages[high(Fimages)].Image := Result;
    Fimages[high(Fimages)].Name := data;
    Fimages[high(Fimages)].Stretched := stretch;
    Fimages[high(Fimages)].OrigWidth := ow;
    Fimages[high(Fimages)].OrigHeight := oh;
    Fimages[high(Fimages)].StretchedWidth := nw;
    Fimages[high(Fimages)].StretchedHeight := nh;
  End
  Else
    Raise Exception.create('Error Image ' + extractfilename(name) + ' has invalid Width / Height, has to be 2^x.');
End;
--
Just try it

Scotty
Beiträge: 768
Registriert: Mo 4. Mai 2009, 13:24
OS, Lazarus, FPC: Arch Linux, Lazarus 1.3 r44426M FPC 2.6.4
CPU-Target: x86_64-linux-qt/gtk2
Kontaktdaten:

Re: Bitmap in Texture kopieren

Beitrag von Scotty »

Ich glaube, es lag am Blending. Mit glColor4f(1,1,1,1); plus glTexImage2D(GL_TEXTURE_2D,0,3,Width,Height,0,GL_RGB,GL_UNSIGNED_BYTE,Data); sehe ich die Texture jedenfalls. Vielen Dank für Euren Beistand :oops:

Antworten