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
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.
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.
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;
- popraw wcięcia i formatowanie kodu.
- popraw posta, by kod był prawidłowo kolorowany.
- w procedurze Draw nie powinno być ładowania żadnych zasobów, na pewno nie LoadImage, którego zresztą nie zwalniasz, tworząc mega wyciek.
- co to za funkcja
LoadTexture
? bez tego to możemy sobie gdybać.
cColorBits:= 24;
cDepthBits:= 32;
Odwrotnie.
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
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ć.
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 :]
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
Jak to nie ma "stretch"? Tworzysz oteksturowany prostokąt i skalujesz go jak chcesz.
faktycznie:) dzięki!