Jak poprawnie załadować bitmapę w OpenGL?

0

witajcie. napisałem sobie grę w Delphi. Jest to prosta platformówka... ludzik chodzi, skacze, strzela wpada do przepaści... są to podwaliny do normalnej gry. Orginał chciał bym napisać w OpenGL. Jak na razie jestem całkiem zielony. Stworzyłem sobie szkielet programu openGL i chciałem wyświetlić teksturę. niestety tekstura (bitmapa) została źle wyświetlona. i pojawiły się schody. Tzn kolory się nie zgadzają... tam gdzie była czerwien jest niebieski kolor,
macie może jakiś pomysł jak dobrze wyświetlić bitmapę w opengl? z w miarę prostym kodem bez dodatków? a może jest tu jakieś miejsce gdzie można zaprezentować swoje dodkonania? jak oni pisali te gry na pegazusa, pozdrawiam

0

OpenGL wymaga dość nietypowego formatu tekstury: obraz powinien być „do góry nogami” (czyli liniami od dołu do góry) oraz kolejność kolorów (RGB) też jest odwrotna niż zazwyczaj się stosuje.

Pokaż kod, jak ładujesz tę teksturę.

macie może jakiś pomysł jak dobrze wyświetlić bitmapę w opengl? z w miarę prostym kodem bez dodatków?
Używając WIC (Windows Imaging Component). Biblioteka wbudowana w Windowsa. Na dzień dobry masz wszystkie potrzebne formaty, w tym .png i .jpg;
tylko do Delphi może być potrzebny unit, bo pewnie nie ma w standardzie.

0

a może jest tu jakieś miejsce gdzie można zaprezentować swoje dodkonania?

Tak, do przedstawiania swoich prac jest przewidziany dział Off-Topic\Oceny i Recenzje;

jak oni pisali te gry na pegazusa

Wolno, w bardzo prymitywnych językach i narzędziach;

@asert - jeżeli masz problem z kodem to go tutaj przedstaw i pokaż co się dzieje po wywołaniu; Do tego zapoznaj się z materiałami tłumaczącymi jak korzystać z OpenGL, jak tworzyć gry itd. - jest tego naprawdę sporo w sieci; Tutaj postuj, jeśli masz z czymś problem, ale nie z brakiem wiedzy czy chęci czytania i uczenia się;

No i popraw tytuł wątku na taki, który w miare sensownie opisywać będzie Twój problem; Wątki z nic nie mówiącym tytułem z reguły szybką zostają usunięte.

0

oto kod

grzyb jest czerwony a wyświetla niebieski albo zielony(bitmapa 24bitowa)

unit frmMain;

interface

uses
  Windows, Messages, Classes, Graphics, Forms, ExtCtrls, Controls,
  StdCtrls, Buttons, OpenGL, gl, Glu, dialogs, SysUtils, textures;

type
  TForm1 = class(TForm)
    Timer2: TTimer;
    Button1: TButton;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure BitBtn1Click(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Timer2Timer(Sender: TObject);
    procedure Button1Click(Sender: TObject);

  private
    DC : HDC;
    UchwytOpenGL : HGLRC;
    procedure Draw;
    procedure SetDCPixelFormat;

  protected

    procedure WMPaint(var Msg: TWMPaint); message WM_PAINT;
  public
  procedure Skok;

  end;

var
  Form1: TForm1;
  Wartosc, Y, WartX: Real;
  Pierwsza: glUint;
  Pion: Real = 0.0;
  Poziom: Real = 0.0;
  a: boolean = True;
  Bitmapa: HBitmap;
  BM: BITMAP;


implementation

{$R *.DFM}


procedure TForm1.BitBtn1Click(Sender: TObject);
begin

while True do
begin

Application.ProcessMessages;
Y := Y + 0.4;
InvalidateRect(Handle, nil, False);

end;

end;

procedure TForm1.Draw;
begin



glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glLoadIdentity;
glTranslatef(WartX-3.5, 0.0 - 1.5, -10.0);
glTranslatef(Poziom,0,0);
glTranslatef(0,Pion,0);


Bitmapa := LoadImage( 0, 'textura.bmp', IMAGE_BITMAP, 200, 200,
LR_CREATEDIBSECTION or LR_DEFAULTSIZE or LR_LOADFROMFILE );

GetObject(Bitmapa, sizeof(BITMAP), @bm );
//glPixelStorei(GL_UNPACK_ALIGNMENT, 24);


 glPixelStorei(GL_PACK_ALIGNMENT, 4); //* Force 4-byte alignment */
  glPixelStorei(GL_PACK_ROW_LENGTH, 0);
  glPixelStorei(GL_PACK_SKIP_ROWS, 0);
  glPixelStorei(GL_PACK_SKIP_PIXELS, 0);


glDrawPixels( BM.bmHeight, BM.bmWidth, GL_RGB, GL_UNSIGNED_BYTE, BM.bmBits );
glFlush();
SwapBuffers(wglGetCurrentDC);

end;
       // Rysuj

procedure TForm1.FormActivate(Sender: TObject);
begin

//showmessage(extractFilePath(Paramstr(0)) + '4.jpg');

glEnable(GL_CULL_FACE);
glEnable(GL_TEXTURE_2D);

LoadTexture(extractFilePath(Paramstr(0)) + '4.jpg', Pierwsza, false);


Form1.WindowState := wsMaximized;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
ExitProcess(0);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin

  DC := GetDC(Handle);
  SetDCPixelFormat;

  UchwytOpenGL := wglCreateContext(DC);
  wglMakeCurrent(DC, UchwytOpenGL);


end;


procedure TForm1.SetDCPixelFormat;
var
  nPixelFormat: Integer;
  pfd: TPixelFormatDescriptor;
begin
//  FillChar(pfd, SizeOf(pfd), 0);

  zeromemory(@pfd,SizeOf(pfd));

  with pfd do begin
    nSize     := sizeof(pfd);
    nVersion  := 1;
    dwFlags   := PFD_DRAW_TO_WINDOW or
                 PFD_SUPPORT_OPENGL or
                 PFD_DOUBLEBUFFER;
    iPixelType:= PFD_TYPE_RGBA;
    cColorBits:= 24;
    cDepthBits:= 32;
    iLayerType:= PFD_MAIN_PLANE;
  end;

  nPixelFormat := ChoosePixelFormat(DC, @pfd);
  SetPixelFormat(DC, nPixelFormat, @pfd);
end;

procedure TForm1.Skok;
var
 I: Integer;

begin
timer2.Enabled := False;
I := 1;

for i := 0 to 10 do
begin
Application.ProcessMessages;
Pion  := Pion + 0.5;

glTranslatef(0,Pion,0);
draw;
end;


for i := 0 to 10 do
begin
Application.ProcessMessages;
Pion  := Pion - 0.5;
glTranslatef(0,Pion,0);
//draw;
InvalidateRect(Handle, nil, False);
end;


timer2.Enabled := True;
end;


procedure TForm1.FormResize(Sender: TObject);
begin
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity;
  gluPerspective(40.0, Width / Height, 1.0, 10.0);
  glViewport(0, 0, Width, Height);
  glMatrixMode(GL_MODELVIEW);
  InvalidateRect(Handle, nil, False);
end;


procedure TForm1.WMPaint(var Msg: TWMPaint);
var
  ps : TPaintStruct;
begin
  BeginPaint(Handle, ps);
  Draw;
  EndPaint(Handle, ps);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  wglMakeCurrent(0, 0);
  wglDeleteContext(UchwytOpenGL);
  ReleaseDC(Handle, DC);
end;

procedure TForm1.Timer2Timer(Sender: TObject);
begin
if getkeystate(vk_up) < 0 then
skok;

If GetKeYState(VK_Left) < 0 then Poziom := poziom - 0.5;
If GetKeYState(VK_Right) < 0 then Poziom := poziom + 0.5;
Draw;


end;


end.


end.


// loadtexture
function LoadTexture(Filename: String; var Texture: GLuint; LoadFromRes : Boolean): Boolean;


function LoadTexture(Filename: String; var Texture : GLuint; LoadFromRes : Boolean) : Boolean;
begin
  if copy(Uppercase(filename), length(filename)-3, 4) = '.BMP' then
    LoadBMPTexture(Filename, Texture, LoadFromRes);
  if copy(Uppercase(filename), length(filename)-3, 4) = '.JPG' then
    LoadJPGTexture(Filename, Texture, LoadFromRes);
  if copy(Uppercase(filename), length(filename)-3, 4) = '.TGA' then
    LoadTGATexture(Filename, Texture, LoadFromRes);
end;

function LoadBMPTexture(Filename: String; var Texture : GLuint; LoadFromResource : Boolean) : Boolean;
var
  FileHeader: BITMAPFILEHEADER;
  InfoHeader: BITMAPINFOHEADER;
  Palette: array of RGBQUAD;
  BitmapFile: THandle;
  BitmapLength: LongWord;
  PaletteLength: LongWord;
  ReadBytes: LongWord;
  Width, Height : Integer;
  pData : Pointer;

  // used for loading from resource
  ResStream : TResourceStream;
begin
  result :=FALSE;

  if LoadFromResource then // Load from resource
  begin
    try
      ResStream := TResourceStream.Create(hInstance, PChar(copy(Filename, 1, Pos('.', Filename)-1)), 'BMP');
      ResStream.ReadBuffer(FileHeader, SizeOf(FileHeader));  // FileHeader
      ResStream.ReadBuffer(InfoHeader, SizeOf(InfoHeader));  // InfoHeader
      PaletteLength := InfoHeader.biClrUsed;
      SetLength(Palette, PaletteLength);
      ResStream.ReadBuffer(Palette, PaletteLength);          // Palette

      Width := InfoHeader.biWidth;
      Height := InfoHeader.biHeight;

      BitmapLength := InfoHeader.biSizeImage;
      if BitmapLength = 0 then
        BitmapLength := Width * Height * InfoHeader.biBitCount Div 8;

      GetMem(pData, BitmapLength);
      ResStream.ReadBuffer(pData^, BitmapLength);            // Bitmap Data
      ResStream.Free;
    except on
      EResNotFound do
      begin
        MessageBox(0, PChar('File not found in resource - ' + Filename), PChar('BMP Texture'), MB_OK);
        Exit;
      end
      else
      begin
        MessageBox(0, PChar('Unable to read from resource - ' + Filename), PChar('BMP Unit'), MB_OK);
        Exit;
      end;
    end;
  end
  else
  begin   // Load image from file
    BitmapFile := CreateFile(PChar(Filename), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
    if (BitmapFile = INVALID_HANDLE_VALUE) then begin
      MessageBox(0, PChar('Error opening ' + Filename), PChar('BMP Unit'), MB_OK);
      Exit;
    end;

    // Get header information
    ReadFile(BitmapFile, FileHeader, SizeOf(FileHeader), ReadBytes, nil);
    ReadFile(BitmapFile, InfoHeader, SizeOf(InfoHeader), ReadBytes, nil);

    // Get palette
    PaletteLength := InfoHeader.biClrUsed;
    SetLength(Palette, PaletteLength);
    ReadFile(BitmapFile, Palette, PaletteLength, ReadBytes, nil);
    if (ReadBytes <> PaletteLength) then begin
      MessageBox(0, PChar('Error reading palette'), PChar('BMP Unit'), MB_OK);
      Exit;
    end;

    Width  := InfoHeader.biWidth;
    Height := InfoHeader.biHeight;
    BitmapLength := InfoHeader.biSizeImage;
    if BitmapLength = 0 then
      BitmapLength := Width * Height * InfoHeader.biBitCount Div 8;

    // Get the actual pixel data
    GetMem(pData, BitmapLength);
    ReadFile(BitmapFile, pData^, BitmapLength, ReadBytes, nil);
    if (ReadBytes <> BitmapLength) then begin
      MessageBox(0, PChar('Error reading bitmap data'), PChar('BMP Unit'), MB_OK);
      Exit;
    end;
    CloseHandle(BitmapFile);
  end;

  // Bitmaps are stored BGR and not RGB, so swap the R and B bytes.
  SwapRGB(pData, Width*Height);

  Texture :=CreateTexture(Width, Height, GL_RGB, pData);
  FreeMem(pData);
  result :=TRUE;
end;




0
  1. popraw wcięcia i formatowanie kodu.
  2. popraw posta, by kod był prawidłowo kolorowany.
  3. w procedurze Draw nie powinno być ładowania żadnych zasobów, na pewno nie LoadImage, którego zresztą nie zwalniasz, tworząc mega wyciek.
  4. co to za funkcja LoadTexture? bez tego to możemy sobie gdybać.
    cColorBits:= 24;
    cDepthBits:= 32;

Odwrotnie.

0

rzeczywiście LoadImage powinno być wcześniej, poprawiłem jak moge koloruje automatycznie, dzięki za uwagę:) nadal źle wyświetla. Gdyby udało się dobrze wyświetlić bitmapę, można by zacząć myśleć o animacji

poza tym w miejscu gdzie wyświetlona jest textura obraz jest tak jakby przyciemniony

0

http://4programmers.net/Forum/994748

Gotowiec to nie jest bo ma parę błędów ale są wskazówki jak je poprawić</del>

{==============================================================================}

interface

{==============================================================================}

uses
  Classes, SysUtils, gEngine_Utils, gl;

{==============================================================================}
type
  TColorFormat = (RGB, RGBA); // Typ określający format kolorów.

{------------------------------------------------------------------------------}

type
  TTextureData = record  // Własny typ zawierający wysokość i szerokość tekstury, format kolorów oraz wskaźnik na dane.
    Width,
    Height : Word;
    Format : TColorFormat;
    Data   : Pointer;
  end;
unit gEngine_Textures_BMP;

{==============================================================================}

const
  BITMAP_ID = $4D42;  // Identyfikator pliku BMP.

{==============================================================================}

type
  TBMPFileHeader = packed record  // Nagłowek pliku BMP.
    bfType      : Word;
    bfSize      : LongWord;
    bfReserved1 : Word;
    bfReserved2 : Word;
    bfOffBits   : DWord;
  end;

{------------------------------------------------------------------------------}

type
  TBMPImageHeader = packed record // Nagłówek obrazu BMP.
    biSize           : LongWord;
    biWidth          : LongInt;
    biHeight         : LongInt;
    biPlanes         : Word;
    biBitCount       : Word;
    biCompression    : LongWord;
    biImageSize      : LongWord;
    biXPelsPerMetter : LongInt;
    biYPelsPerMetter : LongInt;
    biClrUsed        : LongWord;
    biClrImportant   : LongWord;
  end;

{==============================================================================}

function LoadBMPFileHeader(FileName : string) : TBMPFileHeader;
function FileIsBMP(FileName : string) : boolean;
function LoadDataFromBMP(FileName : string) : TTextureData;

{==============================================================================}

implementation

{==============================================================================}

// Funkcja wczytuje nagłówek pliku BMP.
//-------------------------------------
function LoadBMPFileHeader(FileName : string) : TBMPFileHeader;
var
  BMPFile   : TFileStream;
  tmpHeader : TBMPFileHeader;
begin
  BMPFile := TFileStream.Create(Filename, fmOpenRead);
  try
    BMPFile.ReadBuffer(tmpHeader, SizeOf(tmpHeader));
  finally
    FreeAndNil(BMPFile);
  end;
  result := tmpHeader;
end;

{------------------------------------------------------------------------------}

// Funkcja sprawdza czy podany plik to plik BMP.
//----------------------------------------------
function FileIsBMP(FileName : string) : boolean;
var
  BMPFileHeader : TBMPFileHeader;
begin
  BMPFileHeader := LoadBMPFileHeader(FileName);
  if BMPFileHeader.bfType <> BITMAP_ID then
    result := false
  else
    result := true;
end;

{------------------------------------------------------------------------------}

// Funkcja wczytuje dane obrazu z pliku BMP.
//------------------------------------------
function LoadDataFromBMP(FileName : string) : TTextureData;
var
  BMPFile        : TFileStream;
  BMPFileHeader  : TBMPFileHeader;
  BMPImageHEader : TBMPImageHeader;
  ImageData      : PByteArray;
  i              : LongWord;
  tempRGB        : Byte;
begin
  BMPFileHeader := LoadBMPFileHeader(FileName);
  BMPFile := TFileStream.Create(Filename, fmOpenRead);
  try
    BMPFile.Seek(SizeOf(BMPFileHeader), soFromBeginning);

    if BMPFileHeader.bfType <> BITMAP_ID then
    begin
      FreeAndNil(BMPFile);
      result.Height := 0;
      result.Width := 0;
      result.Data := nil;
      exit;
    end;

    BMPFile.ReadBuffer(BMPImageHeader, SizeOf(BMPImageHeader));
    BMPFile.Seek(BMPFileHeader.bfOffBits, soFromBeginning);

    GetMem(ImageData, BMPImageHeader.biImageSize);
    if ImageData = nil then
    begin
      FreeAndNil(BMPFile);
      result.Height := 0;
      result.Width := 0;
      result.Data := nil;
      exit;
    end;

    BMPFile.ReadBuffer(ImageData[0], BMPImageHeader.biImageSize);
  finally
    FreeAndNil(BMPFile);
  end;

  i := 0;
  while i < BMPImageHeader.biImageSize do
  begin
    tempRGB := ImageData^[i];
    ImageData^[i] := ImageData^[i + 2];
    ImageData^[i + 2] := tempRGB;
    Inc(i, 3);
  end;

  result.Width := BMPImageHeader.biWidth;
  result.Height := BMPImageHeader.biHeight;
  result.Format := RGB;
  result.Data := ImageData;
end;

// Funkcja wczytuje teksturę i zwraca jej identyfikator.
//------------------------------------------------------
function LoadTexture(FileName : String) : gluInt;
var
  TextureData : TTextureData;
  ImageType   : TImageType;
begin
  ImageType := GetImageType(FileName);
  case ImageType of
    BMP     : TextureData := LoadDataFromBMP(FileName);
    TGA     : TextureData := LoadDataFromTGA(FileName);
    UNKNOWN : exit;
  end;

  glGenTextures(1, @result);
  glBindTexture(GL_TEXTURE_2D, result);

  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

  Case TextureData.Format of
    RGB  : glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TextureData.Width, TextureData.Height,
                       0, GL_RGB, GL_UNSIGNED_BYTE, TextureData.Data);
    RGBA : glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TextureData.Width, TextureData.Height,
                       0, GL_RGBA, GL_UNSIGNED_BYTE, TextureData.Data);
  end;
  FreeMem(TextureData.Data);
end;   

{==============================================================================}
 

Zlepek kodów. Po małym dostosowaniu będzie działać.

0
function FileIsBMP(FileName : string) : boolean;
var
  BMPFileHeader : TBMPFileHeader;
begin
  BMPFileHeader := LoadBMPFileHeader(FileName);
  if BMPFileHeader.bfType <> BITMAP_ID then
    result := false
  else
    result := true;
end;

Nie sądzisz, że ten warunek jest zbędny? :

function IsBMPFile(FileName: String): Boolean;
var
  BMPFileHeader : TBMPFileHeader;
begin
  BMPFileHeader := LoadBMPFileHeader(FileName);
  Result := BMPFileHeader.bfType = BITMAP_ID;
end;

No i nazewnictwo się kłania :]

0

dzięki za podpowiedź, sprawdzę ten kod. szkoda że w OpenGL nie można modelować bitmapy tak jak Image, nie ma stretch... czyli w sumie jestem w czarnej dupie, pozostało jeszcze usunięcie białego tła z animacji. Robienie gry na Image to wypaczony pomysł jak na razie moje umiejętności ograniczają się do tego OpenGL to czarny kon którego musze się uczyć, pozdrawiam

0

Jak to nie ma "stretch"? Tworzysz oteksturowany prostokąt i skalujesz go jak chcesz.

0

faktycznie:) dzięki!

1 użytkowników online, w tym zalogowanych: 0, gości: 1