GXS.Texture.pas 92 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260
  1. //
  2. // The graphics engine GXScene https://github.com/glscene
  3. //
  4. unit GXS.Texture;
  5. (* Handles all the color and texture stuff *)
  6. interface
  7. {$I GLScene.Defines.inc}
  8. uses
  9. Winapi.OpenGL,
  10. Winapi.OpenGLext,
  11. System.Classes,
  12. System.SysUtils,
  13. System.Types,
  14. FMX.Graphics,
  15. FMX.Objects,
  16. GXS.TextureFormat,
  17. GLScene.Strings,
  18. GXS.XOpenGL,
  19. GLScene.VectorTypes,
  20. GLScene.VectorGeometry,
  21. GXS.BaseClasses,
  22. GXS.ApplicationFileIO,
  23. GXS.Graphics,
  24. GXS.Context,
  25. GXS.State,
  26. GXS.PipelineTransformation,
  27. GXS.Color,
  28. GXS.Coordinates,
  29. GXS.RenderContextInfo,
  30. GXS.ImageUtils,
  31. GLScene.Utils;
  32. const
  33. cDefaultNormalMapScale = 0.125;
  34. CmtPX = 0;
  35. CmtNX = 1;
  36. CmtPY = 2;
  37. CmtNY = 3;
  38. CmtPZ = 4;
  39. CmtNZ = 5;
  40. type
  41. TgxTextureMode = (tmDecal, tmModulate, tmBlend, tmReplace, tmAdd);
  42. TgxTextureWrap = (twBoth, twNone, twVertical, twHorizontal, twSeparate);
  43. TgxMinFilter =
  44. (
  45. miNearest,
  46. miLinear,
  47. miNearestMipmapNearest,
  48. miLinearMipmapNearest,
  49. miNearestMipmapLinear,
  50. miLinearMipmapLinear
  51. );
  52. TgxMagFilter = (maNearest, maLinear);
  53. (* Specifies how depth values should be treated
  54. during filtering and texture application *)
  55. TgxDepthTextureMode = (dtmLuminance, dtmIntensity, dtmAlpha);
  56. // Specifies the depth comparison function.
  57. TgxDepthCompareFunc = TgxDepthFunction;
  58. (* Texture format for OpenGL (rendering) use.
  59. Internally, GLXScene handles all "base" images as 32 Bits RGBA, but you can
  60. specify a generic format to reduce OpenGL texture memory use: *)
  61. TgxTextureFormat = (
  62. tfDefault,
  63. tfRGB, // = tfRGB8
  64. tfRGBA, // = tfRGBA8
  65. tfRGB16, // = tfRGB5
  66. tfRGBA16, // = tfRGBA4
  67. tfAlpha, // = tfALPHA8
  68. tfLuminance, // = tfLUMINANCE8
  69. tfLuminanceAlpha, // = tfLUMINANCE8_ALPHA8
  70. tfIntensity, // = tfINTENSITY8
  71. tfNormalMap, // = tfRGB8
  72. tfRGBAFloat16, // = tfRGBA_FLOAT16_ATI
  73. tfRGBAFloat32, // = tfRGBA_FLOAT32_ATI
  74. tfExtended);
  75. TgxTextureCompression = TglInternalCompression;
  76. TgxTexture = class;
  77. IgxTextureNotifyAble = interface(IgxNotifyAble)
  78. ['{0D9DC0B0-ECE4-4513-A8A1-5AE7022C9426}']
  79. procedure NotifyTexMapChange(Sender: TObject);
  80. end;
  81. TgxTextureNeededEvent = procedure(Sender: TObject; var TextureFileName: string)
  82. of object;
  83. TgxTextureChange = (tcImage, tcParams);
  84. TgxTextureChanges = set of TgxTextureChange;
  85. (*Defines how and if Alpha channel is defined for a texture image.
  86. tiaDefault : uses the alpha channel in the image if any
  87. tiaAlphaFromIntensity : the alpha channel value is deduced from other
  88. RGB components intensity (the brighter, the more opaque)
  89. tiaSuperBlackTransparent : pixels with a RGB color of (0, 0, 0) are
  90. completely transparent, others are completely opaque
  91. tiaLuminance : the luminance value is calculated for each pixel
  92. and used for RGB and Alpha values
  93. tiaLuminanceSqrt : same as tiaLuminance but with an Sqrt(Luminance)
  94. tiaOpaque : alpha channel is uniformously set to 1.0
  95. tiaTopLeftPointColorTransparent : points of the same color as the
  96. top left point of the bitmap are transparent, others are opaque. *)
  97. TgxTextureImageAlpha =
  98. (
  99. tiaDefault,
  100. tiaAlphaFromIntensity,
  101. tiaSuperBlackTransparent,
  102. tiaLuminance,
  103. tiaLuminanceSqrt,
  104. tiaOpaque,
  105. tiaTopLeftPointColorTransparent,
  106. tiaInverseLuminance,
  107. tiaInverseLuminanceSqrt,
  108. tiaBottomRightPointColorTransparent
  109. );
  110. (*Base class for texture image data.
  111. Basicly, subclasses are to be considered as different ways of getting
  112. a HBitmap (interfacing the actual source).
  113. SubClasses should be registered using RegisterTextureImageClass to allow
  114. proper persistence and editability in the IDE experts. *)
  115. TgxTextureImage = class(TgxUpdateAbleObject)
  116. private
  117. function GetResourceName: string;
  118. protected
  119. FOwnerTexture: TgxTexture;
  120. FOnTextureNeeded: TgxTextureNeededEvent;
  121. FResourceFile: string;
  122. class function IsSelfLoading: Boolean; virtual;
  123. procedure LoadTexture(AInternalFormat: TglInternalFormat); virtual;
  124. function GetTextureTarget: TglTextureTarget; virtual;
  125. function GetHeight: Integer; virtual;
  126. function GetWidth: Integer; virtual;
  127. function GetDepth: Integer; virtual;
  128. property OnTextureNeeded: TgxTextureNeededEvent read FOnTextureNeeded write FOnTextureNeeded;
  129. public
  130. constructor Create(AOwner: TPersistent); override;
  131. destructor Destroy; override;
  132. property OwnerTexture: TgxTexture read FOwnerTexture write FOwnerTexture;
  133. procedure NotifyChange(Sender: TObject); override;
  134. (*Save textureImage to file.
  135. This may not save a picture, but for instance, parameters, if the
  136. textureImage is a procedural texture. *)
  137. procedure SaveToFile(const fileName: string); virtual;
  138. (*Load textureImage from a file.
  139. This may not load a picture, but for instance, parameters, if the
  140. textureImage is a procedural texture.
  141. Subclasses should invoke inherited which will take care of the
  142. "OnTextureNeeded" stuff. *)
  143. procedure LoadFromFile(const fileName: string); virtual;
  144. (*Returns a user-friendly denomination for the class.
  145. This denomination is used for picking a texture image class
  146. in the IDE expert. *)
  147. class function FriendlyName: string; virtual;
  148. (*Returns a user-friendly description for the class.
  149. This denomination is used for helping the user when picking a
  150. texture image class in the IDE expert. If it's not overriden,
  151. takes its value from FriendlyName. *)
  152. class function FriendlyDescription: string; virtual;
  153. // Request reload/refresh of data upon next use.
  154. procedure Invalidate; virtual;
  155. (*Returns image's bitmap handle.
  156. If the actual image is not a windows bitmap (BMP), descendants should
  157. take care of properly converting to bitmap. *)
  158. function GetBitmap32: TgxImage; virtual;
  159. (*Request for unloading bitmapData, to free some memory.
  160. This one is invoked when one no longer needs the Bitmap data
  161. it got through a call to GetHBitmap.
  162. Subclasses may ignore this call if the HBitmap was obtained at
  163. no particular memory cost. *)
  164. procedure ReleaseBitmap32; virtual;
  165. // AsBitmap : Returns the TextureImage as a TBitmap
  166. function AsBitmap: TBitmap;
  167. procedure AssignToBitmap(aBitmap: TBitmap);
  168. property Width: Integer read GetWidth;
  169. property Height: Integer read GetHeight;
  170. property Depth: Integer read GetDepth;
  171. //Native OpenGL texture target.
  172. property NativeTextureTarget: TglTextureTarget read GetTextureTarget;
  173. property ResourceName: string read GetResourceName;
  174. end;
  175. TgxTextureImageClass = class of TgxTextureImage;
  176. (* A texture image with no specified content, only a size.
  177. This texture image type is of use if the context of your texture is
  178. calculated at run-time (with a TgxMemoryViewer for instance). *)
  179. TgxBlankImage = class(TgxTextureImage)
  180. private
  181. procedure SetWidth(val: Integer);
  182. procedure SetHeight(val: Integer);
  183. procedure SetDepth(val: Integer);
  184. procedure SetCubeMap(const val: Boolean);
  185. procedure SetArray(const val: Boolean);
  186. protected
  187. fBitmap: TgxImage;
  188. fWidth, fHeight, fDepth: Integer;
  189. // Store a icolor format, because fBitmap is not always defined
  190. fColorFormat: Cardinal;
  191. // Blank Cube Map
  192. fCubeMap: Boolean;
  193. // Flag to interparate depth as layer
  194. fArray: Boolean;
  195. function GetWidth: Integer; override;
  196. function GetHeight: Integer; override;
  197. function GetDepth: Integer; override;
  198. function GetTextureTarget: TglTextureTarget; override;
  199. public
  200. constructor Create(AOwner: TPersistent); override;
  201. destructor Destroy; override;
  202. procedure Assign(Source: TPersistent); override;
  203. function GetBitmap32: TgxImage; override;
  204. procedure ReleaseBitmap32; override;
  205. procedure SaveToFile(const fileName: string); override;
  206. procedure LoadFromFile(const fileName: string); override;
  207. class function FriendlyName: string; override;
  208. class function FriendlyDescription: string; override;
  209. published
  210. // Width, heigth and depth of the blank image (for memory allocation).
  211. property Width: Integer read GetWidth write SetWidth default 256;
  212. property Height: Integer read GetHeight write SetHeight default 256;
  213. property Depth: Integer read GetDepth write SetDepth default 0;
  214. property CubeMap: Boolean read fCubeMap write SetCubeMap default false;
  215. property TextureArray: Boolean read fArray write SetArray default false;
  216. property ColorFormat: Cardinal read fColorFormat write fColorFormat;
  217. end;
  218. // Base class for image data classes internally based on a TgxPicture.
  219. TgxPictureImage = class(TgxTextureImage)
  220. private
  221. FBitmap: TgxImage;
  222. FVKPicture: TImage;
  223. FUpdateCounter: Integer;
  224. protected
  225. function GetHeight: Integer; override;
  226. function GetWidth: Integer; override;
  227. function GetDepth: Integer; override;
  228. function GetTextureTarget: TglTextureTarget; override;
  229. function GetPicture: TImage;
  230. procedure SetPicture(const aPicture: TImage);
  231. procedure PictureChanged(Sender: TObject);
  232. public
  233. constructor Create(AOwner: TPersistent); override;
  234. destructor Destroy; override;
  235. procedure Assign(Source: TPersistent); override;
  236. (* Use this function if you are going to modify the Picture directly.
  237. Each invokation MUST be balanced by a call to EndUpdate. *)
  238. procedure BeginUpdate;
  239. // Ends a direct picture modification session. Follows a BeginUpdate.
  240. procedure EndUpdate;
  241. function GetBitmap32: TgxImage; override;
  242. procedure ReleaseBitmap32; override;
  243. // Holds the image content.
  244. property Picture: TImage read GetPicture write SetPicture;
  245. end;
  246. (* Stores any image compatible with Delphi's TgxPicture mechanism.
  247. The picture's data is actually stored into the DFM, the original
  248. picture name or path is not remembered. It is similar in behaviour
  249. to Delphi's TImage.
  250. Note that if original image is for instance JPEG format, only the JPEG
  251. data will be stored in the DFM (compact) *)
  252. TgxPersistentImage = class(TgxPictureImage)
  253. public
  254. constructor Create(AOwner: TPersistent); override;
  255. destructor Destroy; override;
  256. procedure SaveToFile(const fileName: string); override;
  257. procedure LoadFromFile(const fileName: string); override;
  258. class function FriendlyName: string; override;
  259. class function FriendlyDescription: string; override;
  260. property NativeTextureTarget;
  261. published
  262. property Picture;
  263. end;
  264. (* Uses a picture whose data is found in a file (only filename is stored).
  265. The image is unloaded after upload to OpenGL. *)
  266. TgxPicFileImage = class(TgxPictureImage)
  267. private
  268. FPictureFileName: string;
  269. FAlreadyWarnedAboutMissingFile: Boolean;
  270. FWidth: Integer;
  271. FHeight: Integer;
  272. protected
  273. procedure SetPictureFileName(const val: string);
  274. function GetWidth: Integer; override;
  275. function GetHeight: Integer; override;
  276. function GetDepth: Integer; override;
  277. public
  278. constructor Create(AOwner: TPersistent); override;
  279. destructor Destroy; override;
  280. procedure Assign(Source: TPersistent); override;
  281. // Only picture file name is saved
  282. procedure SaveToFile(const fileName: string); override;
  283. (* Load picture file name or use fileName as picture filename.
  284. The autodetection is based on the filelength and presence of zeros. *)
  285. procedure LoadFromFile(const fileName: string); override;
  286. class function FriendlyName: string; override;
  287. class function FriendlyDescription: string; override;
  288. property NativeTextureTarget;
  289. function GetBitmap32: TgxImage; override;
  290. procedure Invalidate; override;
  291. published
  292. // Filename of the picture to use.
  293. property PictureFileName: string read FPictureFileName write SetPictureFileName;
  294. end;
  295. TgxCubeMapTarget = Integer;
  296. (* A texture image used for specifying and stroing a cube map.
  297. Not unlike TgxPictureImage, but storing 6 of them instead of just one.
  298. Saving & loading as a whole currently not supported. *)
  299. TgxCubeMapImage = class(TgxTextureImage)
  300. private
  301. FImage: TgxImage;
  302. FUpdateCounter: Integer;
  303. FPicture: array[cmtPX..cmtNZ] of TImage;
  304. protected
  305. function GetWidth: Integer; override;
  306. function GetHeight: Integer; override;
  307. function GetDepth: Integer; override;
  308. procedure SetPicture(index: TgxCubeMapTarget; const val: TImage);
  309. function GetPicture(index: TgxCubeMapTarget): TImage;
  310. function GetTextureTarget: TglTextureTarget; override;
  311. procedure PictureChanged(Sender: TObject);
  312. public
  313. constructor Create(AOwner: TPersistent); override;
  314. destructor Destroy; override;
  315. procedure Assign(Source: TPersistent); override;
  316. function GetBitmap32: TgxImage; override;
  317. procedure ReleaseBitmap32; override;
  318. (* Use this function if you are going to modify the Picture directly.
  319. Each invokation MUST be balanced by a call to EndUpdate. *)
  320. procedure BeginUpdate;
  321. procedure EndUpdate;
  322. procedure SaveToFile(const fileName: string); override;
  323. procedure LoadFromFile(const fileName: string); override;
  324. class function FriendlyName: string; override;
  325. class function FriendlyDescription: string; override;
  326. property NativeTextureTarget;
  327. // Indexed access to the cube map's sub pictures.
  328. property Picture[index: TgxCubeMapTarget]: TImage read GetPicture write SetPicture;
  329. published
  330. property PicturePX: TImage index cmtPX read GetPicture write SetPicture;
  331. property PictureNX: TImage index cmtNX read GetPicture write SetPicture;
  332. property PicturePY: TImage index cmtPY read GetPicture write SetPicture;
  333. property PictureNY: TImage index cmtNY read GetPicture write SetPicture;
  334. property PicturePZ: TImage index cmtPZ read GetPicture write SetPicture;
  335. property PictureNZ: TImage index cmtNZ read GetPicture write SetPicture;
  336. end;
  337. TgxTextureMappingMode = (tmmUser, tmmObjectLinear, tmmEyeLinear, tmmSphere,
  338. tmmCubeMapReflection, tmmCubeMapNormal, tmmCubeMapLight0, tmmCubeMapCamera);
  339. (* Defines basic texturing properties.
  340. You can control texture wrapping, smoothing/filtering and of course define
  341. the texture map (note that texturing is disabled by default).
  342. A built-in mechanism (through ImageAlpha) allows auto-generation of an
  343. Alpha channel for all bitmaps (see TgxTextureImageAlpha). *)
  344. TgxTexture = class(TgxUpdateAbleObject)
  345. private
  346. FTextureHandle: TgxTextureHandle;
  347. FSamplerHandle: TgxVirtualHandle;
  348. FTextureFormat: TglInternalFormat;
  349. FTextureMode: TgxTextureMode;
  350. FTextureWrap: TgxTextureWrap;
  351. FMinFilter: TgxMinFilter;
  352. FMagFilter: TgxMagFilter;
  353. FDisabled: Boolean;
  354. FImage: TgxTextureImage;
  355. FImageAlpha: TgxTextureImageAlpha;
  356. FImageBrightness: Single;
  357. FImageGamma: Single;
  358. FMappingMode: TgxTextureMappingMode;
  359. FMapSCoordinates: TgxCoordinates4;
  360. FMapTCoordinates: TgxCoordinates4;
  361. FMapRCoordinates: TgxCoordinates4;
  362. FMapQCoordinates: TgxCoordinates4;
  363. FOnTextureNeeded: TgxTextureNeededEvent;
  364. FCompression: TgxTextureCompression;
  365. FRequiredMemorySize: Integer;
  366. FFilteringQuality: TglTextureFilteringQuality;
  367. FTexWidth: Integer;
  368. FTexHeight: Integer;
  369. FTexDepth: Integer;
  370. FEnvColor: TgxColor;
  371. FBorderColor: TgxColor;
  372. FNormalMapScale: Single;
  373. FTextureWrapS: TglSeparateTextureWrap;
  374. FTextureWrapT: TglSeparateTextureWrap;
  375. FTextureWrapR: TglSeparateTextureWrap;
  376. fTextureCompareMode: TglTextureCompareMode;
  377. fTextureCompareFunc: TgxDepthCompareFunc;
  378. fDepthTextureMode: TgxDepthTextureMode;
  379. FKeepImageAfterTransfer: Boolean;
  380. protected
  381. procedure SetImage(AValue: TgxTextureImage);
  382. procedure SetImageAlpha(const val: TgxTextureImageAlpha);
  383. procedure SetImageBrightness(const val: Single);
  384. function StoreBrightness: Boolean;
  385. procedure SetImageGamma(const val: Single);
  386. function StoreGamma: Boolean;
  387. procedure SetMagFilter(AValue: TgxMagFilter);
  388. procedure SetMinFilter(AValue: TgxMinFilter);
  389. procedure SetTextureMode(AValue: TgxTextureMode);
  390. procedure SetTextureWrap(AValue: TgxTextureWrap);
  391. procedure SetTextureWrapS(AValue: TglSeparateTextureWrap);
  392. procedure SetTextureWrapT(AValue: TglSeparateTextureWrap);
  393. procedure SetTextureWrapR(AValue: TglSeparateTextureWrap);
  394. function GetTextureFormat: TgxTextureFormat;
  395. procedure SetTextureFormat(const val: TgxTextureFormat);
  396. procedure SetTextureFormatEx(const val: TglInternalFormat);
  397. function StoreTextureFormatEx: Boolean;
  398. procedure SetCompression(const val: TgxTextureCompression);
  399. procedure SetFilteringQuality(const val: TglTextureFilteringQuality);
  400. procedure SetMappingMode(const val: TgxTextureMappingMode);
  401. function GetMappingSCoordinates: TgxCoordinates4;
  402. procedure SetMappingSCoordinates(const val: TgxCoordinates4);
  403. function StoreMappingSCoordinates: Boolean;
  404. function GetMappingTCoordinates: TgxCoordinates4;
  405. procedure SetMappingTCoordinates(const val: TgxCoordinates4);
  406. function StoreMappingTCoordinates: Boolean;
  407. function GetMappingRCoordinates: TgxCoordinates4;
  408. procedure SetMappingRCoordinates(const val: TgxCoordinates4);
  409. function StoreMappingRCoordinates: Boolean;
  410. function GetMappingQCoordinates: TgxCoordinates4;
  411. procedure SetMappingQCoordinates(const val: TgxCoordinates4);
  412. function StoreMappingQCoordinates: Boolean;
  413. procedure SetDisabled(AValue: Boolean);
  414. procedure SetEnabled(const val: Boolean);
  415. function GetEnabled: Boolean;
  416. procedure SetEnvColor(const val: TgxColor);
  417. procedure SetBorderColor(const val: TgxColor);
  418. procedure SetNormalMapScale(const val: Single);
  419. procedure SetTextureCompareMode(const val: TglTextureCompareMode);
  420. procedure SetTextureCompareFunc(const val: TgxDepthCompareFunc);
  421. procedure SetDepthTextureMode(const val: TgxDepthTextureMode);
  422. function StoreNormalMapScale: Boolean;
  423. function StoreImageClassName: Boolean;
  424. function GetHandle: Cardinal; virtual;
  425. // Load texture to OpenGL subsystem
  426. procedure PrepareImage(target: Cardinal); virtual;
  427. // Setup OpenGL texture parameters
  428. procedure PrepareParams(target: Cardinal); virtual;
  429. procedure DoOnTextureNeeded(Sender: TObject; var textureFileName: string);
  430. procedure OnSamplerAllocate(Sender: TgxVirtualHandle; var Handle: Cardinal);
  431. procedure OnSamplerDestroy(Sender: TgxVirtualHandle; var Handle: Cardinal);
  432. // Shows a special image that indicates an error
  433. procedure SetTextureErrorImage;
  434. public
  435. constructor Create(AOwner: TPersistent); override;
  436. destructor Destroy; override;
  437. property OnTextureNeeded: TgxTextureNeededEvent read FOnTextureNeeded write
  438. FOnTextureNeeded;
  439. procedure PrepareBuildList;
  440. procedure ApplyMappingMode;
  441. procedure UnApplyMappingMode;
  442. procedure Apply(var rci: TgxRenderContextInfo);
  443. procedure UnApply(var rci: TgxRenderContextInfo);
  444. // Applies to TEXTURE1
  445. procedure ApplyAsTexture2(var rci: TgxRenderContextInfo; textureMatrix: PMatrix4f = nil);
  446. procedure UnApplyAsTexture2(var rci: TgxRenderContextInfo;
  447. reloadIdentityTextureMatrix: boolean);
  448. {N=1 for TEXTURE0, N=2 for TEXTURE1, etc. }
  449. procedure ApplyAsTextureN(n: Integer; var rci: TgxRenderContextInfo;
  450. textureMatrix: PMatrix4f = nil);
  451. procedure UnApplyAsTextureN(n: Integer; var rci: TgxRenderContextInfo;
  452. reloadIdentityTextureMatrix: boolean);
  453. procedure Assign(Source: TPersistent); override;
  454. procedure NotifyChange(Sender: TObject); override;
  455. procedure NotifyImageChange;
  456. procedure NotifyParamsChange;
  457. procedure DestroyHandles;
  458. procedure SetImageClassName(const val: string);
  459. function GetImageClassName: string;
  460. (* Returns the OpenGL memory used by the texture.
  461. The compressed size is returned if, and only if texture compression
  462. if active and possible, and the texture has been allocated (Handle
  463. is defined), otherwise the estimated size (from TextureFormat
  464. specification) is returned. *)
  465. function TextureImageRequiredMemory: Integer;
  466. (* Allocates the texture handle if not already allocated.
  467. The texture is binded and parameters are setup, but no image data
  468. is initialized by this call - for expert use only. *)
  469. function AllocateHandle: Cardinal;
  470. function IsHandleAllocated: Boolean;
  471. // Returns OpenGL texture format corresponding to current options.
  472. function OpenGLTextureFormat: Integer;
  473. //Returns if of float data type
  474. function IsFloatType: Boolean;
  475. // Is the texture enabled? Always equals to 'not Disabled'.
  476. property Enabled: Boolean read GetEnabled write SetEnabled;
  477. (* Handle to the OpenGL texture object.
  478. If the handle hasn't already been allocated, it will be allocated
  479. by this call (ie. do not use if no OpenGL context is active!) *)
  480. property Handle: Cardinal read GetHandle;
  481. property TextureHandle: TgxTextureHandle read FTextureHandle;
  482. // Actual width, height and depth used for last texture specification binding.
  483. property TexWidth: Integer read FTexWidth;
  484. property TexHeight: Integer read FTexHeight;
  485. property TexDepth: Integer read FTexDepth;
  486. //Give texture rendering context
  487. published
  488. (* Image ClassName for enabling True polymorphism.
  489. This is ugly, but since the default streaming mechanism does a
  490. really bad job at storing polymorphic owned-object properties,
  491. and neither TFiler nor TgxPicture allow proper use of the built-in
  492. streaming, that's the only way I found to allow a user-extensible
  493. mechanism. *)
  494. property ImageClassName: string read GetImageClassName write
  495. SetImageClassName stored StoreImageClassName;
  496. // Image data for the texture.
  497. property Image: TgxTextureImage read FImage write SetImage;
  498. (* Automatic Image Alpha setting.
  499. Allows to control how and if the image's Alpha channel (transparency)
  500. is computed. *)
  501. property ImageAlpha: TgxTextureImageAlpha read FImageAlpha write
  502. SetImageAlpha default tiaDefault;
  503. (* Texture brightness correction.
  504. This correction is applied upon loading a TgxTextureImage, it's a
  505. simple saturating scaling applied to the RGB components of
  506. the 32 bits image, before it is passed to OpenGL, and before
  507. gamma correction (if any). *)
  508. property ImageBrightness: Single read FImageBrightness write
  509. SetImageBrightness stored StoreBrightness;
  510. (* Texture gamma correction.
  511. The gamma correction is applied upon loading a TgxTextureImage,
  512. applied to the RGB components of the 32 bits image, before it is
  513. passed to OpenGL, after brightness correction (if any). *)
  514. property ImageGamma: Single read FImageGamma write SetImageGamma stored StoreGamma;
  515. // Texture magnification filter.
  516. property MagFilter: TgxMagFilter read FMagFilter write SetMagFilter default maLinear;
  517. // Texture minification filter.
  518. property MinFilter: TgxMinFilter read FMinFilter write SetMinFilter default miLinearMipMapLinear;
  519. // Texture application mode.
  520. property TextureMode: TgxTextureMode read FTextureMode write SetTextureMode default tmDecal;
  521. // Wrapping mode for the texture.
  522. property TextureWrap: TgxTextureWrap read FTextureWrap write SetTextureWrap default twBoth;
  523. // Wrapping mode for the texture when TextureWrap=twSeparate.
  524. property TextureWrapS: TglSeparateTextureWrap read FTextureWrapS write
  525. SetTextureWrapS default twRepeat;
  526. property TextureWrapT: TglSeparateTextureWrap read FTextureWrapT write
  527. SetTextureWrapT default twRepeat;
  528. property TextureWrapR: TglSeparateTextureWrap read FTextureWrapR write
  529. SetTextureWrapR default twRepeat;
  530. // Texture format for use by the renderer. See TgxTextureFormat for details.
  531. property TextureFormat: TgxTextureFormat read GetTextureFormat write
  532. SetTextureFormat default tfDefault;
  533. property TextureFormatEx: TglInternalFormat read FTextureFormat write
  534. SetTextureFormatEx stored StoreTextureFormatEx;
  535. (* Texture compression control.
  536. If True the compressed TextureFormat variant (the OpenGL ICD must
  537. support GL_ARB_texture_compression, or this option is ignored). *)
  538. property Compression: TgxTextureCompression read FCompression write
  539. SetCompression default tcDefault;
  540. (*Specifies texture filtering quality.
  541. You can choose between bilinear and trilinear filetring (anisotropic).
  542. The OpenGL ICD must support GL_EXT_texture_filter_anisotropic or
  543. this property is ignored. *)
  544. property FilteringQuality: TglTextureFilteringQuality read FFilteringQuality
  545. write SetFilteringQuality default tfIsotropic;
  546. (* Texture coordinates mapping mode.
  547. This property controls automatic texture coordinates generation. *)
  548. property MappingMode: TgxTextureMappingMode read FMappingMode write
  549. SetMappingMode default tmmUser;
  550. (* Texture mapping coordinates mode for S, T, R and Q axis.
  551. This property stores the coordinates for automatic texture
  552. coordinates generation. *)
  553. property MappingSCoordinates: TgxCoordinates4 read GetMappingSCoordinates
  554. write SetMappingSCoordinates stored StoreMappingSCoordinates;
  555. property MappingTCoordinates: TgxCoordinates4 read GetMappingTCoordinates
  556. write SetMappingTCoordinates stored StoreMappingTCoordinates;
  557. property MappingRCoordinates: TgxCoordinates4 read GetMappingRCoordinates
  558. write SetMappingRCoordinates stored StoreMappingRCoordinates;
  559. property MappingQCoordinates: TgxCoordinates4 read GetMappingQCoordinates
  560. write SetMappingQCoordinates stored StoreMappingQCoordinates;
  561. // Texture Environment color.
  562. property EnvColor: TgxColor read FEnvColor write SetEnvColor;
  563. // Texture Border color.
  564. property BorderColor: TgxColor read FBorderColor write SetBorderColor;
  565. // If true, the texture is disabled (not used).
  566. property Disabled: Boolean read FDisabled write SetDisabled default True;
  567. (* Normal Map scaling.
  568. Only applies when TextureFormat is tfNormalMap, this property defines
  569. the scaling that is applied during normal map generation (ie. controls
  570. the intensity of the bumps). *)
  571. property NormalMapScale: Single read FNormalMapScale write SetNormalMapScale
  572. stored StoreNormalMapScale;
  573. property TextureCompareMode: TglTextureCompareMode read fTextureCompareMode
  574. write SetTextureCompareMode default tcmNone;
  575. property TextureCompareFunc: TgxDepthCompareFunc read fTextureCompareFunc
  576. write SetTextureCompareFunc default cfLequal;
  577. property DepthTextureMode: TgxDepthTextureMode read fDepthTextureMode write
  578. SetDepthTextureMode default dtmLuminance;
  579. // Disable image release after transfering it to VGA.
  580. property KeepImageAfterTransfer: Boolean read FKeepImageAfterTransfer
  581. write FKeepImageAfterTransfer default False;
  582. end;
  583. TgxTextureExItem = class(TCollectionItem, IgxTextureNotifyAble)
  584. private
  585. FTexture: TgxTexture;
  586. FTextureIndex: Integer;
  587. FTextureOffset, FTextureScale: TgxCoordinates;
  588. FTextureMatrixIsIdentity: Boolean;
  589. FTextureMatrix: TMatrix4f;
  590. FApplied: Boolean;
  591. //implementing IInterface
  592. function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
  593. function _AddRef: Integer; stdcall;
  594. function _Release: Integer; stdcall;
  595. protected
  596. function GetDisplayName: string; override;
  597. function GetOwner: TPersistent; override;
  598. procedure SetTexture(const Value: TgxTexture);
  599. procedure SetTextureIndex(const Value: Integer);
  600. procedure SetTextureOffset(const Value: TgxCoordinates);
  601. procedure SetTextureScale(const Value: TgxCoordinates);
  602. procedure NotifyTexMapChange(Sender: TObject);
  603. procedure CalculateTextureMatrix;
  604. procedure OnNotifyChange(Sender: TObject);
  605. public
  606. constructor Create(ACollection: TCollection); override;
  607. destructor Destroy; override;
  608. procedure Assign(Source: TPersistent); override;
  609. procedure NotifyChange(Sender: TObject);
  610. procedure Apply(var rci: TgxRenderContextInfo);
  611. procedure UnApply(var rci: TgxRenderContextInfo);
  612. published
  613. property Texture: TgxTexture read FTexture write SetTexture;
  614. property TextureIndex: Integer read FTextureIndex write SetTextureIndex;
  615. property TextureOffset: TgxCoordinates read FTextureOffset write SetTextureOffset;
  616. property TextureScale: TgxCoordinates read FTextureScale write SetTextureScale;
  617. end;
  618. TgxTextureEx = class(TCollection)
  619. private
  620. FOwner: TgxUpdateAbleObject;
  621. protected
  622. procedure SetItems(index: Integer; const Value: TgxTextureExItem);
  623. function GetItems(index: Integer): TgxTextureExItem;
  624. function GetOwner: TPersistent; override;
  625. public
  626. constructor Create(AOwner: TgxUpdateAbleObject);
  627. procedure NotifyChange(Sender: TObject);
  628. procedure Apply(var rci: TgxRenderContextInfo);
  629. procedure UnApply(var rci: TgxRenderContextInfo);
  630. function IsTextureEnabled(Index: Integer): Boolean;
  631. function Add: TgxTextureExItem;
  632. property Items[index: Integer]: TgxTextureExItem read GetItems write
  633. SetItems; default;
  634. procedure Loaded;
  635. end;
  636. ETexture = class(Exception);
  637. EShaderException = class(Exception);
  638. // Register a TgxTextureImageClass (used for persistence and IDE purposes)
  639. procedure RegisterTextureImageClass(textureImageClass: TgxTextureImageClass);
  640. // Finds a registerer TgxTextureImageClass using its classname
  641. function FindTextureImageClass(const className: string): TgxTextureImageClass;
  642. // Finds a registerer TgxTextureImageClass using its FriendlyName
  643. function FindTextureImageClassByFriendlyName(const friendlyName: string):
  644. TgxTextureImageClass;
  645. // Defines a TStrings with the list of registered TgxTextureImageClass.
  646. procedure SetTextureImageClassesToStrings(aStrings: TStrings);
  647. (* Creates a TStrings with the list of registered TgxTextureImageClass.
  648. To be freed by caller. *)
  649. function GetTextureImageClassesAsStrings: TStrings;
  650. procedure RegisterTGraphicClassFileExtension(const extension: string;
  651. const aClass: TGraphicClass);
  652. function CreateGraphicFromFile(const fileName: string): TBitmap;
  653. //------------------------------------------------------------------------------
  654. implementation
  655. //------------------------------------------------------------------------------
  656. uses
  657. GXS.Scene, // TODO: remove dependancy on Scene.pas unit (related to tmmCubeMapLight0)
  658. GXS.PictureRegisteredFormats;
  659. const
  660. cTextureMode: array[tmDecal..tmAdd] of Cardinal =
  661. (GL_DECAL, GL_MODULATE, GL_BLEND, GL_REPLACE, GL_ADD);
  662. cOldTextureFormatToInternalFormat: array[tfRGB..tfRGBAFloat32] of
  663. TglInternalFormat = (
  664. tfRGB8,
  665. tfRGBA8,
  666. tfRGB5,
  667. tfRGBA4,
  668. tfALPHA8,
  669. tfLUMINANCE8,
  670. tfLUMINANCE8_ALPHA8,
  671. tfINTENSITY8,
  672. tfRGB8,
  673. tfRGBA_FLOAT16,
  674. tfRGBA_FLOAT32);
  675. var
  676. vGxTextureImageClasses: TList;
  677. vTGraphicFileExtension: array of string;
  678. vTGraphicClass: array of TGraphicClass;
  679. type
  680. TFriendlyImage = class(TgxBaseImage);
  681. // Dummy methods for CPP
  682. //
  683. function TgxTextureImage.GetTextureTarget: TglTextureTarget;
  684. begin
  685. end;
  686. function TgxTextureImage.GetHeight: Integer;
  687. begin
  688. Result := 0;
  689. end;
  690. function TgxTextureImage.GetWidth: Integer;
  691. begin
  692. Result := 0;
  693. end;
  694. function TgxTextureImage.GetDepth: Integer;
  695. begin
  696. Result := 0;
  697. end;
  698. procedure TgxTextureImage.SaveToFile(const FileName: String);
  699. begin
  700. end;
  701. class function TgxTextureImage.FriendlyName: String;
  702. begin
  703. Result := '';
  704. end;
  705. function TgxTextureImage.GetBitmap32: TgxImage;
  706. begin
  707. Result := nil;
  708. end;
  709. procedure RegisterTGraphicClassFileExtension(const extension: string;
  710. const aClass: TGraphicClass);
  711. var
  712. n: Integer;
  713. begin
  714. n := Length(vTGraphicFileExtension);
  715. SetLength(vTGraphicFileExtension, n + 1);
  716. SetLength(vTGraphicClass, n + 1);
  717. vTGraphicFileExtension[n] := LowerCase(extension);
  718. vTGraphicClass[n] := aClass;
  719. end;
  720. function CreateGraphicFromFile(const fileName: string): TBitmap;
  721. var
  722. i: Integer;
  723. ext: string;
  724. fs: TStream;
  725. graphicClass: TGraphicClass;
  726. begin
  727. Result := nil;
  728. if FileStreamExists(fileName) then
  729. begin
  730. graphicClass := nil;
  731. ext := LowerCase(ExtractFileExt(fileName));
  732. for i := 0 to High(vTGraphicFileExtension) do
  733. begin
  734. if vTGraphicFileExtension[i] = ext then
  735. begin
  736. graphicClass := TGraphicClass(vTGraphicClass[i]);
  737. Break;
  738. end;
  739. end;
  740. if graphicClass = nil then
  741. graphicClass := GraphicClassForExtension(ext);
  742. if graphicClass <> nil then
  743. begin
  744. Result := graphicClass.Create;
  745. try
  746. fs := TFileStream.Create(fileName, fmOpenRead);
  747. try
  748. Result.LoadFromStream(fs);
  749. finally
  750. fs.Free;
  751. end;
  752. except
  753. FreeAndNil(Result);
  754. raise;
  755. end;
  756. end;
  757. end;
  758. end;
  759. procedure RegisterTextureImageClass(textureImageClass: TgxTextureImageClass);
  760. begin
  761. if not Assigned(vGxTextureImageClasses) then
  762. vGxTextureImageClasses := TList.Create;
  763. vGxTextureImageClasses.Add(textureImageClass);
  764. end;
  765. function FindTextureImageClass(const className: string): TgxTextureImageClass;
  766. var
  767. i: Integer;
  768. tic: TgxTextureImageClass;
  769. begin
  770. Result := nil;
  771. if Assigned(vGxTextureImageClasses) then
  772. for i := 0 to vGxTextureImageClasses.Count - 1 do
  773. begin
  774. tic := TgxTextureImageClass(vGxTextureImageClasses[i]);
  775. if tic.ClassName = className then
  776. begin
  777. Result := tic;
  778. Break;
  779. end;
  780. end;
  781. end;
  782. function FindTextureImageClassByFriendlyName(const friendlyName: string):
  783. TgxTextureImageClass;
  784. var
  785. i: Integer;
  786. tic: TgxTextureImageClass;
  787. begin
  788. Result := nil;
  789. if Assigned(vGxTextureImageClasses) then
  790. for i := 0 to vGxTextureImageClasses.Count - 1 do
  791. begin
  792. tic := TgxTextureImageClass(vGxTextureImageClasses[i]);
  793. if tic.FriendlyName = friendlyName then
  794. begin
  795. Result := tic;
  796. Break;
  797. end;
  798. end;
  799. end;
  800. procedure SetTextureImageClassesToStrings(aStrings: TStrings);
  801. var
  802. i: Integer;
  803. tic: TgxTextureImageClass;
  804. begin
  805. with aStrings do
  806. begin
  807. BeginUpdate;
  808. Clear;
  809. if Assigned(vGxTextureImageClasses) then
  810. for i := 0 to vGxTextureImageClasses.Count - 1 do
  811. begin
  812. tic := TgxTextureImageClass(vGxTextureImageClasses[i]);
  813. AddObject(tic.FriendlyName, TObject(Pointer(tic)));
  814. end;
  815. EndUpdate;
  816. end;
  817. end;
  818. function GetTextureImageClassesAsStrings: TStrings;
  819. begin
  820. Result := TStringList.Create;
  821. SetTextureImageClassesToStrings(Result);
  822. end;
  823. // ------------------
  824. // ------------------ TgxTextureImage ------------------
  825. // ------------------
  826. constructor TgxTextureImage.Create(AOwner: TPersistent);
  827. begin
  828. inherited;
  829. FOwnerTexture := (AOwner as TgxTexture);
  830. end;
  831. destructor TgxTextureImage.Destroy;
  832. begin
  833. inherited Destroy;
  834. end;
  835. class function TgxTextureImage.FriendlyDescription: string;
  836. begin
  837. Result := FriendlyName;
  838. end;
  839. procedure TgxTextureImage.Invalidate;
  840. begin
  841. ReleaseBitmap32;
  842. NotifyChange(Self);
  843. end;
  844. procedure TgxTextureImage.ReleaseBitmap32;
  845. begin
  846. // nothing here.
  847. end;
  848. // AsBitmap : Returns the TextureImage as a TBitmap
  849. // WARNING: This Creates a new bitmap. Remember to free it, to prevent leaks.
  850. // If possible, rather use AssignToBitmap.
  851. //
  852. function TgxTextureImage.AsBitmap: TBitmap;
  853. begin
  854. result := self.GetBitmap32.Create32BitsBitmap;
  855. end;
  856. procedure TgxTextureImage.AssignToBitmap(aBitmap: TBitmap);
  857. begin
  858. Self.GetBitmap32.AssignToBitmap(aBitmap);
  859. end;
  860. procedure TgxTextureImage.NotifyChange(Sender: TObject);
  861. begin
  862. if Assigned(FOwnerTexture) then
  863. begin
  864. FOwnerTexture.FTextureHandle.NotifyChangesOfData;
  865. FOwnerTexture.FSamplerHandle.NotifyChangesOfData;
  866. // Check for texture target change
  867. GetTextureTarget;
  868. FOwnerTexture.NotifyChange(Self);
  869. end;
  870. end;
  871. procedure TgxTextureImage.LoadFromFile(const fileName: string);
  872. var
  873. buf: string;
  874. begin
  875. if Assigned(FOnTextureNeeded) then
  876. begin
  877. buf := fileName;
  878. FOnTextureNeeded(Self, buf);
  879. end;
  880. end;
  881. function TgxTextureImage.GetResourceName: string;
  882. begin
  883. Result := FResourceFile;
  884. end;
  885. class function TgxTextureImage.IsSelfLoading: Boolean;
  886. begin
  887. Result := False;
  888. end;
  889. procedure TgxTextureImage.LoadTexture(AInternalFormat: TglInternalFormat);
  890. begin
  891. end;
  892. // ------------------
  893. // ------------------ TgxBlankImage ------------------
  894. // ------------------
  895. constructor TgxBlankImage.Create(AOwner: TPersistent);
  896. begin
  897. inherited;
  898. fWidth := 256;
  899. fHeight := 256;
  900. fDepth := 0;
  901. fColorFormat := GL_RGBA;
  902. end;
  903. destructor TgxBlankImage.Destroy;
  904. begin
  905. ReleaseBitmap32;
  906. inherited Destroy;
  907. end;
  908. procedure TgxBlankImage.Assign(Source: TPersistent);
  909. var
  910. img: TgxBlankImage;
  911. begin
  912. if Assigned(Source) then
  913. begin
  914. if (Source is TgxBlankImage) then
  915. begin
  916. img := Source as TgxBlankImage;
  917. FWidth := img.Width;
  918. FHeight := img.Height;
  919. FDepth := img.Depth;
  920. FCubeMap := img.fCubeMap;
  921. FArray := img.fArray;
  922. fColorFormat := img.ColorFormat;
  923. FResourceFile := img.ResourceName;
  924. Invalidate;
  925. end
  926. else
  927. GetBitmap32.Assign(Source);
  928. NotifyChange(Self);
  929. end
  930. else
  931. inherited;
  932. end;
  933. procedure TgxBlankImage.SetWidth(val: Integer);
  934. begin
  935. if val <> FWidth then
  936. begin
  937. FWidth := val;
  938. if FWidth < 1 then
  939. FWidth := 1;
  940. Invalidate;
  941. end;
  942. end;
  943. function TgxBlankImage.GetWidth: Integer;
  944. begin
  945. Result := FWidth;
  946. end;
  947. procedure TgxBlankImage.SetHeight(val: Integer);
  948. begin
  949. if val <> FHeight then
  950. begin
  951. FHeight := val;
  952. if FHeight < 1 then
  953. FHeight := 1;
  954. Invalidate;
  955. end;
  956. end;
  957. function TgxBlankImage.GetHeight: Integer;
  958. begin
  959. Result := FHeight;
  960. end;
  961. procedure TgxBlankImage.SetDepth(val: Integer);
  962. begin
  963. if val <> FDepth then
  964. begin
  965. FDepth := val;
  966. if FDepth < 0 then
  967. FDepth := 0;
  968. Invalidate;
  969. end;
  970. end;
  971. function TgxBlankImage.GetDepth: Integer;
  972. begin
  973. Result := fDepth;
  974. end;
  975. procedure TgxBlankImage.SetCubeMap(const val: Boolean);
  976. begin
  977. if val <> fCubeMap then
  978. begin
  979. fCubeMap := val;
  980. Invalidate;
  981. end;
  982. end;
  983. procedure TgxBlankImage.SetArray(const val: Boolean);
  984. begin
  985. if val <> fArray then
  986. begin
  987. fArray := val;
  988. Invalidate;
  989. end;
  990. end;
  991. function TgxBlankImage.GetBitmap32: TgxImage;
  992. begin
  993. if not Assigned(FBitmap) then
  994. begin
  995. fBitmap := TgxImage.Create;
  996. fBitmap.Width := FWidth;
  997. fBitmap.Height := FHeight;
  998. fBitmap.Depth := FDepth;
  999. fBitmap.CubeMap := FCubeMap;
  1000. fBitmap.TextureArray := FArray;
  1001. fBitmap.SetColorFormatDataType(FColorFormat, GL_UNSIGNED_BYTE);
  1002. end;
  1003. Result := FBitmap;
  1004. end;
  1005. procedure TgxBlankImage.ReleaseBitmap32;
  1006. begin
  1007. if Assigned(FBitmap) then
  1008. begin
  1009. FBitmap.Free;
  1010. FBitmap := nil;
  1011. end;
  1012. end;
  1013. procedure TgxBlankImage.SaveToFile(const fileName: string);
  1014. begin
  1015. SaveAnsiStringToFile(fileName, AnsiString(
  1016. '[BlankImage]'#13#10'Width=' + IntToStr(Width) +
  1017. #13#10'Height=' + IntToStr(Height) +
  1018. #13#10'Depth=' + IntToStr(Depth)));
  1019. end;
  1020. procedure TgxBlankImage.LoadFromFile(const fileName: string);
  1021. var
  1022. sl: TStringList;
  1023. buf, temp: string;
  1024. begin
  1025. buf := fileName;
  1026. if Assigned(FOnTextureNeeded) then
  1027. FOnTextureNeeded(Self, buf);
  1028. if FileExists(buf) then
  1029. begin
  1030. sl := TStringList.Create;
  1031. try
  1032. sl.LoadFromFile(buf, TEncoding.ASCII);
  1033. FWidth := StrToInt(sl.Values['Width']);
  1034. FHeight := StrToInt(sl.Values['Height']);
  1035. temp := sl.Values['Depth'];
  1036. if Length(temp) > 0 then
  1037. FDepth := StrToInt(temp)
  1038. else
  1039. FDepth := 1;
  1040. finally
  1041. sl.Free;
  1042. end;
  1043. end
  1044. else
  1045. begin
  1046. Assert(False, Format(strFailedOpenFile, [fileName]));
  1047. end;
  1048. end;
  1049. class function TgxBlankImage.FriendlyName: string;
  1050. begin
  1051. Result := 'Blank Image';
  1052. end;
  1053. class function TgxBlankImage.FriendlyDescription: string;
  1054. begin
  1055. Result := 'Blank Image (Width x Height x Depth)';
  1056. end;
  1057. function TgxBlankImage.GetTextureTarget: TglTextureTarget;
  1058. begin
  1059. Result := ttTexture2D;
  1060. // Choose a texture target
  1061. if Assigned(fBitmap) then
  1062. begin
  1063. FWidth := fBitmap.Width;
  1064. FHeight := fBitmap.Height;
  1065. FDepth := fBitmap.Depth;
  1066. FCubeMap := fBitmap.CubeMap;
  1067. FArray := fBitmap.TextureArray;
  1068. end;
  1069. if FHeight = 1 then
  1070. Result := ttTexture1D;
  1071. if FCubeMap then
  1072. Result := ttTextureCube;
  1073. if FDepth > 0 then
  1074. Result := ttTexture3D;
  1075. if FArray then
  1076. begin
  1077. if FDepth < 2 then
  1078. Result := ttTexture1DArray
  1079. else
  1080. Result := ttTexture2DArray;
  1081. if FCubeMap then
  1082. Result := ttTextureCubeArray;
  1083. end;
  1084. if Assigned(FOwnerTexture) then
  1085. begin
  1086. if ((FOwnerTexture.FTextureFormat >= tfFLOAT_R16)
  1087. and (FOwnerTexture.FTextureFormat <= tfFLOAT_RGBA32)) then
  1088. Result := ttTextureRect;
  1089. end;
  1090. end;
  1091. // ------------------
  1092. // ------------------ TgxPictureImage ------------------
  1093. // ------------------
  1094. constructor TgxPictureImage.Create(AOwner: TPersistent);
  1095. begin
  1096. inherited;
  1097. end;
  1098. destructor TgxPictureImage.Destroy;
  1099. begin
  1100. ReleaseBitmap32;
  1101. FVKPicture.Free;
  1102. inherited Destroy;
  1103. end;
  1104. procedure TgxPictureImage.Assign(Source: TPersistent);
  1105. var
  1106. bmp: TBitmap;
  1107. begin
  1108. if Assigned(Source) then
  1109. begin
  1110. if (Source is TgxPersistentImage) then
  1111. Picture.Assign(TgxPersistentImage(Source).Picture)
  1112. else if (Source is TBitmap) then
  1113. Picture.Assign(Source)
  1114. else if (Source is TImage) then
  1115. Picture.Assign(Source)
  1116. else if (Source is TgxImage) then
  1117. begin
  1118. bmp := TgxImage(Source).Create32BitsBitmap;
  1119. Picture.Bitmap := bmp;
  1120. bmp.Free;
  1121. FResourceFile := TgxImage(Source).ResourceName;
  1122. end
  1123. else
  1124. inherited;
  1125. end
  1126. else
  1127. inherited;
  1128. end;
  1129. procedure TgxPictureImage.BeginUpdate;
  1130. begin
  1131. Inc(FUpdateCounter);
  1132. Picture.Bitmap.OnChange := nil;
  1133. end;
  1134. procedure TgxPictureImage.EndUpdate;
  1135. begin
  1136. Assert(FUpdateCounter > 0, ClassName + ': Unbalanced Begin/EndUpdate');
  1137. Dec(FUpdateCounter);
  1138. Picture.Bitmap.OnChange := PictureChanged;
  1139. if FUpdateCounter = 0 then
  1140. PictureChanged(Picture);
  1141. end;
  1142. function TgxPictureImage.GetHeight: Integer;
  1143. begin
  1144. Result := Picture.Bitmap.Height;
  1145. end;
  1146. function TgxPictureImage.GetWidth: Integer;
  1147. begin
  1148. Result := Picture.Bitmap.Width;
  1149. end;
  1150. function TgxPictureImage.GetDepth: Integer;
  1151. begin
  1152. Result := 0;
  1153. end;
  1154. function TgxPictureImage.GetBitmap32: TgxImage;
  1155. begin
  1156. if not Assigned(FBitmap) then
  1157. begin
  1158. FBitmap := TgxImage.Create;
  1159. // we need to deactivate OnChange, due to a "glitch" in some TGraphics,
  1160. // for instance, TJPegImage triggers an OnChange when it is drawn...
  1161. if Assigned(Picture.Bitmap) then
  1162. begin
  1163. if Assigned(Picture.Bitmap.OnChange) then
  1164. begin
  1165. Picture.Bitmap.OnChange := nil;
  1166. try
  1167. FBitmap.Assign(Picture.Bitmap);
  1168. finally
  1169. Picture.Bitmap.OnChange := PictureChanged;
  1170. end;
  1171. end
  1172. else
  1173. FBitmap.Assign(Picture.Bitmap);
  1174. end
  1175. else
  1176. FBitmap.SetErrorImage;
  1177. end;
  1178. Result := FBitmap;
  1179. end;
  1180. procedure TgxPictureImage.ReleaseBitmap32;
  1181. begin
  1182. if Assigned(FBitmap) then
  1183. begin
  1184. FBitmap.Free;
  1185. FBitmap := nil;
  1186. end;
  1187. end;
  1188. procedure TgxPictureImage.PictureChanged(Sender: TObject);
  1189. begin
  1190. Invalidate;
  1191. end;
  1192. function TgxPictureImage.GetPicture: TImage;
  1193. begin
  1194. if not Assigned(FVKPicture) then
  1195. begin
  1196. FVKPicture := TImage.Create(nil);
  1197. FVKPicture.Bitmap.OnChange := PictureChanged;
  1198. end;
  1199. Result := FVKPicture;
  1200. end;
  1201. procedure TgxPictureImage.SetPicture(const aPicture: TImage);
  1202. begin
  1203. Picture.Assign(aPicture);
  1204. end;
  1205. function TgxPictureImage.GetTextureTarget: TglTextureTarget;
  1206. begin
  1207. Result := ttTexture2D;
  1208. end;
  1209. // ------------------
  1210. // ------------------ TgxPersistentImage ------------------
  1211. // ------------------
  1212. constructor TgxPersistentImage.Create(AOwner: TPersistent);
  1213. begin
  1214. inherited;
  1215. end;
  1216. destructor TgxPersistentImage.Destroy;
  1217. begin
  1218. inherited Destroy;
  1219. end;
  1220. procedure TgxPersistentImage.SaveToFile(const fileName: string);
  1221. begin
  1222. Picture.Bitmap.SaveToFile(fileName);
  1223. FResourceFile := fileName;
  1224. end;
  1225. procedure TgxPersistentImage.LoadFromFile(const fileName: string);
  1226. var
  1227. buf: string;
  1228. gr: TBitmap;
  1229. begin
  1230. buf := fileName;
  1231. FResourceFile := fileName;
  1232. if Assigned(FOnTextureNeeded) then
  1233. FOnTextureNeeded(Self, buf);
  1234. if ApplicationFileIODefined then
  1235. begin
  1236. gr := CreateGraphicFromFile(buf);
  1237. if Assigned(gr) then
  1238. begin
  1239. Picture.Bitmap := gr;
  1240. gr.Free;
  1241. Exit;
  1242. end;
  1243. end
  1244. else if FileExists(buf) then
  1245. begin
  1246. Picture.Bitmap.LoadFromFile(buf);
  1247. Exit;
  1248. end;
  1249. Picture.Bitmap := nil;
  1250. raise ETexture.CreateFmt(strFailedOpenFile, [fileName]);
  1251. end;
  1252. class function TgxPersistentImage.FriendlyName: string;
  1253. begin
  1254. Result := 'Persistent Image';
  1255. end;
  1256. class function TgxPersistentImage.FriendlyDescription: string;
  1257. begin
  1258. Result := 'Image data is stored in its original format with other form resources,'
  1259. + 'ie. in the DFM at design-time, and embedded in the EXE at run-time.';
  1260. end;
  1261. // ------------------
  1262. // ------------------ TgxPicFileImage ------------------
  1263. // ------------------
  1264. constructor TgxPicFileImage.Create(AOwner: TPersistent);
  1265. begin
  1266. inherited;
  1267. end;
  1268. destructor TgxPicFileImage.Destroy;
  1269. begin
  1270. inherited;
  1271. end;
  1272. procedure TgxPicFileImage.Assign(Source: TPersistent);
  1273. begin
  1274. if Source is TgxPicFileImage then
  1275. begin
  1276. FPictureFileName := TgxPicFileImage(Source).FPictureFileName;
  1277. FResourceFile := TgxPicFileImage(Source).ResourceName;
  1278. end
  1279. else
  1280. inherited;
  1281. end;
  1282. procedure TgxPicFileImage.SetPictureFileName(const val: string);
  1283. begin
  1284. if val <> FPictureFileName then
  1285. begin
  1286. FPictureFileName := val;
  1287. FResourceFile := val;
  1288. FAlreadyWarnedAboutMissingFile := False;
  1289. Invalidate;
  1290. end;
  1291. end;
  1292. procedure TgxPicFileImage.Invalidate;
  1293. begin
  1294. Picture.Bitmap.OnChange := nil;
  1295. try
  1296. Picture.Assign(nil);
  1297. FBitmap := nil;
  1298. finally
  1299. Picture.Bitmap.OnChange := PictureChanged;
  1300. end;
  1301. inherited;
  1302. end;
  1303. function TgxPicFileImage.GetHeight: Integer;
  1304. begin
  1305. Result := FHeight;
  1306. end;
  1307. function TgxPicFileImage.GetWidth: Integer;
  1308. begin
  1309. Result := FWidth;
  1310. end;
  1311. function TgxPicFileImage.GetDepth: Integer;
  1312. begin
  1313. Result := 0;
  1314. end;
  1315. function TgxPicFileImage.GetBitmap32: TgxImage;
  1316. var
  1317. buf: string;
  1318. gr: TBitmap;
  1319. begin
  1320. if (GetWidth <= 0) and (PictureFileName <> '') then
  1321. begin
  1322. Picture.Bitmap.OnChange := nil;
  1323. try
  1324. buf := PictureFileName;
  1325. SetExeDirectory;
  1326. if Assigned(FOnTextureNeeded) then
  1327. FOnTextureNeeded(Self, buf);
  1328. if FileStreamExists(buf) then
  1329. begin
  1330. gr := CreateGraphicFromFile(buf);
  1331. Picture.Bitmap := gr;
  1332. gr.Free;
  1333. end
  1334. else
  1335. begin
  1336. Picture.Bitmap := nil;
  1337. if not FAlreadyWarnedAboutMissingFile then
  1338. begin
  1339. FAlreadyWarnedAboutMissingFile := True;
  1340. GLOKMessageBox(Format(strFailedOpenFileFromCurrentDir, [PictureFileName, GetCurrentDir]),strError);
  1341. end;
  1342. end;
  1343. Result := inherited GetBitmap32;
  1344. FWidth := Result.Width;
  1345. FHeight := Result.Height;
  1346. Picture.Bitmap := nil;
  1347. finally
  1348. Picture.Bitmap.OnChange := PictureChanged;
  1349. end;
  1350. end
  1351. else
  1352. Result := inherited GetBitmap32;
  1353. end;
  1354. procedure TgxPicFileImage.SaveToFile(const fileName: string);
  1355. begin
  1356. FResourceFile := fileName;
  1357. SaveAnsiStringToFile(fileName, AnsiString(PictureFileName));
  1358. end;
  1359. //
  1360. procedure TgxPicFileImage.LoadFromFile(const fileName: string);
  1361. var
  1362. buf: string;
  1363. begin
  1364. inherited;
  1365. // attempt to autodetect if we are pointed to a file containing
  1366. // a filename or directly to an image
  1367. if SizeOfFile(fileName) < 512 then
  1368. begin
  1369. buf := string(LoadAnsiStringFromFile(fileName));
  1370. if Pos(#0, buf) > 0 then
  1371. PictureFileName := fileName
  1372. else
  1373. PictureFileName := buf;
  1374. end
  1375. else
  1376. PictureFileName := fileName;
  1377. FResourceFile := FPictureFileName;
  1378. end;
  1379. //
  1380. class function TgxPicFileImage.FriendlyName: string;
  1381. begin
  1382. Result := 'PicFile Image';
  1383. end;
  1384. // FriendlyDescription
  1385. //
  1386. class function TgxPicFileImage.FriendlyDescription: string;
  1387. begin
  1388. Result := 'Image data is retrieved from a file.';
  1389. end;
  1390. // ------------------
  1391. // ------------------ TgxCubeMapImage ------------------
  1392. // ------------------
  1393. constructor TgxCubeMapImage.Create(AOwner: TPersistent);
  1394. var
  1395. i: TgxCubeMapTarget;
  1396. begin
  1397. inherited;
  1398. for i := Low(FPicture) to High(FPicture) do
  1399. begin
  1400. FPicture[i] := TImage.Create(nil);
  1401. FPicture[i].Bitmap.OnChange := PictureChanged;
  1402. end;
  1403. end;
  1404. destructor TgxCubeMapImage.Destroy;
  1405. var
  1406. i: TgxCubeMapTarget;
  1407. begin
  1408. ReleaseBitmap32;
  1409. for i := Low(FPicture) to High(FPicture) do
  1410. FPicture[i].Free;
  1411. inherited Destroy;
  1412. end;
  1413. procedure TgxCubeMapImage.Assign(Source: TPersistent);
  1414. var
  1415. i: TgxCubeMapTarget;
  1416. begin
  1417. if Assigned(Source) then
  1418. begin
  1419. if (Source is TgxCubeMapImage) then
  1420. begin
  1421. for i := Low(FPicture) to High(FPicture) do
  1422. FPicture[i].Assign(TgxCubeMapImage(Source).FPicture[i]);
  1423. Invalidate;
  1424. end
  1425. else
  1426. inherited;
  1427. end
  1428. else
  1429. inherited;
  1430. end;
  1431. function TgxCubeMapImage.GetWidth: Integer;
  1432. begin
  1433. Result := FPicture[cmtPX].Bitmap.Width;
  1434. end;
  1435. function TgxCubeMapImage.GetHeight: Integer;
  1436. begin
  1437. Result := FPicture[cmtPX].Bitmap.Height;
  1438. end;
  1439. function TgxCubeMapImage.GetDepth: Integer;
  1440. begin
  1441. Result := 0;
  1442. end;
  1443. function TgxCubeMapImage.GetBitmap32: TgxImage;
  1444. var
  1445. I: Integer;
  1446. LImage: TgxImage;
  1447. begin
  1448. if Assigned(FImage) then
  1449. FImage.Free;
  1450. LImage := TgxImage.Create;
  1451. LImage.VerticalReverseOnAssignFromBitmap := True;
  1452. try
  1453. for I := 0 to 5 do
  1454. begin
  1455. FPicture[TgxCubeMapTarget(I)].Bitmap.OnChange := nil;
  1456. try
  1457. LImage.Assign(FPicture[TgxCubeMapTarget(I)].Bitmap);
  1458. if not Assigned(FImage) then
  1459. begin
  1460. FImage := TgxImage.Create;
  1461. FImage.Blank := True;
  1462. FImage.Width := LImage.Width;
  1463. FImage.Height := LImage.Height;
  1464. FImage.SetColorFormatDataType(LImage.ColorFormat, LImage.DataType);
  1465. FImage.CubeMap := True;
  1466. FImage.Blank := False;
  1467. end;
  1468. Move(LImage.Data^, TFriendlyImage(FImage).GetLevelAddress(0, I)^, LImage.LevelSizeInByte[0]);
  1469. finally
  1470. FPicture[TgxCubeMapTarget(I)].Bitmap.OnChange := PictureChanged;
  1471. end;
  1472. end;
  1473. finally
  1474. LImage.Destroy;
  1475. end;
  1476. Result := FImage;
  1477. end;
  1478. // ReleaseBitmap32
  1479. //
  1480. procedure TgxCubeMapImage.ReleaseBitmap32;
  1481. begin
  1482. if Assigned(FImage) then
  1483. begin
  1484. FImage.Free;
  1485. FImage := nil;
  1486. end;
  1487. end;
  1488. procedure TgxCubeMapImage.BeginUpdate;
  1489. var
  1490. i: TgxCubeMapTarget;
  1491. begin
  1492. Inc(FUpdateCounter);
  1493. for i := Low(FPicture) to High(FPicture) do
  1494. FPicture[i].Bitmap.OnChange := nil;
  1495. end;
  1496. procedure TgxCubeMapImage.EndUpdate;
  1497. var
  1498. i: TgxCubeMapTarget;
  1499. begin
  1500. Assert(FUpdateCounter > 0, ClassName + ': Unbalanced Begin/EndUpdate');
  1501. Dec(FUpdateCounter);
  1502. for i := Low(FPicture) to High(FPicture) do
  1503. FPicture[i].Bitmap.OnChange := PictureChanged;
  1504. if FUpdateCounter = 0 then
  1505. PictureChanged(FPicture[cmtPX]);
  1506. end;
  1507. procedure TgxCubeMapImage.SaveToFile(const fileName: string);
  1508. var
  1509. fs: TFileStream;
  1510. bmp: TBitmap;
  1511. i: TgxCubeMapTarget;
  1512. version: Word;
  1513. begin
  1514. fs := TFileStream.Create(fileName, fmCreate);
  1515. bmp := TBitmap.Create;
  1516. try
  1517. version := $0100;
  1518. fs.Write(version, 2);
  1519. for i := Low(FPicture) to High(FPicture) do
  1520. begin
  1521. bmp.Assign(FPicture[i].Bitmap);
  1522. bmp.SaveToStream(fs);
  1523. end;
  1524. finally
  1525. bmp.Free;
  1526. fs.Free;
  1527. end;
  1528. end;
  1529. procedure TgxCubeMapImage.LoadFromFile(const fileName: string);
  1530. var
  1531. fs: TFileStream;
  1532. bmp: TBitmap;
  1533. i: TgxCubeMapTarget;
  1534. version: Word;
  1535. begin
  1536. fs := TFileStream.Create(fileName, fmOpenRead + fmShareDenyWrite);
  1537. bmp := TBitmap.Create;
  1538. try
  1539. fs.Read(version, 2);
  1540. Assert(version = $0100);
  1541. for i := Low(FPicture) to High(FPicture) do
  1542. begin
  1543. bmp.LoadFromStream(fs);
  1544. FPicture[i].Bitmap := bmp;
  1545. end;
  1546. finally
  1547. bmp.Free;
  1548. fs.Free;
  1549. end;
  1550. end;
  1551. class function TgxCubeMapImage.FriendlyName: string;
  1552. begin
  1553. Result := 'CubeMap Image';
  1554. end;
  1555. class function TgxCubeMapImage.FriendlyDescription: string;
  1556. begin
  1557. Result := 'Image data is contain 6 pictures of cubemap faces.';
  1558. end;
  1559. procedure TgxCubeMapImage.PictureChanged(Sender: TObject);
  1560. begin
  1561. Invalidate;
  1562. end;
  1563. function TgxCubeMapImage.GetTextureTarget: TglTextureTarget;
  1564. begin
  1565. Result := ttTextureCube;
  1566. end;
  1567. procedure TgxCubeMapImage.SetPicture(index: TgxCubeMapTarget; const val: TImage);
  1568. begin
  1569. FPicture[index].Assign(val);
  1570. end;
  1571. function TgxCubeMapImage.GetPicture(index: TgxCubeMapTarget): TImage;
  1572. begin
  1573. Result := FPicture[index];
  1574. end;
  1575. // ------------------
  1576. // ------------------ TgxTexture ------------------
  1577. // ------------------
  1578. constructor TgxTexture.Create(AOwner: TPersistent);
  1579. begin
  1580. inherited;
  1581. FDisabled := True;
  1582. FImage := TgxPersistentImage.Create(Self);
  1583. FImage.OnTextureNeeded := DoOnTextureNeeded;
  1584. FImageAlpha := tiaDefault;
  1585. FImageBrightness := 1.0;
  1586. FImageGamma := 1.0;
  1587. FMagFilter := maLinear;
  1588. FMinFilter := miLinearMipMapLinear;
  1589. FFilteringQuality := tfIsotropic;
  1590. FRequiredMemorySize := -1;
  1591. FTextureHandle := TgxTextureHandle.Create;
  1592. FSamplerHandle := TgxVirtualHandle.Create;
  1593. FSamplerHandle.OnAllocate := OnSamplerAllocate;
  1594. FSamplerHandle.OnDestroy := OnSamplerDestroy;
  1595. FMappingMode := tmmUser;
  1596. FEnvColor := TgxColor.CreateInitialized(Self, clrTransparent);
  1597. FBorderColor := TgxColor.CreateInitialized(Self, clrTransparent);
  1598. FNormalMapScale := cDefaultNormalMapScale;
  1599. FTextureCompareMode := tcmNone;
  1600. FTextureCompareFunc := cfLequal;
  1601. FDepthTextureMode := dtmLuminance;
  1602. TextureFormat := tfDefault;
  1603. FCompression := tcDefault;
  1604. FKeepImageAfterTransfer := False;
  1605. end;
  1606. destructor TgxTexture.Destroy;
  1607. begin
  1608. FEnvColor.Free;
  1609. FBorderColor.Free;
  1610. FMapSCoordinates.Free;
  1611. FMapTCoordinates.Free;
  1612. FMapRCoordinates.Free;
  1613. FMapQCoordinates.Free;
  1614. DestroyHandles;
  1615. FTextureHandle.Free;
  1616. FSamplerHandle.Free;
  1617. FImage.Free;
  1618. inherited Destroy;
  1619. end;
  1620. procedure TgxTexture.Assign(Source: TPersistent);
  1621. begin
  1622. if Assigned(Source) then
  1623. begin
  1624. if (Source is TgxTexture) then
  1625. begin
  1626. if Source <> Self then
  1627. begin
  1628. FImageAlpha := TgxTexture(Source).FImageAlpha;
  1629. FTextureMode := TgxTexture(Source).FTextureMode;
  1630. FTextureWrap := TgxTexture(Source).FTextureWrap;
  1631. FTextureFormat := TgxTexture(Source).FTextureFormat;
  1632. FCompression := TgxTexture(Source).FCompression;
  1633. FMinFilter := TgxTexture(Source).FMinFilter;
  1634. FMagFilter := TgxTexture(Source).FMagFilter;
  1635. FMappingMode := TgxTexture(Source).FMappingMode;
  1636. MappingSCoordinates.Assign(TgxTexture(Source).MappingSCoordinates);
  1637. MappingTCoordinates.Assign(TgxTexture(Source).MappingTCoordinates);
  1638. MappingRCoordinates.Assign(TgxTexture(Source).MappingRCoordinates);
  1639. MappingQCoordinates.Assign(TgxTexture(Source).MappingQCoordinates);
  1640. FDisabled := TgxTexture(Source).FDisabled;
  1641. SetImage(TgxTexture(Source).FImage);
  1642. FImageBrightness := TgxTexture(Source).FImageBrightness;
  1643. FImageGamma := TgxTexture(Source).FImageGamma;
  1644. FFilteringQuality := TgxTexture(Source).FFilteringQuality;
  1645. FEnvColor.Assign(TgxTexture(Source).FEnvColor);
  1646. FBorderColor.Assign(TgxTexture(Source).FBorderColor);
  1647. FNormalMapScale := TgxTexture(Source).FNormalMapScale;
  1648. // Probably don't need to assign these....
  1649. // FOnTextureNeeded := TgxTexture(Source).FImageGamma;
  1650. // FRequiredMemorySize : Integer;
  1651. // FTexWidth, FTexHeight : Integer;
  1652. FTextureHandle.NotifyChangesOfData;
  1653. FSamplerHandle.NotifyChangesOfData;
  1654. end;
  1655. end
  1656. else if (Source is TBitmap) then
  1657. Image.Assign(Source)
  1658. else if (Source is TImage) then
  1659. Image.Assign(TImage(Source).Bitmap)
  1660. else
  1661. inherited Assign(Source);
  1662. end
  1663. else
  1664. begin
  1665. FDisabled := True;
  1666. SetImage(nil);
  1667. FTextureHandle.NotifyChangesOfData;
  1668. FSamplerHandle.NotifyChangesOfData;
  1669. end;
  1670. end;
  1671. procedure TgxTexture.NotifyChange(Sender: TObject);
  1672. begin
  1673. if Assigned(Owner) then
  1674. begin
  1675. if Owner is TgxTextureExItem then
  1676. TgxTextureExItem(Owner).NotifyChange(Self);
  1677. end;
  1678. if Sender is TgxTextureImage then
  1679. FTextureHandle.NotifyChangesOfData;
  1680. inherited;
  1681. end;
  1682. procedure TgxTexture.NotifyImageChange;
  1683. begin
  1684. FTextureHandle.NotifyChangesOfData;
  1685. NotifyChange(Self);
  1686. end;
  1687. procedure TgxTexture.NotifyParamsChange;
  1688. begin
  1689. FSamplerHandle.NotifyChangesOfData;
  1690. NotifyChange(Self);
  1691. end;
  1692. procedure TgxTexture.SetImage(AValue: TgxTextureImage);
  1693. begin
  1694. if Assigned(aValue) then
  1695. begin
  1696. if FImage.ClassType <> AValue.ClassType then
  1697. begin
  1698. FImage.Free;
  1699. FImage := TgxTextureImageClass(AValue.ClassType).Create(Self);
  1700. FImage.OnTextureNeeded := DoOnTextureNeeded;
  1701. end;
  1702. FImage.Assign(AValue);
  1703. end
  1704. else
  1705. begin
  1706. FImage.Free;
  1707. FImage := TgxPersistentImage.Create(Self);
  1708. FImage.OnTextureNeeded := DoOnTextureNeeded;
  1709. end;
  1710. end;
  1711. procedure TgxTexture.SetImageClassName(const val: string);
  1712. var
  1713. newImage: TgxTextureImage;
  1714. newImageClass: TgxTextureImageClass;
  1715. begin
  1716. if val <> '' then
  1717. if FImage.ClassName <> val then
  1718. begin
  1719. newImageClass := FindTextureImageClass(val);
  1720. Assert(newImageClass <> nil, 'Make sure you include the unit for ' + val +
  1721. ' in your uses clause');
  1722. if newImageClass = nil then
  1723. exit;
  1724. newImage := newImageClass.Create(Self);
  1725. newImage.OnTextureNeeded := DoOnTextureNeeded;
  1726. FImage.Free;
  1727. FImage := newImage;
  1728. end;
  1729. end;
  1730. function TgxTexture.GetImageClassName: string;
  1731. begin
  1732. Result := FImage.ClassName;
  1733. end;
  1734. function TgxTexture.TextureImageRequiredMemory: Integer;
  1735. var
  1736. w, h, e, levelSize: Integer;
  1737. begin
  1738. if FRequiredMemorySize < 0 then
  1739. begin
  1740. if IsCompressedFormat(fTextureFormat) then
  1741. begin
  1742. w := (Image.Width + 3) div 4;
  1743. h := (Image.Height + 3) div 4;
  1744. end
  1745. else
  1746. begin
  1747. w := Image.Width;
  1748. h := Image.Height;
  1749. end;
  1750. e := GetTextureElementSize(fTextureFormat);
  1751. FRequiredMemorySize := w * h * e;
  1752. if Image.Depth > 0 then
  1753. FRequiredMemorySize := FRequiredMemorySize * Image.Depth;
  1754. if not (MinFilter in [miNearest, miLinear]) then
  1755. begin
  1756. levelSize := FRequiredMemorySize;
  1757. while e < levelSize do
  1758. begin
  1759. levelSize := levelSize div 4;
  1760. FRequiredMemorySize := FRequiredMemorySize + levelSize;
  1761. end;
  1762. end;
  1763. if Image.NativeTextureTarget = ttTextureCube then
  1764. FRequiredMemorySize := FRequiredMemorySize * 6;
  1765. end;
  1766. Result := FRequiredMemorySize;
  1767. end;
  1768. procedure TgxTexture.SetImageAlpha(const val: TgxTextureImageAlpha);
  1769. begin
  1770. if FImageAlpha <> val then
  1771. begin
  1772. FImageAlpha := val;
  1773. NotifyImageChange;
  1774. end;
  1775. end;
  1776. procedure TgxTexture.SetImageBrightness(const val: Single);
  1777. begin
  1778. if FImageBrightness <> val then
  1779. begin
  1780. FImageBrightness := val;
  1781. NotifyImageChange;
  1782. end;
  1783. end;
  1784. function TgxTexture.StoreBrightness: Boolean;
  1785. begin
  1786. Result := (FImageBrightness <> 1.0);
  1787. end;
  1788. procedure TgxTexture.SetImageGamma(const val: Single);
  1789. begin
  1790. if FImageGamma <> val then
  1791. begin
  1792. FImageGamma := val;
  1793. NotifyImageChange;
  1794. end;
  1795. end;
  1796. function TgxTexture.StoreGamma: Boolean;
  1797. begin
  1798. Result := (FImageGamma <> 1.0);
  1799. end;
  1800. procedure TgxTexture.SetMagFilter(AValue: TgxMagFilter);
  1801. begin
  1802. if AValue <> FMagFilter then
  1803. begin
  1804. FMagFilter := AValue;
  1805. NotifyParamsChange;
  1806. end;
  1807. end;
  1808. procedure TgxTexture.SetMinFilter(AValue: TgxMinFilter);
  1809. begin
  1810. if AValue <> FMinFilter then
  1811. begin
  1812. FMinFilter := AValue;
  1813. NotifyParamsChange;
  1814. end;
  1815. end;
  1816. procedure TgxTexture.SetTextureMode(AValue: TgxTextureMode);
  1817. begin
  1818. if AValue <> FTextureMode then
  1819. begin
  1820. FTextureMode := AValue;
  1821. NotifyParamsChange;
  1822. end;
  1823. end;
  1824. procedure TgxTexture.SetDisabled(AValue: Boolean);
  1825. var
  1826. intf: IgxTextureNotifyAble;
  1827. begin
  1828. if AValue <> FDisabled then
  1829. begin
  1830. FDisabled := AValue;
  1831. if Supports(Owner, IgxTextureNotifyAble, intf) then
  1832. intf.NotifyTexMapChange(Self)
  1833. else
  1834. NotifyChange(Self);
  1835. end;
  1836. end;
  1837. procedure TgxTexture.SetEnabled(const val: Boolean);
  1838. begin
  1839. Disabled := not val;
  1840. end;
  1841. function TgxTexture.GetEnabled: Boolean;
  1842. begin
  1843. Result := not Disabled;
  1844. end;
  1845. procedure TgxTexture.SetEnvColor(const val: TgxColor);
  1846. begin
  1847. FEnvColor.Assign(val);
  1848. NotifyParamsChange;
  1849. end;
  1850. procedure TgxTexture.SetBorderColor(const val: TgxColor);
  1851. begin
  1852. FBorderColor.Assign(val);
  1853. NotifyParamsChange;
  1854. end;
  1855. procedure TgxTexture.SetNormalMapScale(const val: Single);
  1856. begin
  1857. if val <> FNormalMapScale then
  1858. begin
  1859. FNormalMapScale := val;
  1860. if TextureFormat = tfNormalMap then
  1861. NotifyImageChange;
  1862. end;
  1863. end;
  1864. function TgxTexture.StoreNormalMapScale: Boolean;
  1865. begin
  1866. Result := (FNormalMapScale <> cDefaultNormalMapScale);
  1867. end;
  1868. procedure TgxTexture.SetTextureWrap(AValue: TgxTextureWrap);
  1869. begin
  1870. if AValue <> FTextureWrap then
  1871. begin
  1872. FTextureWrap := AValue;
  1873. NotifyParamsChange;
  1874. end;
  1875. end;
  1876. procedure TgxTexture.SetTextureWrapS(AValue: TglSeparateTextureWrap);
  1877. begin
  1878. if AValue <> FTextureWrapS then
  1879. begin
  1880. FTextureWrapS := AValue;
  1881. NotifyParamsChange;
  1882. end;
  1883. end;
  1884. procedure TgxTexture.SetTextureWrapT(AValue: TglSeparateTextureWrap);
  1885. begin
  1886. if AValue <> FTextureWrapT then
  1887. begin
  1888. FTextureWrapT := AValue;
  1889. NotifyParamsChange;
  1890. end;
  1891. end;
  1892. procedure TgxTexture.SetTextureWrapR(AValue: TglSeparateTextureWrap);
  1893. begin
  1894. if AValue <> FTextureWrapR then
  1895. begin
  1896. FTextureWrapR := AValue;
  1897. NotifyParamsChange;
  1898. end;
  1899. end;
  1900. function TgxTexture.GetTextureFormat: TgxTextureFormat;
  1901. var
  1902. i: TgxTextureFormat;
  1903. begin
  1904. if vDefaultTextureFormat = FTextureFormat then
  1905. begin
  1906. Result := tfDefault;
  1907. Exit;
  1908. end;
  1909. for i := tfRGB to tfRGBAFloat32 do
  1910. begin
  1911. if cOldTextureFormatToInternalFormat[i] = FTextureFormat then
  1912. begin
  1913. Result := i;
  1914. Exit;
  1915. end;
  1916. end;
  1917. Result := tfExtended;
  1918. end;
  1919. procedure TgxTexture.SetTextureFormat(const val: TgxTextureFormat);
  1920. begin
  1921. if val = tfDefault then
  1922. begin
  1923. FTextureFormat := vDefaultTextureFormat;
  1924. end
  1925. else if val < tfExtended then
  1926. begin
  1927. FTextureFormat := cOldTextureFormatToInternalFormat[val];
  1928. end;
  1929. end;
  1930. procedure TgxTexture.SetTextureFormatEx(const val: TglInternalFormat);
  1931. begin
  1932. if val <> FTextureFormat then
  1933. begin
  1934. FTextureFormat := val;
  1935. NotifyImageChange;
  1936. end;
  1937. end;
  1938. function TgxTexture.StoreTextureFormatEx: Boolean;
  1939. begin
  1940. Result := GetTextureFormat >= tfExtended;
  1941. end;
  1942. procedure TgxTexture.SetCompression(const val: TgxTextureCompression);
  1943. begin
  1944. if val <> FCompression then
  1945. begin
  1946. FCompression := val;
  1947. NotifyParamsChange;
  1948. end;
  1949. end;
  1950. procedure TgxTexture.SetFilteringQuality(const val: TglTextureFilteringQuality);
  1951. begin
  1952. if val <> FFilteringQuality then
  1953. begin
  1954. FFilteringQuality := val;
  1955. NotifyParamsChange;
  1956. end;
  1957. end;
  1958. procedure TgxTexture.SetMappingMode(const val: TgxTextureMappingMode);
  1959. var
  1960. texMapChange: Boolean;
  1961. intf: IgxTextureNotifyAble;
  1962. begin
  1963. if val <> FMappingMode then
  1964. begin
  1965. texMapChange := ((val = tmmUser) and (FMappingMode <> tmmUser))
  1966. or ((val = tmmUser) and (FMappingMode <> tmmUser));
  1967. FMappingMode := val;
  1968. if texMapChange then
  1969. begin
  1970. // when switching between texGen modes and user mode, the geometry
  1971. // must be rebuilt in whole (to specify/remove texCoord data!)
  1972. if Supports(Owner, IgxTextureNotifyAble, intf) then
  1973. intf.NotifyTexMapChange(Self);
  1974. end
  1975. else
  1976. NotifyChange(Self);
  1977. end;
  1978. end;
  1979. procedure TgxTexture.SetMappingSCoordinates(const val: TgxCoordinates4);
  1980. begin
  1981. MappingSCoordinates.Assign(val);
  1982. end;
  1983. function TgxTexture.GetMappingSCoordinates: TgxCoordinates4;
  1984. begin
  1985. if not Assigned(FMapSCoordinates) then
  1986. FMapSCoordinates := TgxCoordinates4.CreateInitialized(Self, XHmgVector, csVector);
  1987. Result := FMapSCoordinates;
  1988. end;
  1989. function TgxTexture.StoreMappingSCoordinates: Boolean;
  1990. begin
  1991. if Assigned(FMapSCoordinates) then
  1992. Result := not VectorEquals(FMapSCoordinates.AsVector, XHmgVector)
  1993. else
  1994. Result := false;
  1995. end;
  1996. procedure TgxTexture.SetMappingTCoordinates(const val: TgxCoordinates4);
  1997. begin
  1998. MappingTCoordinates.Assign(val);
  1999. end;
  2000. function TgxTexture.GetMappingTCoordinates: TgxCoordinates4;
  2001. begin
  2002. if not Assigned(FMapTCoordinates) then
  2003. FMapTCoordinates := TgxCoordinates4.CreateInitialized(Self, YHmgVector,
  2004. csVector);
  2005. Result := FMapTCoordinates;
  2006. end;
  2007. function TgxTexture.StoreMappingTCoordinates: Boolean;
  2008. begin
  2009. if Assigned(FMapTCoordinates) then
  2010. Result := not VectorEquals(FMapTCoordinates.AsVector, YHmgVector)
  2011. else
  2012. Result := false;
  2013. end;
  2014. procedure TgxTexture.SetMappingRCoordinates(const val: TgxCoordinates4);
  2015. begin
  2016. MappingRCoordinates.Assign(val);
  2017. end;
  2018. function TgxTexture.GetMappingRCoordinates: TgxCoordinates4;
  2019. begin
  2020. if not Assigned(FMapRCoordinates) then
  2021. FMapRCoordinates := TgxCoordinates4.CreateInitialized(Self, ZHmgVector,
  2022. csVector);
  2023. Result := FMapRCoordinates;
  2024. end;
  2025. function TgxTexture.StoreMappingRCoordinates: Boolean;
  2026. begin
  2027. if Assigned(FMapRCoordinates) then
  2028. Result := not VectorEquals(FMapRCoordinates.AsVector, ZHmgVector)
  2029. else
  2030. Result := false;
  2031. end;
  2032. procedure TgxTexture.SetMappingQCoordinates(const val: TgxCoordinates4);
  2033. begin
  2034. MappingQCoordinates.Assign(val);
  2035. end;
  2036. function TgxTexture.GetMappingQCoordinates: TgxCoordinates4;
  2037. begin
  2038. if not Assigned(FMapQCoordinates) then
  2039. FMapQCoordinates := TgxCoordinates4.CreateInitialized(Self, WHmgVector,
  2040. csVector);
  2041. Result := FMapQCoordinates;
  2042. end;
  2043. function TgxTexture.StoreMappingQCoordinates: Boolean;
  2044. begin
  2045. if Assigned(FMapQCoordinates) then
  2046. Result := not VectorEquals(FMapQCoordinates.AsVector, WHmgVector)
  2047. else
  2048. Result := false;
  2049. end;
  2050. function TgxTexture.StoreImageClassName: Boolean;
  2051. begin
  2052. Result := (FImage.ClassName <> TgxPersistentImage.ClassName);
  2053. end;
  2054. procedure TgxTexture.SetTextureCompareMode(const val: TglTextureCompareMode);
  2055. begin
  2056. if val <> fTextureCompareMode then
  2057. begin
  2058. fTextureCompareMode := val;
  2059. NotifyParamsChange;
  2060. end;
  2061. end;
  2062. procedure TgxTexture.SetTextureCompareFunc(const val: TgxDepthCompareFunc);
  2063. begin
  2064. if val <> fTextureCompareFunc then
  2065. begin
  2066. fTextureCompareFunc := val;
  2067. NotifyParamsChange;
  2068. end;
  2069. end;
  2070. procedure TgxTexture.SetDepthTextureMode(const val: TgxDepthTextureMode);
  2071. begin
  2072. if val <> fDepthTextureMode then
  2073. begin
  2074. fDepthTextureMode := val;
  2075. NotifyParamsChange;
  2076. end;
  2077. end;
  2078. procedure TgxTexture.PrepareBuildList;
  2079. begin
  2080. GetHandle;
  2081. end;
  2082. procedure TgxTexture.ApplyMappingMode;
  2083. begin
  2084. case MappingMode of
  2085. tmmUser: ; // nothing to do, but checked first (common case)
  2086. tmmObjectLinear:
  2087. begin
  2088. glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  2089. glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  2090. glTexGenfv(GL_S, GL_OBJECT_PLANE, @MappingSCoordinates.DirectVector);
  2091. glTexGenfv(GL_T, GL_OBJECT_PLANE, @MappingTCoordinates.DirectVector);
  2092. glEnable(GL_TEXTURE_GEN_S);
  2093. glEnable(GL_TEXTURE_GEN_T);
  2094. /// if GL_TEXTURE_CUBE_MAP or GL_TEXTURE_3D then
  2095. begin
  2096. glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  2097. glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  2098. glTexGenfv(GL_R, GL_OBJECT_PLANE, @MappingRCoordinates.DirectVector);
  2099. glTexGenfv(GL_Q, GL_OBJECT_PLANE, @MappingQCoordinates.DirectVector);
  2100. glEnable(GL_TEXTURE_GEN_R);
  2101. glEnable(GL_TEXTURE_GEN_Q);
  2102. end;
  2103. end;
  2104. tmmEyeLinear:
  2105. begin
  2106. glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  2107. glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  2108. // specify planes in eye space, not world space
  2109. glMatrixMode(GL_MODELVIEW);
  2110. glPushMatrix;
  2111. glLoadIdentity;
  2112. glTexGenfv(GL_S, GL_EYE_PLANE, @MappingSCoordinates.DirectVector);
  2113. glTexGenfv(GL_T, GL_EYE_PLANE, @MappingTCoordinates.DirectVector);
  2114. glEnable(GL_TEXTURE_GEN_S);
  2115. glEnable(GL_TEXTURE_GEN_T);
  2116. /// if GL_TEXTURE_CUBE_MAP or GL_TEXTURE_3D then
  2117. begin
  2118. glTexGenfv(GL_R, GL_EYE_PLANE, @MappingRCoordinates.DirectVector);
  2119. glTexGenfv(GL_Q, GL_EYE_PLANE, @MappingQCoordinates.DirectVector);
  2120. glEnable(GL_TEXTURE_GEN_R);
  2121. glEnable(GL_TEXTURE_GEN_Q);
  2122. end;
  2123. glPopMatrix;
  2124. end;
  2125. tmmSphere:
  2126. begin
  2127. glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
  2128. glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
  2129. glEnable(GL_TEXTURE_GEN_S);
  2130. glEnable(GL_TEXTURE_GEN_T);
  2131. end;
  2132. tmmCubeMapReflection, tmmCubeMapCamera:
  2133. /// if GL_TEXTURE_CUBE_MAP then
  2134. begin
  2135. glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
  2136. glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
  2137. glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
  2138. glEnable(GL_TEXTURE_GEN_S);
  2139. glEnable(GL_TEXTURE_GEN_T);
  2140. glEnable(GL_TEXTURE_GEN_R);
  2141. end;
  2142. tmmCubeMapNormal, tmmCubeMapLight0:
  2143. /// if GL_TEXTURE_CUBE_MAP then
  2144. begin
  2145. glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
  2146. glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
  2147. glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
  2148. glEnable(GL_TEXTURE_GEN_S);
  2149. glEnable(GL_TEXTURE_GEN_T);
  2150. glEnable(GL_TEXTURE_GEN_R);
  2151. end;
  2152. else
  2153. Assert(False);
  2154. end;
  2155. end;
  2156. procedure TgxTexture.UnApplyMappingMode;
  2157. begin
  2158. if MappingMode <> tmmUser then
  2159. begin
  2160. glDisable(GL_TEXTURE_GEN_S);
  2161. glDisable(GL_TEXTURE_GEN_T);
  2162. /// if GL_TEXTURE_3D or GL_TEXTURE_CUBE_MAP then
  2163. begin
  2164. glDisable(GL_TEXTURE_GEN_R);
  2165. glDisable(GL_TEXTURE_GEN_Q);
  2166. end;
  2167. end;
  2168. end;
  2169. procedure TgxTexture.Apply(var rci: TgxRenderContextInfo);
  2170. procedure SetCubeMapTextureMatrix;
  2171. var
  2172. m, mm: TMatrix4f;
  2173. begin
  2174. // compute model view matrix for proper viewing
  2175. case MappingMode of
  2176. tmmCubeMapReflection, tmmCubeMapNormal:
  2177. begin
  2178. m := rci.PipelineTransformation.ViewMatrix^;
  2179. NormalizeMatrix(m);
  2180. TransposeMatrix(m);
  2181. rci.gxStates.SetTextureMatrix(m);
  2182. end;
  2183. tmmCubeMapLight0:
  2184. begin
  2185. with TgxScene(rci.scene).Lights do
  2186. if Count > 0 then
  2187. begin
  2188. m := TgxLightSource(Items[0]).AbsoluteMatrix;
  2189. NormalizeMatrix(m);
  2190. mm := rci.PipelineTransformation.ViewMatrix^;
  2191. NormalizeMatrix(mm);
  2192. TransposeMatrix(mm);
  2193. m := MatrixMultiply(m, mm);
  2194. rci.gxStates.SetTextureMatrix(m);
  2195. end;
  2196. end;
  2197. tmmCubeMapCamera:
  2198. begin
  2199. m.X := VectorCrossProduct(rci.cameraUp, rci.cameraDirection);
  2200. m.Y := VectorNegate(rci.cameraDirection);
  2201. m.Z := rci.cameraUp;
  2202. m.W := WHmgPoint;
  2203. mm := rci.PipelineTransformation.ViewMatrix^;
  2204. NormalizeMatrix(mm);
  2205. TransposeMatrix(mm);
  2206. m := MatrixMultiply(m, mm);
  2207. rci.gxStates.SetTextureMatrix(m);
  2208. end;
  2209. end;
  2210. end;
  2211. var
  2212. H : Cardinal;
  2213. begin
  2214. // Multisample image do not work with FFP
  2215. if (FTextureHandle.Target = ttTexture2DMultisample) or
  2216. (FTextureHandle.Target = ttTexture2DMultisampleArray) then
  2217. exit;
  2218. H := Handle;
  2219. if not Disabled and (H > 0) then
  2220. begin
  2221. with rci.gxStates do
  2222. begin
  2223. ActiveTexture := 0;
  2224. TextureBinding[0, FTextureHandle.Target] := H;
  2225. ActiveTextureEnabled[FTextureHandle.Target] := True;
  2226. end;
  2227. if not rci.gxStates.ForwardContext then
  2228. begin
  2229. if FTextureHandle.Target = ttTextureCube then
  2230. SetCubeMapTextureMatrix;
  2231. glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
  2232. cTextureMode[FTextureMode]);
  2233. glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, FEnvColor.AsAddress);
  2234. ApplyMappingMode;
  2235. xglMapTexCoordToMain;
  2236. end;
  2237. end
  2238. else if not rci.gxStates.ForwardContext then
  2239. begin // default
  2240. xglMapTexCoordToMain;
  2241. end;
  2242. end;
  2243. procedure TgxTexture.UnApply(var rci: TgxRenderContextInfo);
  2244. begin
  2245. if not Disabled
  2246. and not rci.gxStates.ForwardContext then
  2247. begin
  2248. // Multisample image do not work with FFP
  2249. if FTextureHandle.Target in [ttNoShape, ttTexture2DMultisample, ttTexture2DMultisampleArray] then
  2250. exit;
  2251. with rci.gxStates do
  2252. begin
  2253. ActiveTexture := 0;
  2254. ActiveTextureEnabled[FTextureHandle.Target] := False;
  2255. if FTextureHandle.Target = ttTextureCube then
  2256. ResetTextureMatrix;
  2257. end;
  2258. UnApplyMappingMode;
  2259. end;
  2260. end;
  2261. procedure TgxTexture.ApplyAsTexture2(var rci: TgxRenderContextInfo; textureMatrix:
  2262. PMatrix4f = nil);
  2263. begin
  2264. ApplyAsTextureN(2, rci, textureMatrix);
  2265. end;
  2266. procedure TgxTexture.UnApplyAsTexture2(var rci: TgxRenderContextInfo;
  2267. reloadIdentityTextureMatrix: boolean);
  2268. begin
  2269. UnApplyAsTextureN(2, rci, reloadIdentityTextureMatrix);
  2270. end;
  2271. procedure TgxTexture.ApplyAsTextureN(n: Integer; var rci: TgxRenderContextInfo;
  2272. textureMatrix: PMatrix4f = nil);
  2273. var
  2274. m: TMatrix4f;
  2275. begin
  2276. if not Disabled then
  2277. begin
  2278. // Multisample image do not work with FFP
  2279. if (FTextureHandle.Target = ttTexture2DMultisample) or
  2280. (FTextureHandle.Target = ttTexture2DMultisampleArray) then
  2281. exit;
  2282. with rci.gxStates do
  2283. begin
  2284. ActiveTexture := n - 1;
  2285. TextureBinding[n - 1, FTextureHandle.Target] := Handle;
  2286. ActiveTextureEnabled[FTextureHandle.Target] := True;
  2287. if Assigned(textureMatrix) then
  2288. SetTextureMatrix(textureMatrix^)
  2289. else if FTextureHandle.Target = ttTextureCube then
  2290. begin
  2291. m := rci.PipelineTransformation.ModelViewMatrix^;
  2292. NormalizeMatrix(m);
  2293. TransposeMatrix(m);
  2294. rci.gxStates.SetTextureMatrix(m);
  2295. end;
  2296. if not ForwardContext then
  2297. begin
  2298. glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, cTextureMode[FTextureMode]);
  2299. glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, FEnvColor.AsAddress);
  2300. ApplyMappingMode;
  2301. ActiveTexture := 0;
  2302. end;
  2303. end;
  2304. end;
  2305. end;
  2306. procedure TgxTexture.UnApplyAsTextureN(n: Integer; var rci: TgxRenderContextInfo;
  2307. reloadIdentityTextureMatrix: boolean);
  2308. begin
  2309. if not rci.gxStates.ForwardContext then
  2310. begin
  2311. // Multisample image do not work with FFP
  2312. if (FTextureHandle.Target = ttTexture2DMultisample) or
  2313. (FTextureHandle.Target = ttTexture2DMultisampleArray) then
  2314. exit;
  2315. with rci.gxStates do
  2316. begin
  2317. ActiveTexture := n - 1;
  2318. ActiveTextureEnabled[FTextureHandle.Target] := False;
  2319. UnApplyMappingMode;
  2320. if (FTextureHandle.Target = ttTextureCube) or reloadIdentityTextureMatrix then
  2321. ResetTextureMatrix;
  2322. ActiveTexture := 0;
  2323. end;
  2324. end;
  2325. end;
  2326. function TgxTexture.AllocateHandle: Cardinal;
  2327. var
  2328. vTarget: TglTextureTarget;
  2329. begin
  2330. vTarget := Image.NativeTextureTarget;
  2331. if (vTarget <> ttNoShape) and (FTextureHandle.Target <> vTarget) then
  2332. FTextureHandle.DestroyHandle;
  2333. Result := FTextureHandle.Handle;
  2334. if Result = 0 then
  2335. begin
  2336. FTextureHandle.AllocateHandle;
  2337. Result := FTextureHandle.Handle;
  2338. end;
  2339. if FTextureHandle.IsDataNeedUpdate then
  2340. begin
  2341. FTextureHandle.Target := vTarget;
  2342. FSamplerHandle.NotifyChangesOfData;
  2343. end;
  2344. if FSamplerHandle.Handle = 0 then
  2345. FSamplerHandle.AllocateHandle;
  2346. // bind texture
  2347. if (FTextureHandle.Target <> ttNoShape) and
  2348. IsTargetSupported(FTextureHandle.Target) then
  2349. begin
  2350. if FSamplerHandle.IsDataNeedUpdate then
  2351. begin
  2352. with CurrentContext.gxStates do
  2353. TextureBinding[ActiveTexture, FTextureHandle.Target] := Result;
  2354. PrepareParams(DecodeTextureTarget(FTextureHandle.Target));
  2355. FSamplerHandle.NotifyDataUpdated;
  2356. end;
  2357. end
  2358. else
  2359. Result := 0;
  2360. end;
  2361. function TgxTexture.IsHandleAllocated: Boolean;
  2362. begin
  2363. Result := (FTextureHandle.Handle <> 0);
  2364. end;
  2365. function TgxTexture.GetHandle: Cardinal;
  2366. var
  2367. target: Cardinal;
  2368. LBinding: array[TglTextureTarget] of Cardinal;
  2369. procedure StoreBindings;
  2370. var
  2371. t: TglTextureTarget;
  2372. begin
  2373. with CurrentContext.gxStates do
  2374. begin
  2375. if TextureBinding[ActiveTexture, FTextureHandle.Target] = FTextureHandle.Handle then
  2376. TextureBinding[ActiveTexture, FTextureHandle.Target] := 0;
  2377. for t := Low(TglTextureTarget) to High(TglTextureTarget) do
  2378. LBinding[t] := TextureBinding[ActiveTexture, t];
  2379. end;
  2380. end;
  2381. procedure RestoreBindings;
  2382. var
  2383. t: TglTextureTarget;
  2384. begin
  2385. with CurrentContext.gxStates do
  2386. for t := Low(TglTextureTarget) to High(TglTextureTarget) do
  2387. TextureBinding[ActiveTexture, t] := LBinding[t];
  2388. end;
  2389. begin
  2390. with CurrentContext.gxStates do
  2391. begin
  2392. StoreBindings;
  2393. try
  2394. Result := AllocateHandle;
  2395. if FTextureHandle.IsDataNeedUpdate then
  2396. begin
  2397. FTextureHandle.NotifyDataUpdated;
  2398. // Check supporting
  2399. target := DecodeTextureTarget(Image.NativeTextureTarget);
  2400. if not IsTargetSupported(target)
  2401. or not IsFormatSupported(TextureFormatEx) then
  2402. begin
  2403. SetTextureErrorImage;
  2404. target := GL_TEXTURE_2D;
  2405. end;
  2406. // Load images
  2407. // if not GL_EXT_direct_state_access then
  2408. TextureBinding[ActiveTexture, FTextureHandle.Target] := Result;
  2409. PrepareImage(target);
  2410. end;
  2411. finally
  2412. RestoreBindings;
  2413. end;
  2414. end;
  2415. end;
  2416. procedure TgxTexture.DestroyHandles;
  2417. begin
  2418. FTextureHandle.DestroyHandle;
  2419. FSamplerHandle.DestroyHandle;
  2420. FRequiredMemorySize := -1;
  2421. end;
  2422. function TgxTexture.IsFloatType: Boolean;
  2423. begin
  2424. Result := IsFloatFormat(TextureFormatEx);
  2425. end;
  2426. function TgxTexture.OpenGLTextureFormat: Integer;
  2427. var
  2428. texComp: TgxTextureCompression;
  2429. begin
  2430. if GL_TEXTURE_COMPRESSION_HINT > 0 then ///
  2431. begin
  2432. if Compression = tcDefault then
  2433. if vDefaultTextureCompression = tcDefault then
  2434. texComp := tcNone
  2435. else
  2436. texComp := vDefaultTextureCompression
  2437. else
  2438. texComp := Compression;
  2439. end
  2440. else
  2441. texComp := tcNone;
  2442. if IsFloatType then
  2443. texComp := tcNone; // no compression support for float_type
  2444. if (texComp <> tcNone) and (TextureFormat <= tfNormalMap) then
  2445. with CurrentContext.gxStates do
  2446. begin
  2447. case texComp of
  2448. tcStandard: TextureCompressionHint := hintDontCare;
  2449. tcHighQuality: TextureCompressionHint := hintNicest;
  2450. tcHighSpeed: TextureCompressionHint := hintFastest;
  2451. else
  2452. Assert(False);
  2453. end;
  2454. Result := CompressedInternalFormatToOpenGL(TextureFormatEx);
  2455. end
  2456. else
  2457. Result := InternalFormatToOpenGLFormat(TextureFormatEx);
  2458. end;
  2459. procedure TgxTexture.PrepareImage(target: Cardinal);
  2460. var
  2461. bitmap32: TgxImage;
  2462. texComp: TgxTextureCompression;
  2463. glFormat: Cardinal;
  2464. begin
  2465. if Image.IsSelfLoading then
  2466. begin
  2467. Image.LoadTexture(FTextureFormat);
  2468. end
  2469. else
  2470. begin
  2471. bitmap32 := Image.GetBitmap32;
  2472. if (bitmap32 = nil) or bitmap32.IsEmpty then
  2473. Exit;
  2474. if TextureFormat = tfNormalMap then
  2475. bitmap32.GrayScaleToNormalMap(NormalMapScale,
  2476. TextureWrap in [twBoth, twHorizontal],
  2477. TextureWrap in [twBoth, twVertical]);
  2478. // prepare AlphaChannel
  2479. case ImageAlpha of
  2480. tiaDefault: ; // nothing to do
  2481. tiaAlphaFromIntensity:
  2482. bitmap32.SetAlphaFromIntensity;
  2483. tiaSuperBlackTransparent:
  2484. bitmap32.SetAlphaTransparentForColor($000000);
  2485. tiaLuminance:
  2486. bitmap32.SetAlphaFromIntensity;
  2487. tiaLuminanceSqrt:
  2488. begin
  2489. bitmap32.SetAlphaFromIntensity;
  2490. bitmap32.SqrtAlpha;
  2491. end;
  2492. tiaOpaque:
  2493. bitmap32.SetAlphaToValue(255);
  2494. tiaTopLeftPointColorTransparent:
  2495. begin
  2496. bitmap32.Narrow;
  2497. bitmap32.SetAlphaTransparentForColor(bitmap32.Data^[0]);
  2498. end;
  2499. tiaInverseLuminance:
  2500. begin
  2501. bitmap32.SetAlphaFromIntensity;
  2502. bitmap32.InvertAlpha;
  2503. end;
  2504. tiaInverseLuminanceSqrt:
  2505. begin
  2506. bitmap32.SetAlphaFromIntensity;
  2507. bitmap32.SqrtAlpha;
  2508. bitmap32.InvertAlpha;
  2509. end;
  2510. tiaBottomRightPointColorTransparent:
  2511. begin
  2512. bitmap32.Narrow;
  2513. bitmap32.SetAlphaTransparentForColor(bitmap32.Data^[bitmap32.Width - 1]);
  2514. end;
  2515. else
  2516. Assert(False);
  2517. end;
  2518. // apply brightness correction
  2519. if FImageBrightness <> 1.0 then
  2520. bitmap32.BrightnessCorrection(FImageBrightness);
  2521. // apply gamma correction
  2522. if FImageGamma <> 1.0 then
  2523. bitmap32.GammaCorrection(FImageGamma);
  2524. if /// GL_ARB_texture_compression and
  2525. (TextureFormat <> tfExtended) then
  2526. begin
  2527. if Compression = tcDefault then
  2528. if vDefaultTextureCompression = tcDefault then
  2529. texComp := tcNone
  2530. else
  2531. texComp := vDefaultTextureCompression
  2532. else
  2533. texComp := Compression;
  2534. if IsFloatType then
  2535. texComp := tcNone;
  2536. end
  2537. else
  2538. texComp := tcNone;
  2539. if (texComp <> tcNone) and (TextureFormat <= tfNormalMap) then
  2540. with CurrentContext.gxStates do
  2541. begin
  2542. case texComp of
  2543. tcStandard: TextureCompressionHint := hintDontCare;
  2544. tcHighQuality: TextureCompressionHint := hintNicest;
  2545. tcHighSpeed: TextureCompressionHint := hintFastest;
  2546. else
  2547. Assert(False, strErrorEx + strUnknownType);
  2548. end;
  2549. glFormat := CompressedInternalFormatToOpenGL(FTextureFormat);
  2550. end
  2551. else
  2552. glFormat := InternalFormatToOpenGLFormat(FTextureFormat);
  2553. bitmap32.RegisterAsOpenRXTexture(
  2554. FTextureHandle,
  2555. not (FMinFilter in [miNearest, miLinear]),
  2556. glFormat,
  2557. FTexWidth,
  2558. FTexHeight,
  2559. FTexDepth);
  2560. end;
  2561. if glGetError <> GL_NO_ERROR then
  2562. begin
  2563. SetTextureErrorImage;
  2564. end
  2565. else
  2566. begin
  2567. FRequiredMemorySize := -1;
  2568. TextureImageRequiredMemory;
  2569. if not IsDesignTime and not FKeepImageAfterTransfer then
  2570. Image.ReleaseBitmap32;
  2571. end;
  2572. end;
  2573. procedure TgxTexture.PrepareParams(target: Cardinal);
  2574. const
  2575. cTextureSWrap: array[twBoth..twHorizontal] of Cardinal =
  2576. (GL_REPEAT, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_REPEAT);
  2577. cTextureTWrap: array[twBoth..twHorizontal] of Cardinal =
  2578. (GL_REPEAT, GL_CLAMP_TO_EDGE, GL_REPEAT, GL_CLAMP_TO_EDGE);
  2579. cTextureRWrap: array[twBoth..twHorizontal] of Cardinal =
  2580. (GL_REPEAT, GL_CLAMP_TO_EDGE, GL_REPEAT, GL_CLAMP_TO_EDGE);
  2581. cTextureSWrapOld: array[twBoth..twHorizontal] of Cardinal =
  2582. (GL_REPEAT, GL_CLAMP, GL_CLAMP, GL_REPEAT);
  2583. cTextureTWrapOld: array[twBoth..twHorizontal] of Cardinal =
  2584. (GL_REPEAT, GL_CLAMP, GL_REPEAT, GL_CLAMP);
  2585. cTextureMagFilter: array[maNearest..maLinear] of Cardinal =
  2586. (GL_NEAREST, GL_LINEAR);
  2587. cTextureMinFilter: array[miNearest..miLinearMipmapLinear] of Cardinal =
  2588. (GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST,
  2589. GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR,
  2590. GL_LINEAR_MIPMAP_LINEAR);
  2591. cFilteringQuality: array[tfIsotropic..tfAnisotropic] of Integer = (1, 2);
  2592. cSeparateTextureWrap: array[twRepeat..twMirrorClampToBorder] of Cardinal =
  2593. (GL_REPEAT, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER,
  2594. GL_MIRRORED_REPEAT, GL_MIRROR_CLAMP_TO_EDGE_ATI, GL_MIRROR_CLAMP_TO_BORDER_EXT);
  2595. cTextureCompareMode: array[tcmNone..tcmCompareRtoTexture] of Cardinal =
  2596. (GL_NONE, GL_COMPARE_R_TO_TEXTURE);
  2597. cDepthTextureMode: array[dtmLuminance..dtmAlpha] of Cardinal =
  2598. (GL_LUMINANCE, GL_INTENSITY, GL_ALPHA);
  2599. var
  2600. lMinFilter: TgxMinFilter;
  2601. begin
  2602. if (target = GL_TEXTURE_2D_MULTISAMPLE)
  2603. or (target = GL_TEXTURE_2D_MULTISAMPLE_ARRAY) then
  2604. Exit;
  2605. with CurrentContext.gxStates do
  2606. begin
  2607. UnpackAlignment := 1;
  2608. UnpackRowLength := 0;
  2609. UnpackSkipRows := 0;
  2610. UnpackSkipPixels := 0;
  2611. end;
  2612. glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, FBorderColor.AsAddress);
  2613. /// if (GL_VERSION_1_2 or GL_texture_edge_clamp) then
  2614. begin
  2615. if FTextureWrap = twSeparate then
  2616. begin
  2617. glTexParameteri(target, GL_TEXTURE_WRAP_S,
  2618. cSeparateTextureWrap[FTextureWrapS]);
  2619. glTexParameteri(target, GL_TEXTURE_WRAP_T,
  2620. cSeparateTextureWrap[FTextureWrapT]);
  2621. if (target = GL_TEXTURE_3D) then ///
  2622. glTexParameteri(target, GL_TEXTURE_WRAP_R,
  2623. cSeparateTextureWrap[FTextureWrapR]);
  2624. end
  2625. else
  2626. begin
  2627. glTexParameteri(target, GL_TEXTURE_WRAP_S, cTextureSWrap[FTextureWrap]);
  2628. glTexParameteri(target, GL_TEXTURE_WRAP_T, cTextureTWrap[FTextureWrap]);
  2629. /// if R_Dim then
  2630. glTexParameteri(target, GL_TEXTURE_WRAP_R, cTextureRWrap[FTextureWrap]);
  2631. end;
  2632. end;
  2633. (*
  2634. else
  2635. begin
  2636. glTexParameteri(target, GL_TEXTURE_WRAP_S, cTextureSWrapOld[FTextureWrap]);
  2637. glTexParameteri(target, GL_TEXTURE_WRAP_T, cTextureTWrapOld[FTextureWrap]);
  2638. end;
  2639. *)
  2640. lMinFilter := FMinFilter;
  2641. // Down paramenter to rectangular texture supported
  2642. if (target = GL_TEXTURE_RECTANGLE)
  2643. /// or not (GL_EXT_texture_lod_bias or GL_SGIS_texture_lod)
  2644. then
  2645. begin
  2646. if lMinFilter in [miNearestMipmapNearest, miNearestMipmapLinear] then
  2647. lMinFilter := miNearest;
  2648. if FMinFilter in [miLinearMipmapNearest, miLinearMipmapLinear] then
  2649. lMinFilter := miLinear;
  2650. end;
  2651. glTexParameteri(target, GL_TEXTURE_MIN_FILTER, cTextureMinFilter[lMinFilter]);
  2652. glTexParameteri(target, GL_TEXTURE_MAG_FILTER, cTextureMagFilter[FMagFilter]);
  2653. /// if GL_EXT_texture_filter_anisotropic then
  2654. glTexParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT,
  2655. cFilteringQuality[FFilteringQuality]);
  2656. if IsDepthFormat(fTextureFormat) then
  2657. begin
  2658. glTexParameteri(target, GL_TEXTURE_COMPARE_MODE,
  2659. cTextureCompareMode[fTextureCompareMode]);
  2660. glTexParameteri(target, GL_TEXTURE_COMPARE_FUNC,
  2661. cGLComparisonFunctionToGLEnum[fTextureCompareFunc]);
  2662. /// if not FTextureHandle.RenderingContext.gxStates.ForwardContext then
  2663. glTexParameteri(target, GL_DEPTH_TEXTURE_MODE,
  2664. cDepthTextureMode[fDepthTextureMode]);
  2665. end;
  2666. end;
  2667. procedure TgxTexture.DoOnTextureNeeded(Sender: TObject; var textureFileName:
  2668. string);
  2669. begin
  2670. if Assigned(FOnTextureNeeded) then
  2671. FOnTextureNeeded(Sender, textureFileName);
  2672. end;
  2673. procedure TgxTexture.OnSamplerAllocate(Sender: TgxVirtualHandle; var Handle: Cardinal);
  2674. begin
  2675. Handle := 1;
  2676. end;
  2677. procedure TgxTexture.OnSamplerDestroy(Sender: TgxVirtualHandle; var Handle: Cardinal);
  2678. begin
  2679. Handle := 0;
  2680. end;
  2681. procedure TgxTexture.SetTextureErrorImage;
  2682. var
  2683. img: TgxImage;
  2684. begin
  2685. img := TgxImage.Create;
  2686. img.SetErrorImage;
  2687. ImageClassName := TgxBlankImage.className;
  2688. TgxBlankImage(Image).Assign(img);
  2689. img.Free;
  2690. MagFilter := maNearest;
  2691. MinFilter := miNearest;
  2692. TextureWrap := twBoth;
  2693. MappingMode := tmmUser;
  2694. Compression := tcNone;
  2695. AllocateHandle;
  2696. end;
  2697. // ---------------
  2698. // --------------- TgxTextureExItem ---------------
  2699. // ---------------
  2700. constructor TgxTextureExItem.Create(ACollection: TCollection);
  2701. begin
  2702. inherited;
  2703. FTexture := TgxTexture.Create(Self);
  2704. FTextureOffset := TgxCoordinates.CreateInitialized(Self, NullHMGVector,
  2705. csPoint);
  2706. FTextureOffset.OnNotifyChange := OnNotifyChange;
  2707. FTextureScale := TgxCoordinates.CreateInitialized(Self, XYZHmgVector,
  2708. csPoint);
  2709. FTextureScale.OnNotifyChange := OnNotifyChange;
  2710. FTextureIndex := ID;
  2711. FTextureMatrix := IdentityHMGMatrix;
  2712. // not very flexible code, assumes it's owned by a material,
  2713. // that has a Texture property, but may need to re-implement it somehow
  2714. (*
  2715. if ACollection is TgxTextureEx then
  2716. if TgxTextureEx(ACollection).FOwner <> nil then
  2717. FTexture.OnTextureNeeded := TgxTextureEx(ACollection).FOwner.Texture.OnTextureNeeded;
  2718. *)
  2719. end;
  2720. destructor TgxTextureExItem.Destroy;
  2721. begin
  2722. FTexture.Free;
  2723. FTextureOffset.Free;
  2724. FTextureScale.Free;
  2725. inherited;
  2726. end;
  2727. function TgxTextureExItem.QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
  2728. begin
  2729. if GetInterface(IID, Obj) then
  2730. Result := S_OK
  2731. else
  2732. Result := E_NOINTERFACE;
  2733. end;
  2734. function TgxTextureExItem._AddRef: Integer; stdcall;
  2735. begin
  2736. Result := -1; //ignore
  2737. end;
  2738. function TgxTextureExItem._Release: Integer; stdcall;
  2739. begin
  2740. Result := -1; //ignore
  2741. end;
  2742. procedure TgxTextureExItem.Assign(Source: TPersistent);
  2743. begin
  2744. if Source is TgxTextureExItem then
  2745. begin
  2746. Texture := TgxTextureExItem(Source).Texture;
  2747. TextureIndex := TgxTextureExItem(Source).TextureIndex;
  2748. TextureOffset := TgxTextureExItem(Source).TextureOffset;
  2749. TextureScale := TgxTextureExItem(Source).TextureScale;
  2750. NotifyChange(Self);
  2751. end
  2752. else
  2753. inherited;
  2754. end;
  2755. procedure TgxTextureExItem.NotifyChange(Sender: TObject);
  2756. begin
  2757. if Assigned(Collection) then
  2758. TgxTextureEx(Collection).NotifyChange(Self);
  2759. end;
  2760. procedure TgxTextureExItem.Apply(var rci: TgxRenderContextInfo);
  2761. begin
  2762. FApplied := False;
  2763. if FTexture.Enabled then
  2764. begin
  2765. rci.gxStates.ActiveTexture := FTextureIndex;
  2766. glMatrixMode(GL_TEXTURE);
  2767. glPushMatrix;
  2768. if FTextureMatrixIsIdentity then
  2769. glLoadIdentity
  2770. else
  2771. glLoadMatrixf(@FTextureMatrix.X.X);
  2772. glMatrixMode(GL_MODELVIEW);
  2773. rci.gxStates.ActiveTexture := 0;
  2774. if FTextureIndex = 0 then
  2775. FTexture.Apply(rci)
  2776. else if FTextureIndex = 1 then
  2777. FTexture.ApplyAsTexture2(rci, nil)
  2778. else if FTextureIndex >= 2 then
  2779. FTexture.ApplyAsTextureN(FTextureIndex + 1, rci, nil);
  2780. FApplied := True;
  2781. end;
  2782. end;
  2783. procedure TgxTextureExItem.UnApply(var rci: TgxRenderContextInfo);
  2784. begin
  2785. if FApplied then
  2786. begin
  2787. if FTextureIndex = 0 then
  2788. FTexture.UnApply(rci)
  2789. else if FTextureIndex = 1 then
  2790. FTexture.UnApplyAsTexture2(rci, false)
  2791. else if FTextureIndex >= 2 then
  2792. FTexture.UnApplyAsTextureN(FTextureIndex + 1, rci, false);
  2793. rci.gxStates.ActiveTexture := FTextureIndex;
  2794. glMatrixMode(GL_TEXTURE);
  2795. glPopMatrix;
  2796. glMatrixMode(GL_MODELVIEW);
  2797. rci.gxStates.ActiveTexture := 0;
  2798. FApplied := False;
  2799. end;
  2800. end;
  2801. function TgxTextureExItem.GetDisplayName: string;
  2802. begin
  2803. Result := Format('Tex [%d]', [FTextureIndex]);
  2804. end;
  2805. function TgxTextureExItem.GetOwner: TPersistent;
  2806. begin
  2807. Result := Collection;
  2808. end;
  2809. procedure TgxTextureExItem.NotifyTexMapChange(Sender: TObject);
  2810. var
  2811. intf: IgxTextureNotifyAble;
  2812. begin
  2813. if Supports(TObject(TgxTextureEx(Collection).FOwner), IgxTextureNotifyAble,
  2814. intf) then
  2815. intf.NotifyTexMapChange(Sender);
  2816. end;
  2817. procedure TgxTextureExItem.SetTexture(const Value: TgxTexture);
  2818. begin
  2819. FTexture.Assign(Value);
  2820. NotifyChange(Self);
  2821. end;
  2822. procedure TgxTextureExItem.SetTextureIndex(const Value: Integer);
  2823. var
  2824. temp: Integer;
  2825. begin
  2826. temp := Value;
  2827. if temp < 0 then
  2828. temp := 0;
  2829. if temp <> FTextureIndex then
  2830. begin
  2831. FTextureIndex := temp;
  2832. NotifyChange(Self);
  2833. end;
  2834. end;
  2835. procedure TgxTextureExItem.SetTextureOffset(const Value: TgxCoordinates);
  2836. begin
  2837. FTextureOffset.Assign(Value);
  2838. NotifyChange(Self);
  2839. end;
  2840. procedure TgxTextureExItem.SetTextureScale(const Value: TgxCoordinates);
  2841. begin
  2842. FTextureScale.Assign(Value);
  2843. NotifyChange(Self);
  2844. end;
  2845. procedure TgxTextureExItem.CalculateTextureMatrix;
  2846. begin
  2847. if TextureOffset.Equals(NullHmgVector) and TextureScale.Equals(XYZHmgVector) then
  2848. FTextureMatrixIsIdentity := True
  2849. else
  2850. begin
  2851. FTextureMatrixIsIdentity := False;
  2852. FTextureMatrix := CreateScaleAndTranslationMatrix(TextureScale.AsVector,
  2853. TextureOffset.AsVector);
  2854. end;
  2855. NotifyChange(Self);
  2856. end;
  2857. procedure TgxTextureExItem.OnNotifyChange(Sender: TObject);
  2858. begin
  2859. CalculateTextureMatrix;
  2860. end;
  2861. // ---------------
  2862. // --------------- TgxTextureEx ---------------
  2863. // ---------------
  2864. constructor TgxTextureEx.Create(AOwner: TgxUpdateAbleObject);
  2865. begin
  2866. inherited Create(TgxTextureExItem);
  2867. FOwner := AOwner;
  2868. end;
  2869. procedure TgxTextureEx.NotifyChange(Sender: TObject);
  2870. begin
  2871. if Assigned(FOwner) then
  2872. FOwner.NotifyChange(Self);
  2873. end;
  2874. procedure TgxTextureEx.Apply(var rci: TgxRenderContextInfo);
  2875. var
  2876. i, texUnits: Integer;
  2877. units: Cardinal;
  2878. begin
  2879. /// if not (GL_ARB_multitexture) then exit;
  2880. units := 0;
  2881. glGetIntegeri_v(GL_MAX_TEXTURE_UNITS, 0, @texUnits);
  2882. for i := 0 to Count - 1 do
  2883. begin
  2884. if Items[i].TextureIndex < texUnits then
  2885. begin
  2886. Items[i].Apply(rci);
  2887. if Items[i].FApplied then
  2888. if (Items[i].TextureIndex > 0) and (Items[i].Texture.MappingMode =
  2889. tmmUser) then
  2890. units := units or (1 shl Items[i].TextureIndex);
  2891. end;
  2892. end;
  2893. if units > 0 then
  2894. xglMapTexCoordToArbitraryAdd(units);
  2895. end;
  2896. procedure TgxTextureEx.UnApply(var rci: TgxRenderContextInfo);
  2897. var
  2898. i: Integer;
  2899. begin
  2900. /// if not GL_ARB_multitexture then exit;
  2901. for i := 0 to Count - 1 do
  2902. Items[i].UnApply(rci);
  2903. end;
  2904. function TgxTextureEx.Add: TgxTextureExItem;
  2905. begin
  2906. Result := TgxTextureExItem(inherited Add);
  2907. end;
  2908. procedure TgxTextureEx.Loaded;
  2909. var
  2910. i: Integer;
  2911. begin
  2912. for i := 0 to Count - 1 do
  2913. Items[i].CalculateTextureMatrix;
  2914. end;
  2915. function TgxTextureEx.GetOwner: TPersistent;
  2916. begin
  2917. Result := FOwner;
  2918. end;
  2919. procedure TgxTextureEx.SetItems(index: Integer; const Value: TgxTextureExItem);
  2920. begin
  2921. inherited SetItem(index, Value);
  2922. end;
  2923. function TgxTextureEx.GetItems(index: Integer): TgxTextureExItem;
  2924. begin
  2925. Result := TgxTextureExItem(inherited GetItem(index));
  2926. end;
  2927. function TgxTextureEx.IsTextureEnabled(Index: Integer): Boolean;
  2928. var
  2929. i: Integer;
  2930. begin
  2931. Result := False;
  2932. if Self = nil then
  2933. Exit;
  2934. for i := 0 to Count - 1 do
  2935. if Items[i].TextureIndex = Index then
  2936. Result := Result or Items[i].Texture.Enabled;
  2937. end;
  2938. // ------------------------------------------------------------------
  2939. initialization
  2940. // ------------------------------------------------------------------
  2941. RegisterTextureImageClass(TgxBlankImage);
  2942. RegisterTextureImageClass(TgxPersistentImage);
  2943. RegisterTextureImageClass(TgxPicFileImage);
  2944. RegisterTextureImageClass(TgxCubeMapImage);
  2945. RegisterTGraphicClassFileExtension('.bmp', TBitmap);
  2946. finalization
  2947. vGxTextureImageClasses.Free;
  2948. vGxTextureImageClasses := nil;
  2949. end.