X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fengine%2Fe_textures.pas;h=ef9b660c9254c694f15bdf7900c088ba2e18532c;hb=605f9546f8ffc4a8354f83ed3a854d95562e45b3;hp=1c470fa6b3fe997e483e451bbaa4b9a19ab42c1e;hpb=ff104a8cdc79693b7546d839605ec73ae135d904;p=d2df-sdl.git diff --git a/src/engine/e_textures.pas b/src/engine/e_textures.pas index 1c470fa..ef9b660 100644 --- a/src/engine/e_textures.pas +++ b/src/engine/e_textures.pas @@ -9,28 +9,49 @@ interface uses GL, GLExt, SysUtils, e_log; +type + GLTexture = record + id: GLuint; + width, height: Word; // real + glwidth, glheight: Word; // powerof2 + u, v: Single; // usually 1.0 + end; + var - fUseMipmaps: Boolean = False; TEXTUREFILTER: Integer = GL_NEAREST; -function CreateTexture( Width, Height, Format: Word; pData: Pointer ): Integer; +function CreateTexture(var tex: GLTexture; Width, Height, aFormat: Word; pData: Pointer ): Boolean; // Standard set of images loading functions -function LoadTexture( Filename: String; var Texture: GLuint; +function LoadTexture( Filename: String; var Texture: GLTexture; var pWidth, pHeight: Word; Fmt: PWord = nil ): Boolean; -function LoadTextureEx( Filename: String; var Texture: GLuint; +function LoadTextureEx( Filename: String; var Texture: GLTexture; fX, fY, fWidth, fHeight: Word; Fmt: PWord = nil ): Boolean; -function LoadTextureMem( pData: Pointer; var Texture: GLuint; +function LoadTextureMem( pData: Pointer; var Texture: GLTexture; var pWidth, pHeight: Word; Fmt: PWord = nil ): Boolean; -function LoadTextureMemEx( pData: Pointer; var Texture: GLuint; +function LoadTextureMemEx( pData: Pointer; var Texture: GLTexture; fX, fY, fWidth, fHeight: Word; Fmt: PWord = nil ): Boolean; implementation -uses BinEditor; +uses BinEditor, g_options; + + +function AlignP2 (n: Word): Word; +begin + Dec(n); + n := n or (n shr 1); + n := n or (n shr 2); + n := n or (n shr 4); + n := n or (n shr 8); + n := n or (n shr 16); + Inc(n); + Result := n; +end; + type TTGAHeader = packed record @@ -47,17 +68,40 @@ type end; // This is auxiliary function that creates OpenGL texture from raw image data -function CreateTexture( Width, Height, Format: Word; pData: Pointer ): Integer; +function CreateTexture (var tex: GLTexture; Width, Height, aFormat: Word; pData: Pointer): Boolean; var Texture: GLuint; begin - glGenTextures( 1, @Texture ); - glBindTexture( GL_TEXTURE_2D, Texture ); + tex.width := Width; + tex.height := Height; + if glLegacyNPOT then + begin + tex.glwidth := AlignP2(Width); + tex.glheight := AlignP2(Height); + end + else + begin + tex.glwidth := Width; + tex.glheight := Height; + end; + tex.u := 1; + tex.v := 1; + if tex.glwidth <> tex.width then tex.u := (tex.width+0.0)/(tex.glwidth+0.0); + if tex.glheight <> tex.height then tex.v := (tex.height+0.0)/(tex.glheight+0.0); + + if (tex.glwidth <> tex.width) or (tex.glheight <> tex.height) then + begin + e_WriteLog(Format('NPOT: orig is %ux%u; gl is %ux%u; u=%f; v=%f', [Width, Height, tex.glwidth, tex.glheight, tex.u, tex.v]), MSG_NOTIFY); + end; + + glGenTextures(1, @Texture); + tex.id := Texture; + glBindTexture(GL_TEXTURE_2D, Texture); - {Texture blends with object background} - glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); - {Texture does NOT blend with object background} - // glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); + // texture blends with object background + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + // texture does NOT blend with object background + //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); { Select a filtering type. @@ -70,26 +114,46 @@ begin } // for GL_TEXTURE_MAG_FILTER only first two can be used - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TEXTUREFILTER ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TEXTUREFILTER); // for GL_TEXTURE_MIN_FILTER all of the above can be used - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TEXTUREFILTER ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TEXTUREFILTER); - if Format = GL_RGBA then + // create empty texture + if aFormat = GL_RGBA then begin - glTexImage2D( GL_TEXTURE_2D, 0, 4, Width, Height, - 0, GL_RGBA, GL_UNSIGNED_BYTE, pData ); - end else + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.glwidth, tex.glheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nil); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, pData); + end + else begin - glTexImage2D( GL_TEXTURE_2D, 0, 3, Width, Height, - 0, GL_RGB, GL_UNSIGNED_BYTE, pData ); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex.glwidth, tex.glheight, 0, GL_RGB, GL_UNSIGNED_BYTE, nil); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, Width, Height, GL_RGB, GL_UNSIGNED_BYTE, pData); end; + // the following is ok too + //bindTexture(0); + //glTextureSubImage2D(tid, 0, 0, 0, img.width, img.height, GL_RGBA, GL_UNSIGNED_BYTE, img.imageData.bytes.ptr); + + { + if (tex.glwidth = tex.glwidth) and (tex.glheight = tex.height) then + // easy case + if aFormat = GL_RGBA then + begin + glTexImage2D(GL_TEXTURE_2D, 0, 4, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pData); + end + else + begin + glTexImage2D(GL_TEXTURE_2D, 0, 3, Width, Height, 0, GL_RGB, GL_UNSIGNED_BYTE, pData); + end; + end + } + glBindTexture(GL_TEXTURE_2D, 0); - Result := Texture; + Result := true; end; -function LoadTextureMem( pData: Pointer; var Texture: GLuint; +function LoadTextureMem( pData: Pointer; var Texture: GLTexture; var pWidth, pHeight: Word; Fmt: PWord = nil ): Boolean; var TGAHeader: TTGAHeader; @@ -128,6 +192,12 @@ begin Exit; end; + if (TGAHeader.ImageInfo and $c0) <> 0 then + begin + e_WriteLog('Error loading texture: interleaved TGA', MSG_WARNING); + Exit; + end; + Width := TGAHeader.Width[0] + TGAHeader.Width[1] * 256; Height := TGAHeader.Height[0] + TGAHeader.Height[1] * 256; BPP := TGAHeader.BPP; @@ -146,12 +216,14 @@ begin Back^ := Temp; end; + //if (TGAHeader.ImageInfo and $20) <> 0 then UpsideDown(Image, Width, Height); + if ( BPP = 24 ) then TFmt := GL_RGB else TFmt := GL_RGBA; - Texture := CreateTexture( Width, Height, TFmt, Image ); + CreateTexture(Texture, Width, Height, TFmt, Image ); FreeMem( Image ); @@ -163,7 +235,7 @@ begin Result := True; end; -function LoadTextureMemEx( pData: Pointer; var Texture: GLuint; +function LoadTextureMemEx( pData: Pointer; var Texture: GLTexture; fX, fY, fWidth, fHeight: Word; Fmt: PWord = nil ): Boolean; var TGAHeader: TTGAHeader; @@ -201,6 +273,12 @@ begin Exit; end; + if (TGAHeader.ImageInfo and $c0) <> 0 then + begin + e_WriteLog('Error loading texture: interleaved TGA', MSG_WARNING); + Exit; + end; + Width := TGAHeader.Width[0] + TGAHeader.Width[1] * 256; Height := TGAHeader.Height[0] + TGAHeader.Height[1] * 256; BPP := TGAHeader.BPP; @@ -237,12 +315,14 @@ begin for i := 0 to fHeight-1 do CopyMemory( PByte(image) + a*i, Base + b*i, a ); + //if (TGAHeader.ImageInfo and $20) <> 0 then UpsideDown(Image, Width, Height); + if ( BPP = 24 ) then TFmt := GL_RGB else TFmt := GL_RGBA; - Texture := CreateTexture( fWidth, fHeight, TFmt, Image ); + CreateTexture(Texture, fWidth, fHeight, TFmt, Image ); FreeMem( Image ); FreeMem( Image2 ); @@ -252,7 +332,7 @@ begin Result := True; end; -function LoadTexture( Filename: String; var Texture: GLuint; +function LoadTexture( Filename: String; var Texture: GLTexture; var pWidth, pHeight: Word; Fmt: PWord = nil ): Boolean; var TGAHeader: TTGAHeader; @@ -335,7 +415,7 @@ begin else TFmt := GL_RGBA; - Texture := CreateTexture( Width, Height, TFmt, Image ); + CreateTexture(Texture, Width, Height, TFmt, Image ); FreeMem( Image ); @@ -347,7 +427,7 @@ begin Result := True; end; -function LoadTextureEx( Filename: String; var Texture: GLuint; +function LoadTextureEx( Filename: String; var Texture: GLTexture; fX, fY, fWidth, fHeight: Word; Fmt: PWord = nil ): Boolean; var TGAHeader: TTGAHeader; @@ -439,7 +519,7 @@ begin else TFmt := GL_RGBA; - Texture := CreateTexture( fWidth, fHeight, TFmt, Image ); + CreateTexture(Texture, fWidth, fHeight, TFmt, Image ); FreeMem( Image ); FreeMem( Image2 );