Results 1 to 2 of 2

Thread: SDL and OpenGL textures

  1. #1

    SDL and OpenGL textures

    I've tried to get my SDL/OpenGL app to work with Lazarus but I've ran into problems.

    I can't seem to be able to use any classes like TBitmap etc. My texture loading routines use these and they work just fine in Delphi whether I have a pure SDL application or normal app with forms.

    Any workarounds for this or do I have to write my own texture loading routines without the help of TBitmap class for all image formats (BMP, TGA, JPEG, PCX etc.) that I use?
    If you develop an idiot proof system, the nature develops better idiots.

  2. #2

    SDL and OpenGL textures

    Got tired of looking for the solution, so I decided the to write the loades myself. www.wotsit.org is the programmer's best friend.

    If anyone's interested, here's the code to load 8, 24 and 32 bit BMP files without compression and 8bit PCX files with RLE compression.
    The loading routines are quite fast, but you're welcome to try to optimize it if you like.

    [pascal]
    type
    TTextureData = array [0..0] of Byte;
    PTextureData = ^TTextureData;
    PTexture = ^TTexture;
    TTexture = record
    Filename: String;
    Width, Height, Size: Integer;
    GL_ID: TInt;
    GL_Type: Integer;
    GL_Parameters: Integer;
    GL_Uploaded: Boolean;
    end;

    function Load_BMP(FileName: String; var TextureData: PTextureData; var Texture: PTexture): Boolean;

    const
    // Header types
    BMP_BM = 'BM'; // Windows 3.1x, 95, NT etc.
    BMP_BA = 'BA'; // OS/2 Bitmap Array
    BMP_CI = 'CI'; // OS/2 Color Icon
    BMP_CP = 'CP'; // OS/2 Color Pointer
    BMP_IC = 'IC'; // OS/2 Icon
    BMP_PT = 'PT'; // OS/2 Pointer

    // Compression types
    BMP_BI_RGB = 0; // RGB
    BMP_BI_RLE8 = 1; // RLE8
    BMP_BI_RLE4 = 2; // RLE4
    BMP_BI_BITFIELDS = 4; // Bitfields

    // Color types
    BMP_COLOR_1 = 1; // Monochrome
    BMP_COLOR_4 = 4; // 16 color bitmap
    BMP_COLOR_8 = 8; // 256 color bitmap
    BMP_COLOR_16 = 16; // 16bit (hight color) bitmap
    BMP_COLOR_24 = 24; // 24bit (true color) bitmap
    BMP_COLOR_32 = 32; // 32bit (true color) bitmap

    BMP_COMPRESSION_NONE = 0; // None (Also identified by BI_RGB)
    BMP_COMPRESSION_RLE8 = 1; // RLE 8-bit / pixel (Also identified by BI_RLE4)
    BMP_COMPRESSION_RLE4 = 2; // RLE 4-bit / pixel (Also identified by BI_RLE
    BMP_COMPRESSION_BITFIELDS = 3; // Bitfields (Also identified by BI_BITFIELDS)
    type
    TBMP_FileHeader = packed record
    ID: array [0..1] of Char;
    FileSize: LongWord;
    Reserved1: Word;
    Reserved2: Word;
    BitmapDataOffset: LongWord;
    end;

    TBMP_InfoHeader = packed record
    BitmapHeaderSize: LongWord;
    Width: LongWord;
    Height: LongWord;
    Planes: Word;
    BitsPerPixel: Word;
    Compression: LongWord;
    BitmapDataSize: LongWord;
    HResolution: LongWord;
    VResolution: LongWord;
    Colors: LongWord;
    ImportantColors: LongWord;
    Palette: array [0..255, 0..3] of Byte;
    end;

    TBMP_Buffer24 = array [0..2] of Byte;
    TBMP_Buffer32 = array [0..3] of Byte;

    var
    BMP_File: TMemoryStream;
    BMP_FileHeader: TBMP_FileHeader;
    BMP_InfoHeader: TBMP_InfoHeader;
    BMP_Buffer: array [0..3] of Byte;
    x: LongWord;
    y: LongWord;
    Offset: LongWord;

    b: Byte;

    begin
    BMP_File := TMemoryStream.Create;
    BMP_File.LoadFromFile(FileName);
    try
    BMP_File.Read(BMP_FileHeader, SizeOf(TBMP_FileHeader));
    if (BMP_FileHeader.ID <> BMP_BM) then
    raise EUnsupportedFileFormatError.Create('Unsupported BMP file format ' + BMP_FileHeader.ID + '!');
    BMP_File.Read(BMP_InfoHeader, SizeOf(TBMP_InfoHeader));
    Texture^.Width := BMP_InfoHeader.Width;
    Texture^.Height := BMP_InfoHeader.Height;
    Texture^.Size := BMP_InfoHeader.Width * BMP_InfoHeader.Height * 3;
    Texture^.GL_Type := GL_RGB;
    GetMem(TextureData, Texture^.Size);
    y := BMP_InfoHeader.Height - 1;
    x := 0;
    if BMP_InfoHeader.BitsPerPixel = BMP_COLOR_8 then
    begin
    BMP_File.Seek(BMP_FileHeader.BitmapDataOffset, soFromBeginning);
    while BMP_File.Position < BMP_File.Size do
    begin
    BMP_File.Read(b, 1);
    Offset := ((y * BMP_InfoHeader.Width) + x) * 3;
    TextureData^[Offset + 0] := BMP_InfoHeader.Palette[b][2];
    TextureData^[Offset + 1] := BMP_InfoHeader.Palette[b][1];
    TextureData^[Offset + 2] := BMP_InfoHeader.Palette[b][0];
    Inc(x);
    if (x >= BMP_InfoHeader.Width) then
    begin
    x := 0;
    Dec(y);
    end;
    end;
    end;
    if (BMP_InfoHeader.BitsPerPixel in [BMP_COLOR_24, BMP_COLOR_32]) then
    begin
    BMP_File.Seek(BMP_FileHeader.BitmapDataOffset, soFromBeginning);
    while BMP_File.Position < BMP_File.Size do
    begin
    if BMP_InfoHeader.BitsPerPixel = BMP_COLOR_24 then
    BMP_File.Read(BMP_Buffer, SizeOf(TBMP_Buffer24))
    else
    BMP_File.Read(BMP_Buffer, SizeOf(TBMP_Buffer32));
    // Bitmap data is stored upside down in the file, so we calculate an offset
    // to the texture data on
    Offset := ((y * BMP_InfoHeader.Width) + x) * 3;
    TextureData^[Offset + 0] := BMP_Buffer[2];
    TextureData^[Offset + 1] := BMP_Buffer[1];
    TextureData^[Offset + 2] := BMP_Buffer[0];
    Inc(x);
    if (x >= BMP_InfoHeader.Width) then
    begin
    x := 0;
    Dec(y);
    end;
    end;
    end;
    BMP_File.Free;
    Result := TRUE;
    except
    on E: Exception do
    begin
    if TextureData <> nil then
    FreeMem(TextureData, Texture^.Size);
    BMP_File.Free;
    raise ExtendedException.Create('uTextureFormat', 'Load_BMP', E);
    end;
    end;
    end;

    function Load_PCX(Filename: String; var TextureData: PTextureData; var Texture: PTexture): Boolean;

    type
    TPCX_Header = packed record
    Manufacturer,
    Version,
    Encoding,
    BitsPerPixel: Byte;
    XMin, YMin, XMax, YMax: SmallInt;
    HRes, VRes: SmallInt;
    Palette: array [0..47] of Byte;
    Reserved,
    ColorPlanes: Byte;
    BytesPerLine,
    PaletteType: Word;
    Filler: array [0..57] of Byte;
    end;

    TPCX_Palette = array [0..255, 0..2] of Byte;

    var
    PCX_Header: TPCX_Header;
    PCX_Palette: TPCX_Palette;
    PCX_Data: PTextureData;
    PCX_DataSize: LongWord;
    PCX_File: TMemoryStream;
    IsPalette: Byte;
    x, y, Count, PCX_Count: LongWord;
    DataByte, Len: Byte;
    begin
    Result := FALSE;
    PCX_Data := nil;
    PCX_DataSize := 0;
    PCX_File := TMemoryStream.Create();
    PCX_File.LoadFromFile(Filename);
    try
    PCX_File.Read(PCX_Header, SizeOf(TPCX_Header));
    // Check for bad PCX file
    if not ((PCX_Header.Manufacturer <> $0A) or (PCX_Header.version <> 5) or (PCX_Header.Encoding <> 1) or (PCX_Header.BitsPerPixel <> or (PCX_Header.XMax >= 640) or (PCX_Header.YMax >= 480)) then
    begin
    PCX_File.Seek(128, soFromBeginning);
    PCX_DataSize := (PCX_File.Size - SizeOf(TPCX_Header)) - 769;
    GetMem(PCX_Data, PCX_DataSize);
    PCX_File.Read(PCX_Data^, PCX_DataSize);
    PCX_File.Seek(PCX_File.Size - 769, soFromBeginning);
    PCX_File.Read(IsPalette, SizeOf(Byte));
    PCX_File.Read(PCX_Palette, 76;
    Texture^.Width := PCX_Header.XMax + 1;
    Texture^.Height := PCX_Header.YMax + 1;
    Texture^.Size := Texture^.Width * Texture^.Height * 3;
    Texture^.GL_Type := GL_RGB;
    GetMem(TextureData, Texture^.Size);
    Count := 0;
    PCX_Count := 0;
    for y := 0 to PCX_Header.YMax + 1 do
    begin
    x := 0;
    while x < PCX_Header.XMax do
    begin
    if PCX_Count > PCX_DataSize then
    Break;
    DataByte := PCX_Data^[PCX_Count];
    Inc(PCX_Count);
    if (DataByte and $C0) = $C0 then
    begin
    Len := (DataByte and $3F);
    DataByte := PCX_Data^[PCX_Count];
    Inc(PCX_Count);
    end
    else
    Len := 1;
    while Len > 0 do
    begin
    if (Count + 2) > Texture^.Size then
    Break;
    TextureData^[Count] := PCX_Palette[DataByte, 0];
    TextureData^[Count + 1] := PCX_Palette[DataByte, 1];
    TextureData^[Count + 2] := PCX_Palette[DataByte, 2];
    Inc(Count, 3);
    Inc(x);
    Dec(Len);
    end;
    end;
    end;
    if (PCX_Data <> nil) and (PCX_DataSize > 0) then
    FreeMem(PCX_Data, PCX_DataSize);
    Result := TRUE;
    end;
    PCX_File.Free;
    except
    on E: Exception do
    begin
    if (PCX_Data <> nil) and (PCX_DataSize > 0) then
    FreeMem(PCX_Data, PCX_DataSize);
    PCX_File.Free;
    raise ExtendedException.Create('uTextureFormat', 'Load_PCX', E);
    end;
    end;
    end;
    [/pascal]

    EDIT: Fixed a bug in the PCX code.
    If you develop an idiot proof system, the nature develops better idiots.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •