X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fengine%2Fe_textures.pas;h=8dfd2cc8392a4796b6714787e49b920fb5bbbf65;hb=0cf82d25f7ffee01d662d9d11793077805a263cb;hp=19efb4b1659cd844b340281ee9ec243f6fceb5c2;hpb=8f815647c61a98e32b85066bf245b262694ac634;p=d2df-sdl.git diff --git a/src/engine/e_textures.pas b/src/engine/e_textures.pas index 19efb4b..8dfd2cc 100644 --- a/src/engine/e_textures.pas +++ b/src/engine/e_textures.pas @@ -1,3 +1,18 @@ +(* Copyright (C) DooM 2D:Forever Developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *) {$MODE DELPHI} unit e_textures; @@ -8,7 +23,8 @@ unit e_textures; interface uses - GL, GLExt, SysUtils, e_log; + GL, GLExt, SysUtils, e_log, + ImagingTypes, Imaging, ImagingUtility; type GLTexture = record @@ -16,6 +32,7 @@ type width, height: Word; // real glwidth, glheight: Word; // powerof2 u, v: Single; // usually 1.0 + fmt: GLuint; end; var @@ -30,11 +47,14 @@ function LoadTextureEx (Filename: String; var Texture: GLTexture; fX, fY, fWidth function LoadTextureMem (pData: Pointer; dataSize: LongInt; var Texture: GLTexture; var pWidth, pHeight: Word; Fmt: PWord=nil): Boolean; function LoadTextureMemEx (pData: Pointer; dataSize: LongInt; var Texture: GLTexture; fX, fY, fWidth, fHeight: Word; Fmt: PWord=nil): Boolean; +// `img` must be valid! +function LoadTextureImg (var img: TImageData; var Texture: GLTexture; var pWidth, pHeight: Word; Fmt: PWord=nil): Boolean; + + implementation uses - Classes, BinEditor, g_options, utils, - ImagingTypes, Imaging, ImagingUtility; + Classes, BinEditor, g_options, utils; function AlignP2 (n: Word): Word; @@ -50,49 +70,31 @@ begin end; -{ -type - TTGAHeader = packed record - FileType: Byte; - ColorMapType: Byte; - ImageType: Byte; - ColorMapSpec: array[0..4] of Byte; - OrigX: array[0..1] of Byte; - OrigY: array[0..1] of Byte; - Width: array[0..1] of Byte; - Height: array[0..1] of Byte; - BPP: Byte; - ImageInfo: Byte; - end; -} - - // This is auxiliary function that creates OpenGL texture from raw image data function CreateTexture (var tex: GLTexture; Width, Height, aFormat: Word; pData: Pointer): Boolean; var Texture: GLuint; + fmt: GLenum; + //buf: PByte; + //f, c: Integer; begin tex.width := Width; tex.height := Height; + tex.glwidth := Width; + tex.glheight := Height; + tex.u := 1; + tex.v := 1; + if glLegacyNPOT then begin tex.glwidth := AlignP2(Width); tex.glheight := AlignP2(Height); - end - else - begin - tex.glwidth := Width; - tex.glheight := Height; + 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); 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; + //if (tex.glwidth <> tex.width) or (tex.glheight <> tex.height) then + // 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); if e_DummyTextures then begin @@ -105,6 +107,9 @@ begin tex.id := Texture; glBindTexture(GL_TEXTURE_2D, Texture); + if (tex.glwidth <> tex.width) or (tex.glheight <> tex.height) then + e_WriteLog(Format('NPOT: %u is %ux%u; gl is %ux%u; u=%f; v=%f', [tex.id, Width, Height, tex.glwidth, tex.glheight, tex.u, tex.v]), MSG_NOTIFY); + // texture blends with object background glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // texture does NOT blend with object background @@ -126,46 +131,46 @@ begin glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TEXTUREFILTER); // create empty texture - if aFormat = GL_RGBA then - begin - 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, 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 aFormat = GL_RGBA then fmt := GL_RGBA else fmt := GL_RGB; // silly, yeah? + glTexImage2D(GL_TEXTURE_2D, 0, fmt, tex.glwidth, tex.glheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nil); - { - 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 + (* + GetMem(buf, tex.glwidth*4*tex.glheight); + try + FillChar(buf^, tex.glwidth*4*tex.glheight, 255); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, tex.glwidth, tex.glheight, fmt, GL_UNSIGNED_BYTE, buf); + if (tex.glheight = 128) and (tex.height = 80) then begin - glTexImage2D(GL_TEXTURE_2D, 0, 3, Width, Height, 0, GL_RGB, GL_UNSIGNED_BYTE, pData); + for f := 0 to tex.glheight-1 do + begin + for c := 0 to tex.glwidth-1 do + begin + buf[f*(tex.glwidth*4)+c*4+0] := 255; + buf[f*(tex.glwidth*4)+c*4+1] := 127; + buf[f*(tex.glwidth*4)+c*4+2] := 0; + end; + end; + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 82, tex.glwidth, {tex.glheight}1, fmt, GL_UNSIGNED_BYTE, buf); end; - end - } + finally + FreeMem(buf); + end; + *) + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, Width, Height, fmt, GL_UNSIGNED_BYTE, pData); + //glTexSubImage2D(GL_TEXTURE_2D, 0, 0, tex.glheight-tex.height, Width, Height, fmt, GL_UNSIGNED_BYTE, pData); glBindTexture(GL_TEXTURE_2D, 0); Result := true; end; -function LoadTextureMem (pData: Pointer; dataSize: LongInt; var Texture: GLTexture; var pWidth, pHeight: Word; Fmt: PWord=nil): Boolean; +// `img` must be valid! +function LoadTextureImg (var img: TImageData; var Texture: GLTexture; var pWidth, pHeight: Word; Fmt: PWord=nil): Boolean; var image, ii: PByte; width, height: Integer; imageSize: Integer; - img: TImageData; x, y: Integer; clr: TColor32Rec; begin @@ -174,44 +179,62 @@ begin pHeight := 0; if Fmt <> nil then Fmt^ := GL_RGBA; // anyway - InitImage(img); - if not LoadImageFromMemory(pData, dataSize, img) then + if (img.width < 1) or (img.width > 32768) or (img.height < 1) or (img.height > 32768) then begin - e_WriteLog('Error loading texture: unknown image format', MSG_WARNING); + e_WriteLog('Error loading texture: invalid image dimensions', MSG_WARNING); exit; end; + //ConvertImage(img, ifA8R8G8B8); + width := img.width; + height := img.height; + pWidth := width; + pHeight := height; + imageSize := Width*Height*4; + GetMem(image, imageSize); try - if (img.width < 1) or (img.width > 32768) or (img.height < 1) or (img.height > 32768) then + // it's slow, but i don't care for now + ii := image; + for y := height-1 downto 0 do begin - e_WriteLog('Error loading texture: invalid image dimensions', MSG_WARNING); - exit; - end; - //ConvertImage(img, ifA8R8G8B8); - width := img.width; - height := img.height; - pWidth := width; - pHeight := height; - imageSize := Width*Height*32; - GetMem(image, imageSize); - try - // it's slow, but i don't care for now - ii := image; - for y := height-1 downto 0 do + for x := 0 to width-1 do begin - for x := 0 to width-1 do - begin - clr := GetPixel32(img, x, y); - ii^ := clr.r; Inc(ii); - ii^ := clr.g; Inc(ii); - ii^ := clr.b; Inc(ii); - ii^ := clr.a; Inc(ii); - end; + clr := GetPixel32(img, x, y); + ii^ := clr.r; Inc(ii); + ii^ := clr.g; Inc(ii); + ii^ := clr.b; Inc(ii); + ii^ := clr.a; Inc(ii); end; - CreateTexture(Texture, width, height, GL_RGBA, image); - result := true; - finally - FreeMem(image); end; + CreateTexture(Texture, width, height, GL_RGBA, image); + result := true; + finally + FreeMem(image); + end; +end; + + +function LoadTextureMem (pData: Pointer; dataSize: LongInt; var Texture: GLTexture; var pWidth, pHeight: Word; Fmt: PWord=nil): Boolean; +var + //image, ii: PByte; + //width, height: Integer; + //imageSize: Integer; + img: TImageData; + //x, y: Integer; + //clr: TColor32Rec; +begin + result := false; + pWidth := 0; + pHeight := 0; + if Fmt <> nil then Fmt^ := GL_RGBA; // anyway + + InitImage(img); + if not LoadImageFromMemory(pData, dataSize, img) then + begin + e_WriteLog('Error loading texture: unknown image format', MSG_WARNING); + exit; + end; + try + result := LoadTextureImg(img, Texture, pWidth, pHeight, Fmt); finally FreeImage(img); end; @@ -221,7 +244,7 @@ end; function LoadTextureMemEx (pData: Pointer; dataSize: LongInt; var Texture: GLTexture; fX, fY, fWidth, fHeight: Word; Fmt: PWord=nil): Boolean; var image, ii: PByte; - width, height: Integer; + //width, height: Integer; imageSize: Integer; img: TImageData; x, y: Integer; @@ -247,12 +270,13 @@ begin if fY > img.height then exit; if fX+fWidth > img.width then exit; if fY+fHeight > img.height then exit; - imageSize := img.width*img.height*32; + //writeln('fX=', fX, '; fY=', fY, '; fWidth=', fWidth, '; fHeight=', fHeight); + imageSize := img.width*img.height*4; GetMem(image, imageSize); try // it's slow, but i don't care for now ii := image; - for y := fY+fHeight-1 downto 0 do + for y := fY+fHeight-1 downto fY do begin for x := fX to fX+fWidth-1 do begin