📄 textures.pas
字号:
//----------------------------------------------------------------------------
//
// Author : Jan Horn
// Email : jhorn@global.co.za
// Website : http://www.sulaco.co.za
// http://home.global.co.za/~jhorn
// Version : 1.03
// Date : 1 May 2001
// Changes : 28 July 2001 - Faster BGR to RGB swapping routine
// 2 October 2001 - Added support for 24, 32bit TGA files
// 28 April 2002 - Added support for compressed TGA files
//
// Description : A unit that used with OpenGL projects to load BMP, JPG and TGA
// files from the disk or a resource file.
// Usage : LoadTexture(Filename, TextureName, LoadFromResource);
//
// eg : LoadTexture('logo.jpg', LogoTex, TRUE);
// will load a JPG texture from the resource included
// with the EXE. File has to be loaded into the Resource
// using this format "logo JPEG logo.jpg"
//
//----------------------------------------------------------------------------
unit Textures;
interface
uses
Windows, OpenGL, Graphics, Classes, JPEG, SysUtils;
function LoadTexture(Filename: String; var Texture: GLuint; LoadFromRes : Boolean): Boolean;
procedure glGenTextures(n: GLsizei; var Textures: GLuint); stdcall;external 'opengl32.dll';
{$EXTERNALSYM glGenTextures}
procedure glBindTexture(target: GLenum; Texture: GLuint); stdcall;external 'opengl32.dll';
{$EXTERNALSYM glBindTexture}
procedure glDeleteTextures(n:GLsizei; var textureNames:GLuint); stdcall;external 'opengl32.dll';
{$EXTERNALSYM glDeleteTextures}
function gluBuild2DMipmaps (target: GLenum; components, width, height: GLint;
format, atype: GLenum; data: Pointer): Integer; stdcall;external 'glu32.dll';
implementation
{------------------------------------------------------------------}
{ Swap bitmap format from BGR to RGB }
{------------------------------------------------------------------}
procedure SwapRGB(data : Pointer; Size : Integer);
asm
mov ebx, eax
mov ecx, size
@@loop :
mov al,[ebx+0]
mov ah,[ebx+2]
mov [ebx+2],al
mov [ebx+0],ah
add ebx,3
dec ecx
jnz @@loop
end;
{------------------------------------------------------------------}
{ Create the Texture }
{------------------------------------------------------------------}
function CreateTexture(Width, Height, Format : Word; pData : Pointer) : Integer;
var
Texture : GLuint;
begin
glGenTextures(1, Texture);
glBindTexture(GL_TEXTURE_2D, Texture);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); {Texture blends with object background}
// glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); {Texture does NOT blend with object background}
{ Select a filtering type. BiLinear filtering produces very good results with little performance impact
GL_NEAREST - Basic texture (grainy looking texture)
GL_LINEAR - BiLinear filtering
GL_LINEAR_MIPMAP_NEAREST - Basic mipmapped texture
GL_LINEAR_MIPMAP_LINEAR - BiLinear Mipmapped texture
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); { only first two can be used }
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); { all of the above can be used }
if Format = GL_RGBA then
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, pData)
else
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, Width, Height, GL_RGB, GL_UNSIGNED_BYTE, pData);
// glTexImage2D(GL_TEXTURE_2D, 0, 3, Width, Height, 0, GL_RGB, GL_UNSIGNED_BYTE, pData); // Use when not wanting mipmaps to be built by openGL
result :=Texture;
end;
{------------------------------------------------------------------}
{ Load BMP textures }
{------------------------------------------------------------------}
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;
{------------------------------------------------------------------}
{ Load JPEG textures }
{------------------------------------------------------------------}
function LoadJPGTexture(Filename: String; var Texture: GLuint; LoadFromResource : Boolean): Boolean;
var
Data : Array of LongWord;
W, Width : Integer;
H, Height : Integer;
BMP : TBitmap;
JPG : TJPEGImage;
C : LongWord;
Line : ^LongWord;
ResStream : TResourceStream; // used for loading from resource
begin
result :=FALSE;
JPG:=TJPEGImage.Create;
if LoadFromResource then // Load from resource
begin
try
ResStream := TResourceStream.Create(hInstance, PChar(copy(Filename, 1, Pos('.', Filename)-1)), 'JPEG');
JPG.LoadFromStream(ResStream);
ResStream.Free;
except on
EResNotFound do
begin
MessageBox(0, PChar('File not found in resource - ' + Filename), PChar('JPG Texture'), MB_OK);
Exit;
end
else
begin
MessageBox(0, PChar('Couldn''t load JPG Resource - "'+ Filename +'"'), PChar('BMP Unit'), MB_OK);
Exit;
end;
end;
end
else
begin
try
JPG.LoadFromFile(Filename);
except
MessageBox(0, PChar('Couldn''t load JPG - "'+ Filename +'"'), PChar('BMP Unit'), MB_OK);
Exit;
end;
end;
// Create Bitmap
BMP:=TBitmap.Create;
BMP.pixelformat:=pf32bit;
BMP.width:=JPG.width;
BMP.height:=JPG.height;
BMP.canvas.draw(0,0,JPG); // Copy the JPEG onto the Bitmap
// BMP.SaveToFile('D:\test.bmp');
Width :=BMP.Width;
Height :=BMP.Height;
SetLength(Data, Width*Height);
For H:=0 to Height-1 do
Begin
Line :=BMP.scanline[Height-H-1]; // flip JPEG
For W:=0 to Width-1 do
Begin
c:=Line^ and $FFFFFF; // Need to do a color swap
Data[W+(H*Width)] :=(((c and $FF) shl 16)+(c shr 16)+(c and $FF00)) or $FF000000; // 4 channel.
inc(Line);
End;
End;
BMP.free;
JPG.free;
Texture :=CreateTexture(Width, Height, GL_RGBA, addr(Data[0]));
result :=TRUE;
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -