GXS.Texture.pas 92 KB

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