GLS.Texture.pas 92 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246
  1. //
  2. // The graphics engine GLScene https://github.com/glscene
  3. //
  4. unit GLS.Texture;
  5. (* Handles all texture stuff *)
  6. interface
  7. {$I GLScene.Defines.inc}
  8. uses
  9. Winapi.OpenGL,
  10. Winapi.OpenGLext,
  11. System.Classes,
  12. System.SysUtils,
  13. Vcl.Graphics,
  14. Vcl.Imaging.jpeg,
  15. Vcl.Imaging.pngimage,
  16. GLScene.OpenGLTokens,
  17. GLScene.VectorTypes,
  18. GLScene.VectorGeometry,
  19. GLScene.BaseClasses,
  20. GLS.Graphics,
  21. GLS.Context,
  22. GLS.State,
  23. GLS.Color,
  24. GLScene.Coordinates,
  25. GLS.RenderContextInfo,
  26. GLScene.PersistentClasses,
  27. GLS.PipelineTransformation,
  28. GLS.ImageUtils,
  29. GLScene.TextureFormat,
  30. GLS.ApplicationFileIO,
  31. GLScene.Utils,
  32. GLScene.Strings;
  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. TGLTextureMode = (tmDecal, tmModulate, tmBlend, tmReplace, tmAdd);
  43. TGLTextureWrap = (twBoth, twNone, twVertical, twHorizontal, twSeparate);
  44. TGLMinFilter =
  45. (
  46. miNearest,
  47. miLinear,
  48. miNearestMipmapNearest,
  49. miLinearMipmapNearest,
  50. miNearestMipmapLinear,
  51. miLinearMipmapLinear
  52. );
  53. TGLMagFilter = (maNearest, maLinear);
  54. (* Specifies how depth values should be treated
  55. during filtering and texture application *)
  56. TGLDepthTextureMode = (dtmLuminance, dtmIntensity, dtmAlpha);
  57. (* Specifies the depth comparison function. *)
  58. TGLDepthCompareFunc = TGLDepthFunction;
  59. (* Texture format for OpenGL (rendering) use.
  60. Internally, GLScene handles all "base" images as 32 Bits RGBA, but you can
  61. specify a generic format to reduce OpenGL texture memory use: *)
  62. TGLTextureFormat = (
  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. TGLTextureCompression = TGLInternalCompression;
  77. TGLTexture = class;
  78. IGLTextureNotifyAble = interface(IGNotifyAble)
  79. ['{0D9DC0B0-ECE4-4513-A8A1-5AE7022C9426}']
  80. procedure NotifyTexMapChange(Sender: TObject);
  81. end;
  82. TGLTextureNeededEvent = procedure(Sender: TObject; var textureFileName: string)
  83. of object;
  84. TGLTextureChange = (tcImage, tcParams);
  85. TGLTextureChanges = set of TGLTextureChange;
  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. TGLTextureImageAlpha =
  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 RegisterGLTextureImageClass to allow
  115. proper persistence and editability in the IDE experts. *)
  116. TGLTextureImage = class(TGUpdateAbleObject)
  117. private
  118. function GetResourceName: string;
  119. protected
  120. FOwnerTexture: TGLTexture;
  121. FOnTextureNeeded: TGLTextureNeededEvent;
  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: TGLTextureNeededEvent read FOnTextureNeeded write FOnTextureNeeded;
  130. public
  131. constructor Create(AOwner: TPersistent); override;
  132. destructor Destroy; override;
  133. property OwnerTexture: TGLTexture 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: TGLImage; virtual;
  160. (* Request for unloading bitmapData, to free some memory.
  161. This one is invoked when GLScene 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. TGLTextureImageClass = class of TGLTextureImage;
  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 TGLMemoryViewer for instance). *)
  180. TGLBlankImage = class(TGLTextureImage)
  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: TGLImage;
  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: TGLImage; 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 TPicture.
  220. TGLPictureImage = class(TGLTextureImage)
  221. private
  222. FBitmap: TGLImage;
  223. FGLPicture: TPicture;
  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: TPicture;
  231. procedure SetPicture(const aPicture: TPicture);
  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: TGLImage; override;
  243. procedure ReleaseBitmap32; override;
  244. // Holds the image content.
  245. property Picture: TPicture read GetPicture write SetPicture;
  246. end;
  247. (* Stores any image compatible with Delphi's TPicture mechanism.
  248. The picture's data is actually stored into the DFM, the original
  249. picture name or path is not remembered.
  250. It is similar in behaviour of 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. TGLPersistentImage = class(TGLPictureImage)
  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. TGLPicFileImage = class(TGLPictureImage)
  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: TGLImage; 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. TGLCubeMapTarget = Integer;
  297. (* A texture image used for specifying and stroing a cube map.
  298. Not unlike TGLPictureImage, but storing 6 of them instead of just one.
  299. Saving & loading as a whole currently not supported. *)
  300. TGLCubeMapImage = class(TGLTextureImage)
  301. private
  302. FImage: TGLImage;
  303. FUpdateCounter: Integer;
  304. FPicture: array[cmtPX..cmtNZ] of TPicture;
  305. protected
  306. function GetWidth: Integer; override;
  307. function GetHeight: Integer; override;
  308. function GetDepth: Integer; override;
  309. procedure SetPicture(index: TGLCubeMapTarget; const val: TPicture);
  310. function GetPicture(index: TGLCubeMapTarget): TPicture;
  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: TGLImage; 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: TGLCubeMapTarget]: TPicture read GetPicture write SetPicture;
  330. published
  331. property PicturePX: TPicture index cmtPX read GetPicture write SetPicture;
  332. property PictureNX: TPicture index cmtNX read GetPicture write SetPicture;
  333. property PicturePY: TPicture index cmtPY read GetPicture write SetPicture;
  334. property PictureNY: TPicture index cmtNY read GetPicture write SetPicture;
  335. property PicturePZ: TPicture index cmtPZ read GetPicture write SetPicture;
  336. property PictureNZ: TPicture index cmtNZ read GetPicture write SetPicture;
  337. end;
  338. TGLTextureMappingMode = (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 TGLTextureImageAlpha). *)
  345. TGLTexture = class(TGUpdateAbleObject)
  346. private
  347. FTextureHandle: TGLTextureHandle;
  348. FSamplerHandle: TGLVirtualHandle;
  349. FTextureFormat: TGLInternalFormat;
  350. FTextureMode: TGLTextureMode;
  351. FTextureWrap: TGLTextureWrap;
  352. FMinFilter: TGLMinFilter;
  353. FMagFilter: TGLMagFilter;
  354. FDisabled: Boolean;
  355. FImage: TGLTextureImage;
  356. FImageAlpha: TGLTextureImageAlpha;
  357. FImageBrightness: Single;
  358. FImageGamma: Single;
  359. FMappingMode: TGLTextureMappingMode;
  360. FMapSCoordinates: TGCoordinates4;
  361. FMapTCoordinates: TGCoordinates4;
  362. FMapRCoordinates: TGCoordinates4;
  363. FMapQCoordinates: TGCoordinates4;
  364. FOnTextureNeeded: TGLTextureNeededEvent;
  365. FCompression: TGLTextureCompression;
  366. FRequiredMemorySize: Integer;
  367. FFilteringQuality: TGLTextureFilteringQuality;
  368. FTexWidth: Integer;
  369. FTexHeight: Integer;
  370. FTexDepth: Integer;
  371. FEnvColor: TGLColor;
  372. FBorderColor: TGLColor;
  373. FNormalMapScale: Single;
  374. FTextureWrapS: TGLSeparateTextureWrap;
  375. FTextureWrapT: TGLSeparateTextureWrap;
  376. FTextureWrapR: TGLSeparateTextureWrap;
  377. fTextureCompareMode: TGLTextureCompareMode;
  378. fTextureCompareFunc: TGLDepthCompareFunc;
  379. fDepthTextureMode: TGLDepthTextureMode;
  380. FKeepImageAfterTransfer: Boolean;
  381. protected
  382. procedure SetImage(AValue: TGLTextureImage);
  383. procedure SetImageAlpha(const val: TGLTextureImageAlpha);
  384. procedure SetImageBrightness(const val: Single);
  385. function StoreBrightness: Boolean;
  386. procedure SetImageGamma(const val: Single);
  387. function StoreGamma: Boolean;
  388. procedure SetMagFilter(AValue: TGLMagFilter);
  389. procedure SetMinFilter(AValue: TGLMinFilter);
  390. procedure SetTextureMode(AValue: TGLTextureMode);
  391. procedure SetTextureWrap(AValue: TGLTextureWrap);
  392. procedure SetTextureWrapS(AValue: TGLSeparateTextureWrap);
  393. procedure SetTextureWrapT(AValue: TGLSeparateTextureWrap);
  394. procedure SetTextureWrapR(AValue: TGLSeparateTextureWrap);
  395. function GetTextureFormat: TGLTextureFormat;
  396. procedure SetTextureFormat(const val: TGLTextureFormat);
  397. procedure SetTextureFormatEx(const val: TGLInternalFormat);
  398. function StoreTextureFormatEx: Boolean;
  399. procedure SetCompression(const val: TGLTextureCompression);
  400. procedure SetFilteringQuality(const val: TGLTextureFilteringQuality);
  401. procedure SetMappingMode(const val: TGLTextureMappingMode);
  402. function GetMappingSCoordinates: TGCoordinates4;
  403. procedure SetMappingSCoordinates(const val: TGCoordinates4);
  404. function StoreMappingSCoordinates: Boolean;
  405. function GetMappingTCoordinates: TGCoordinates4;
  406. procedure SetMappingTCoordinates(const val: TGCoordinates4);
  407. function StoreMappingTCoordinates: Boolean;
  408. function GetMappingRCoordinates: TGCoordinates4;
  409. procedure SetMappingRCoordinates(const val: TGCoordinates4);
  410. function StoreMappingRCoordinates: Boolean;
  411. function GetMappingQCoordinates: TGCoordinates4;
  412. procedure SetMappingQCoordinates(const val: TGCoordinates4);
  413. function StoreMappingQCoordinates: Boolean;
  414. procedure SetDisabled(AValue: Boolean);
  415. procedure SetEnabled(const val: Boolean);
  416. function GetEnabled: Boolean; inline;
  417. procedure SetEnvColor(const val: TGLColor);
  418. procedure SetBorderColor(const val: TGLColor);
  419. procedure SetNormalMapScale(const val: Single);
  420. procedure SetTextureCompareMode(const val: TGLTextureCompareMode);
  421. procedure SetTextureCompareFunc(const val: TGLDepthCompareFunc);
  422. procedure SetDepthTextureMode(const val: TGLDepthTextureMode);
  423. function StoreNormalMapScale: Boolean;
  424. function StoreImageClassName: Boolean;
  425. function GetHandle: Cardinal;
  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: TGLVirtualHandle; var Handle: Cardinal);
  432. procedure OnSamplerDestroy(Sender: TGLVirtualHandle; 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: TGLTextureNeededEvent read FOnTextureNeeded write
  439. FOnTextureNeeded;
  440. procedure PrepareBuildList;
  441. procedure ApplyMappingMode;
  442. procedure UnApplyMappingMode;
  443. procedure Apply(var rci: TGLRenderContextInfo);
  444. procedure UnApply(var rci: TGLRenderContextInfo);
  445. // Applies to TEXTURE1
  446. procedure ApplyAsTexture2(var rci: TGLRenderContextInfo; textureMatrix: PGLMatrix = nil);
  447. procedure UnApplyAsTexture2(var rci: TGLRenderContextInfo;
  448. reloadIdentityTextureMatrix: boolean);
  449. // N=1 for TEXTURE0, N=2 for TEXTURE1, etc.
  450. procedure ApplyAsTextureN(n: Integer; var rci: TGLRenderContextInfo;
  451. textureMatrix: PGLMatrix = nil);
  452. procedure UnApplyAsTextureN(n: Integer; var rci: TGLRenderContextInfo;
  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: TGLTextureHandle read FTextureHandle;
  483. (* Actual width, height and depth used for last texture
  484. specification binding *)
  485. property TexWidth: Integer read FTexWidth;
  486. property TexHeight: Integer read FTexHeight;
  487. property TexDepth: Integer read FTexDepth;
  488. // Give texture rendering context
  489. published
  490. (* Image ClassName for enabling True polymorphism.
  491. This is ugly, but since the default streaming mechanism does a
  492. really bad job at storing polymorphic owned-object properties,
  493. and neither TFiler nor TPicture allow proper use of the built-in
  494. streaming, that's the only way to allow a user-extensible mechanism *)
  495. property ImageClassName: string read GetImageClassName write
  496. SetImageClassName stored StoreImageClassName;
  497. // Image data for the texture
  498. property Image: TGLTextureImage 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: TGLTextureImageAlpha read FImageAlpha write
  503. SetImageAlpha default tiaDefault;
  504. (* Texture brightness correction.
  505. This correction is applied upon loading a TGLTextureImage, 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 TGLTextureImage,
  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: TGLMagFilter read FMagFilter write SetMagFilter default maLinear;
  518. // Texture minification filter.
  519. property MinFilter: TGLMinFilter read FMinFilter write SetMinFilter default miLinearMipMapLinear;
  520. // Texture application mode.
  521. property TextureMode: TGLTextureMode read FTextureMode write SetTextureMode default tmDecal;
  522. // Wrapping mode for the texture.
  523. property TextureWrap: TGLTextureWrap 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 TGLTextureFormat for details
  532. property TextureFormat: TGLTextureFormat 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: TGLTextureCompression 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: TGLTextureMappingMode 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: TGCoordinates4 read GetMappingSCoordinates
  555. write SetMappingSCoordinates stored StoreMappingSCoordinates;
  556. property MappingTCoordinates: TGCoordinates4 read GetMappingTCoordinates
  557. write SetMappingTCoordinates stored StoreMappingTCoordinates;
  558. property MappingRCoordinates: TGCoordinates4 read GetMappingRCoordinates
  559. write SetMappingRCoordinates stored StoreMappingRCoordinates;
  560. property MappingQCoordinates: TGCoordinates4 read GetMappingQCoordinates
  561. write SetMappingQCoordinates stored StoreMappingQCoordinates;
  562. // Texture Environment color
  563. property EnvColor: TGLColor read FEnvColor write SetEnvColor;
  564. // Texture Border color
  565. property BorderColor: TGLColor 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: TGLDepthCompareFunc read fTextureCompareFunc
  577. write SetTextureCompareFunc default cfLequal;
  578. property DepthTextureMode: TGLDepthTextureMode 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. TGLTextureExItem = class(TCollectionItem, IGLTextureNotifyAble)
  585. private
  586. FTexture: TGLTexture;
  587. FTextureIndex: Integer;
  588. FTextureOffset, FTextureScale: TGCoordinates;
  589. FTextureMatrixIsIdentity: Boolean;
  590. FTextureMatrix: TGLMatrix;
  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: TGLTexture);
  600. procedure SetTextureIndex(const Value: Integer);
  601. procedure SetTextureOffset(const Value: TGCoordinates);
  602. procedure SetTextureScale(const Value: TGCoordinates);
  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: TGLRenderContextInfo); inline;
  612. procedure UnApply(var rci: TGLRenderContextInfo); inline;
  613. published
  614. property Texture: TGLTexture read FTexture write SetTexture;
  615. property TextureIndex: Integer read FTextureIndex write SetTextureIndex;
  616. property TextureOffset: TGCoordinates read FTextureOffset write SetTextureOffset;
  617. property TextureScale: TGCoordinates read FTextureScale write SetTextureScale;
  618. end;
  619. TGLTextureEx = class(TCollection)
  620. private
  621. FOwner: TGUpdateAbleObject;
  622. protected
  623. procedure SetItems(index: Integer; const Value: TGLTextureExItem);
  624. function GetItems(index: Integer): TGLTextureExItem; inline;
  625. function GetOwner: TPersistent; override;
  626. public
  627. constructor Create(AOwner: TGUpdateAbleObject);
  628. procedure NotifyChange(Sender: TObject);
  629. procedure Apply(var rci: TGLRenderContextInfo);
  630. procedure UnApply(var rci: TGLRenderContextInfo);
  631. function IsTextureEnabled(Index: Integer): Boolean; inline;
  632. function Add: TGLTextureExItem;
  633. property Items[index: Integer]: TGLTextureExItem read GetItems write
  634. SetItems; default;
  635. procedure Loaded;
  636. end;
  637. ETexture = class(Exception);
  638. EGLShaderException = class(Exception);
  639. // Register a TGLTextureImageClass (used for persistence and IDE purposes)
  640. procedure RegisterGLTextureImageClass(textureImageClass: TGLTextureImageClass);
  641. // Finds a registerer TGLTextureImageClass using its classname
  642. function FindGLTextureImageClass(const className: string): TGLTextureImageClass;
  643. // Finds a registerer TGLTextureImageClass using its FriendlyName
  644. function FindGLTextureImageClassByFriendlyName(const friendlyName: string):
  645. TGLTextureImageClass;
  646. // Defines a TStrings with the list of registered TGLTextureImageClass.
  647. procedure SetGLTextureImageClassesToStrings(aStrings: TStrings);
  648. (* Creates a TStrings with the list of registered TGLTextureImageClass.
  649. To be freed by caller. *)
  650. function GetGLTextureImageClassesAsStrings: TStrings;
  651. procedure RegisterTGraphicClassFileExtension(const extension: string;
  652. const aClass: TGraphicClass);
  653. function CreateGraphicFromFile(const fileName: string): TGraphic;
  654. //------------------------------------------------------------------------------
  655. implementation
  656. //------------------------------------------------------------------------------
  657. uses
  658. GLS.Scene, // TODO: remove dependancy on GLScene.pas unit (related to tmmCubeMapLight0)
  659. GLS.XOpenGL;
  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. vGLTextureImageClasses: TList;
  678. vTGraphicFileExtension: array of string;
  679. vTGraphicClass: array of TGraphicClass;
  680. type
  681. TFriendlyImage = class(TGLBaseImage);
  682. function xgl(): TGLMultitextureCoordinator; inline;
  683. begin
  684. Result := TGLMultitextureCoordinator(vCurrentGLContext.MultitextureCoordinator);
  685. end;
  686. // Dummy methods for CPP
  687. //
  688. function TGLTextureImage.GetTextureTarget: TGLTextureTarget;
  689. begin
  690. Result := ttNoShape;
  691. end;
  692. function TGLTextureImage.GetHeight: Integer;
  693. begin
  694. Result := 0;
  695. end;
  696. function TGLTextureImage.GetWidth: Integer;
  697. begin
  698. Result := 0;
  699. end;
  700. function TGLTextureImage.GetDepth: Integer;
  701. begin
  702. Result := 0;
  703. end;
  704. procedure TGLTextureImage.SaveToFile(const FileName: String);
  705. begin
  706. end;
  707. class function TGLTextureImage.FriendlyName: String;
  708. begin
  709. Result := '';
  710. end;
  711. function TGLTextureImage.GetBitmap32: TGLImage;
  712. begin
  713. Result := nil;
  714. end;
  715. procedure RegisterTGraphicClassFileExtension(const extension: string;
  716. const aClass: TGraphicClass);
  717. var
  718. n: Integer;
  719. begin
  720. n := Length(vTGraphicFileExtension);
  721. SetLength(vTGraphicFileExtension, n + 1);
  722. SetLength(vTGraphicClass, n + 1);
  723. vTGraphicFileExtension[n] := LowerCase(extension);
  724. vTGraphicClass[n] := aClass;
  725. end;
  726. function CreateGraphicFromFile(const fileName: string): TGraphic;
  727. var
  728. i: Integer;
  729. ext: string;
  730. fs: TStream;
  731. graphicClass: TGraphicClass;
  732. begin
  733. Result := nil;
  734. if FileStreamExists(fileName) then
  735. begin
  736. graphicClass := nil;
  737. ext := LowerCase(ExtractFileExt(fileName));
  738. for i := 0 to High(vTGraphicFileExtension) do
  739. begin
  740. if vTGraphicFileExtension[i] = ext then
  741. begin
  742. graphicClass := TGraphicClass(vTGraphicClass[i]);
  743. Break;
  744. end;
  745. end;
  746. if graphicClass = nil then
  747. graphicClass := GraphicClassForExtension(ext);
  748. if graphicClass <> nil then
  749. begin
  750. Result := graphicClass.Create;
  751. try
  752. fs := TFileStream.Create(fileName, fmOpenRead);
  753. try
  754. Result.LoadFromStream(fs);
  755. finally
  756. fs.Free;
  757. end;
  758. except
  759. FreeAndNil(Result);
  760. raise;
  761. end;
  762. end;
  763. end;
  764. end;
  765. procedure RegisterGLTextureImageClass(textureImageClass: TGLTextureImageClass);
  766. begin
  767. if not Assigned(vGLTextureImageClasses) then
  768. vGLTextureImageClasses := TList.Create;
  769. vGLTextureImageClasses.Add(textureImageClass);
  770. end;
  771. function FindGLTextureImageClass(const className: string): TGLTextureImageClass;
  772. var
  773. i: Integer;
  774. tic: TGLTextureImageClass;
  775. begin
  776. Result := nil;
  777. if Assigned(vGLTextureImageClasses) then
  778. for i := 0 to vGLTextureImageClasses.Count - 1 do
  779. begin
  780. tic := TGLTextureImageClass(vGLTextureImageClasses[i]);
  781. if tic.ClassName = className then
  782. begin
  783. Result := tic;
  784. Break;
  785. end;
  786. end;
  787. end;
  788. function FindGLTextureImageClassByFriendlyName(const friendlyName: string):
  789. TGLTextureImageClass;
  790. var
  791. i: Integer;
  792. tic: TGLTextureImageClass;
  793. begin
  794. Result := nil;
  795. if Assigned(vGLTextureImageClasses) then
  796. for i := 0 to vGLTextureImageClasses.Count - 1 do
  797. begin
  798. tic := TGLTextureImageClass(vGLTextureImageClasses[i]);
  799. if tic.FriendlyName = friendlyName then
  800. begin
  801. Result := tic;
  802. Break;
  803. end;
  804. end;
  805. end;
  806. procedure SetGLTextureImageClassesToStrings(aStrings: TStrings);
  807. var
  808. i: Integer;
  809. tic: TGLTextureImageClass;
  810. begin
  811. with aStrings do
  812. begin
  813. BeginUpdate;
  814. Clear;
  815. if Assigned(vGLTextureImageClasses) then
  816. for i := 0 to vGLTextureImageClasses.Count - 1 do
  817. begin
  818. tic := TGLTextureImageClass(vGLTextureImageClasses[i]);
  819. AddObject(tic.FriendlyName, TObject(Pointer(tic)));
  820. end;
  821. EndUpdate;
  822. end;
  823. end;
  824. function GetGLTextureImageClassesAsStrings: TStrings;
  825. begin
  826. Result := TStringList.Create;
  827. SetGLTextureImageClassesToStrings(Result);
  828. end;
  829. // ------------------
  830. // ------------------ TGLTextureImage ------------------
  831. // ------------------
  832. constructor TGLTextureImage.Create(AOwner: TPersistent);
  833. begin
  834. inherited;
  835. FOwnerTexture := (AOwner as TGLTexture);
  836. end;
  837. destructor TGLTextureImage.Destroy;
  838. begin
  839. inherited Destroy;
  840. end;
  841. class function TGLTextureImage.FriendlyDescription: string;
  842. begin
  843. Result := FriendlyName;
  844. end;
  845. procedure TGLTextureImage.Invalidate;
  846. begin
  847. ReleaseBitmap32;
  848. NotifyChange(Self);
  849. end;
  850. procedure TGLTextureImage.ReleaseBitmap32;
  851. begin
  852. // nothing here.
  853. end;
  854. // AsBitmap : Returns the TextureImage as a TBitmap
  855. // WARNING: This Creates a new bitmap. Remember to free it, to prevent leaks.
  856. // If possible, rather use AssignToBitmap.
  857. //
  858. function TGLTextureImage.AsBitmap: TBitmap;
  859. begin
  860. result := self.GetBitmap32.Create32BitsBitmap;
  861. end;
  862. procedure TGLTextureImage.AssignToBitmap(aBitmap: TBitmap);
  863. begin
  864. Self.GetBitmap32.AssignToBitmap(aBitmap);
  865. end;
  866. procedure TGLTextureImage.NotifyChange(Sender: TObject);
  867. begin
  868. if Assigned(FOwnerTexture) then
  869. begin
  870. FOwnerTexture.FTextureHandle.NotifyChangesOfData;
  871. FOwnerTexture.FSamplerHandle.NotifyChangesOfData;
  872. // Check for texture target change
  873. GetTextureTarget;
  874. FOwnerTexture.NotifyChange(Self);
  875. end;
  876. end;
  877. procedure TGLTextureImage.LoadFromFile(const fileName: string);
  878. var
  879. buf: string;
  880. begin
  881. if Assigned(FOnTextureNeeded) then
  882. begin
  883. buf := fileName;
  884. FOnTextureNeeded(Self, buf);
  885. end;
  886. end;
  887. function TGLTextureImage.GetResourceName: string;
  888. begin
  889. Result := FResourceFile;
  890. end;
  891. class function TGLTextureImage.IsSelfLoading: Boolean;
  892. begin
  893. Result := False;
  894. end;
  895. procedure TGLTextureImage.LoadTexture(AInternalFormat: TGLInternalFormat);
  896. begin
  897. end;
  898. // ------------------
  899. // ------------------ TGLBlankImage ------------------
  900. // ------------------
  901. constructor TGLBlankImage.Create(AOwner: TPersistent);
  902. begin
  903. inherited;
  904. fWidth := 256;
  905. fHeight := 256;
  906. fDepth := 0;
  907. fColorFormat := GL_RGBA;
  908. end;
  909. destructor TGLBlankImage.Destroy;
  910. begin
  911. ReleaseBitmap32;
  912. inherited Destroy;
  913. end;
  914. procedure TGLBlankImage.Assign(Source: TPersistent);
  915. var
  916. img: TGLBlankImage;
  917. begin
  918. if Assigned(Source) then
  919. begin
  920. if (Source is TGLBlankImage) then
  921. begin
  922. img := Source as TGLBlankImage;
  923. FWidth := img.Width;
  924. FHeight := img.Height;
  925. FDepth := img.Depth;
  926. FCubeMap := img.fCubeMap;
  927. FArray := img.fArray;
  928. fColorFormat := img.ColorFormat;
  929. FResourceFile := img.ResourceName;
  930. Invalidate;
  931. end
  932. else
  933. GetBitmap32.Assign(Source);
  934. NotifyChange(Self);
  935. end
  936. else
  937. inherited;
  938. end;
  939. procedure TGLBlankImage.SetWidth(val: Integer);
  940. begin
  941. if val <> FWidth then
  942. begin
  943. FWidth := val;
  944. if FWidth < 1 then
  945. FWidth := 1;
  946. Invalidate;
  947. end;
  948. end;
  949. function TGLBlankImage.GetWidth: Integer;
  950. begin
  951. Result := FWidth;
  952. end;
  953. procedure TGLBlankImage.SetHeight(val: Integer);
  954. begin
  955. if val <> FHeight then
  956. begin
  957. FHeight := val;
  958. if FHeight < 1 then
  959. FHeight := 1;
  960. Invalidate;
  961. end;
  962. end;
  963. function TGLBlankImage.GetHeight: Integer;
  964. begin
  965. Result := FHeight;
  966. end;
  967. procedure TGLBlankImage.SetDepth(val: Integer);
  968. begin
  969. if val <> FDepth then
  970. begin
  971. FDepth := val;
  972. if FDepth < 0 then
  973. FDepth := 0;
  974. Invalidate;
  975. end;
  976. end;
  977. function TGLBlankImage.GetDepth: Integer;
  978. begin
  979. Result := fDepth;
  980. end;
  981. procedure TGLBlankImage.SetCubeMap(const val: Boolean);
  982. begin
  983. if val <> fCubeMap then
  984. begin
  985. fCubeMap := val;
  986. Invalidate;
  987. end;
  988. end;
  989. procedure TGLBlankImage.SetArray(const val: Boolean);
  990. begin
  991. if val <> fArray then
  992. begin
  993. fArray := val;
  994. Invalidate;
  995. end;
  996. end;
  997. function TGLBlankImage.GetBitmap32: TGLImage;
  998. begin
  999. if not Assigned(FBitmap) then
  1000. begin
  1001. fBitmap := TGLImage.Create;
  1002. fBitmap.Width := FWidth;
  1003. fBitmap.Height := FHeight;
  1004. fBitmap.Depth := FDepth;
  1005. fBitmap.CubeMap := FCubeMap;
  1006. fBitmap.TextureArray := FArray;
  1007. fBitmap.SetColorFormatDataType(FColorFormat, GL_UNSIGNED_BYTE);
  1008. end;
  1009. Result := FBitmap;
  1010. end;
  1011. procedure TGLBlankImage.ReleaseBitmap32;
  1012. begin
  1013. if Assigned(FBitmap) then
  1014. begin
  1015. FBitmap.Free;
  1016. FBitmap := nil;
  1017. end;
  1018. end;
  1019. procedure TGLBlankImage.SaveToFile(const fileName: string);
  1020. begin
  1021. SaveAnsiStringToFile(fileName, AnsiString(
  1022. '[BlankImage]'#13#10'Width=' + IntToStr(Width) +
  1023. #13#10'Height=' + IntToStr(Height) +
  1024. #13#10'Depth=' + IntToStr(Depth)));
  1025. end;
  1026. procedure TGLBlankImage.LoadFromFile(const fileName: string);
  1027. var
  1028. sl: TStringList;
  1029. buf, temp: string;
  1030. begin
  1031. buf := fileName;
  1032. if Assigned(FOnTextureNeeded) then
  1033. FOnTextureNeeded(Self, buf);
  1034. if FileExists(buf) then
  1035. begin
  1036. sl := TStringList.Create;
  1037. try
  1038. sl.LoadFromFile(buf, TEncoding.ASCII);
  1039. FWidth := StrToInt(sl.Values['Width']);
  1040. FHeight := StrToInt(sl.Values['Height']);
  1041. temp := sl.Values['Depth'];
  1042. if Length(temp) > 0 then
  1043. FDepth := StrToInt(temp)
  1044. else
  1045. FDepth := 1;
  1046. finally
  1047. sl.Free;
  1048. end;
  1049. end
  1050. else
  1051. begin
  1052. Assert(False, Format(strFailedOpenFile, [fileName]));
  1053. end;
  1054. end;
  1055. class function TGLBlankImage.FriendlyName: string;
  1056. begin
  1057. Result := 'Blank Image';
  1058. end;
  1059. class function TGLBlankImage.FriendlyDescription: string;
  1060. begin
  1061. Result := 'Blank Image (Width x Height x Depth)';
  1062. end;
  1063. function TGLBlankImage.GetTextureTarget: TGLTextureTarget;
  1064. begin
  1065. Result := ttTexture2D;
  1066. // Choose a texture target
  1067. if Assigned(fBitmap) then
  1068. begin
  1069. FWidth := fBitmap.Width;
  1070. FHeight := fBitmap.Height;
  1071. FDepth := fBitmap.Depth;
  1072. FCubeMap := fBitmap.CubeMap;
  1073. FArray := fBitmap.TextureArray;
  1074. end;
  1075. if FHeight = 1 then
  1076. Result := ttTexture1D;
  1077. if FCubeMap then
  1078. Result := ttTextureCube;
  1079. if FDepth > 0 then
  1080. Result := ttTexture3D;
  1081. if FArray then
  1082. begin
  1083. if FDepth < 2 then
  1084. Result := ttTexture1DArray
  1085. else
  1086. Result := ttTexture2DArray;
  1087. if FCubeMap then
  1088. Result := ttTextureCubeArray;
  1089. end;
  1090. if Assigned(FOwnerTexture) then
  1091. begin
  1092. if ((FOwnerTexture.FTextureFormat >= tfFLOAT_R16)
  1093. and (FOwnerTexture.FTextureFormat <= tfFLOAT_RGBA32)) then
  1094. Result := ttTextureRect;
  1095. end;
  1096. end;
  1097. // ------------------
  1098. // ------------------ TGLPictureImage ------------------
  1099. // ------------------
  1100. constructor TGLPictureImage.Create(AOwner: TPersistent);
  1101. begin
  1102. inherited;
  1103. end;
  1104. destructor TGLPictureImage.Destroy;
  1105. begin
  1106. ReleaseBitmap32;
  1107. FGLPicture.Free;
  1108. inherited Destroy;
  1109. end;
  1110. procedure TGLPictureImage.Assign(Source: TPersistent);
  1111. var
  1112. bmp: TBitmap;
  1113. begin
  1114. if Assigned(Source) then
  1115. begin
  1116. if (Source is TGLPersistentImage) then
  1117. Picture.Assign(TGLPersistentImage(Source).Picture)
  1118. else if (Source is TGraphic) then
  1119. Picture.Assign(Source)
  1120. else if (Source is TPicture) then
  1121. Picture.Assign(Source)
  1122. else if (Source is TGLImage) then
  1123. begin
  1124. bmp := TGLImage(Source).Create32BitsBitmap;
  1125. Picture.Graphic := bmp;
  1126. bmp.Free;
  1127. FResourceFile := TGLImage(Source).ResourceName;
  1128. end
  1129. else
  1130. inherited;
  1131. end
  1132. else
  1133. inherited;
  1134. end;
  1135. procedure TGLPictureImage.BeginUpdate;
  1136. begin
  1137. Inc(FUpdateCounter);
  1138. Picture.OnChange := nil;
  1139. end;
  1140. procedure TGLPictureImage.EndUpdate;
  1141. begin
  1142. Assert(FUpdateCounter > 0, ClassName + ': Unbalanced Begin/EndUpdate');
  1143. Dec(FUpdateCounter);
  1144. Picture.OnChange := PictureChanged;
  1145. if FUpdateCounter = 0 then
  1146. PictureChanged(Picture);
  1147. end;
  1148. function TGLPictureImage.GetHeight: Integer;
  1149. begin
  1150. Result := Picture.Height;
  1151. end;
  1152. function TGLPictureImage.GetWidth: Integer;
  1153. begin
  1154. Result := Picture.Width;
  1155. end;
  1156. function TGLPictureImage.GetDepth: Integer;
  1157. begin
  1158. Result := 0;
  1159. end;
  1160. function TGLPictureImage.GetBitmap32: TGLImage;
  1161. begin
  1162. if not Assigned(FBitmap) then
  1163. begin
  1164. FBitmap := TGLImage.Create;
  1165. // we need to deactivate OnChange, due to a "glitch" in some TGraphics,
  1166. // for instance, TJPegImage triggers an OnChange when it is drawn...
  1167. if Assigned(Picture.Graphic) then
  1168. begin
  1169. if Assigned(Picture.OnChange) then
  1170. begin
  1171. Picture.OnChange := nil;
  1172. try
  1173. FBitmap.Assign(Picture.Graphic);
  1174. finally
  1175. Picture.OnChange := PictureChanged;
  1176. end;
  1177. end
  1178. else
  1179. FBitmap.Assign(Picture.Graphic);
  1180. end
  1181. else
  1182. FBitmap.SetErrorImage;
  1183. end;
  1184. Result := FBitmap;
  1185. end;
  1186. procedure TGLPictureImage.ReleaseBitmap32;
  1187. begin
  1188. if Assigned(FBitmap) then
  1189. begin
  1190. FBitmap.Free;
  1191. FBitmap := nil;
  1192. end;
  1193. end;
  1194. procedure TGLPictureImage.PictureChanged(Sender: TObject);
  1195. begin
  1196. Invalidate;
  1197. end;
  1198. function TGLPictureImage.GetPicture: TPicture;
  1199. begin
  1200. if not Assigned(FGLPicture) then
  1201. begin
  1202. FGLPicture := TPicture.Create;
  1203. FGLPicture.OnChange := PictureChanged;
  1204. end;
  1205. Result := FGLPicture;
  1206. end;
  1207. procedure TGLPictureImage.SetPicture(const aPicture: TPicture);
  1208. begin
  1209. Picture.Assign(aPicture);
  1210. end;
  1211. function TGLPictureImage.GetTextureTarget: TGLTextureTarget;
  1212. begin
  1213. Result := ttTexture2D;
  1214. end;
  1215. // ------------------
  1216. // ------------------ TGLPersistentImage ------------------
  1217. // ------------------
  1218. constructor TGLPersistentImage.Create(AOwner: TPersistent);
  1219. begin
  1220. inherited;
  1221. end;
  1222. destructor TGLPersistentImage.Destroy;
  1223. begin
  1224. inherited Destroy;
  1225. end;
  1226. procedure TGLPersistentImage.SaveToFile(const fileName: string);
  1227. begin
  1228. Picture.SaveToFile(fileName);
  1229. FResourceFile := fileName;
  1230. end;
  1231. procedure TGLPersistentImage.LoadFromFile(const fileName: string);
  1232. var
  1233. buf: string;
  1234. gr: TGraphic;
  1235. begin
  1236. buf := fileName;
  1237. FResourceFile := fileName;
  1238. if Assigned(FOnTextureNeeded) then
  1239. FOnTextureNeeded(Self, buf);
  1240. if ApplicationFileIODefined then
  1241. begin
  1242. gr := CreateGraphicFromFile(buf);
  1243. if Assigned(gr) then
  1244. begin
  1245. Picture.Graphic := gr;
  1246. gr.Free;
  1247. Exit;
  1248. end;
  1249. end
  1250. else if FileExists(buf) then
  1251. begin
  1252. Picture.LoadFromFile(buf);
  1253. Exit;
  1254. end;
  1255. Picture.Graphic := nil;
  1256. raise ETexture.CreateFmt(strFailedOpenFile, [fileName]);
  1257. end;
  1258. class function TGLPersistentImage.FriendlyName: string;
  1259. begin
  1260. Result := 'Persistent Image';
  1261. end;
  1262. class function TGLPersistentImage.FriendlyDescription: string;
  1263. begin
  1264. Result := 'Image data is stored in its original format with other form resources,'
  1265. + 'ie. in the DFM at design-time, and embedded in the EXE at run-time.';
  1266. end;
  1267. // ------------------
  1268. // ------------------ TGLPicFileImage ------------------
  1269. // ------------------
  1270. constructor TGLPicFileImage.Create(AOwner: TPersistent);
  1271. begin
  1272. inherited;
  1273. end;
  1274. destructor TGLPicFileImage.Destroy;
  1275. begin
  1276. inherited;
  1277. end;
  1278. procedure TGLPicFileImage.Assign(Source: TPersistent);
  1279. begin
  1280. if Source is TGLPicFileImage then
  1281. begin
  1282. FPictureFileName := TGLPicFileImage(Source).FPictureFileName;
  1283. FResourceFile := TGLPicFileImage(Source).ResourceName;
  1284. end
  1285. else
  1286. inherited;
  1287. end;
  1288. procedure TGLPicFileImage.SetPictureFileName(const val: string);
  1289. begin
  1290. if val <> FPictureFileName then
  1291. begin
  1292. FPictureFileName := val;
  1293. FResourceFile := val;
  1294. FAlreadyWarnedAboutMissingFile := False;
  1295. Invalidate;
  1296. end;
  1297. end;
  1298. procedure TGLPicFileImage.Invalidate;
  1299. begin
  1300. Picture.OnChange := nil;
  1301. try
  1302. Picture.Assign(nil);
  1303. FBitmap := nil;
  1304. finally
  1305. Picture.OnChange := PictureChanged;
  1306. end;
  1307. inherited;
  1308. end;
  1309. function TGLPicFileImage.GetHeight: Integer;
  1310. begin
  1311. Result := FHeight;
  1312. end;
  1313. function TGLPicFileImage.GetWidth: Integer;
  1314. begin
  1315. Result := FWidth;
  1316. end;
  1317. function TGLPicFileImage.GetDepth: Integer;
  1318. begin
  1319. Result := 0;
  1320. end;
  1321. function TGLPicFileImage.GetBitmap32: TGLImage;
  1322. var
  1323. buf: string;
  1324. gr: TGraphic;
  1325. begin
  1326. if (GetWidth <= 0) and (PictureFileName <> '') then
  1327. begin
  1328. Picture.OnChange := nil;
  1329. try
  1330. buf := PictureFileName;
  1331. SetExeDirectory;
  1332. if Assigned(FOnTextureNeeded) then
  1333. FOnTextureNeeded(Self, buf);
  1334. if FileStreamExists(buf) then
  1335. begin
  1336. gr := CreateGraphicFromFile(buf);
  1337. Picture.Graphic := gr;
  1338. gr.Free;
  1339. end
  1340. else
  1341. begin
  1342. Picture.Graphic := nil;
  1343. if not FAlreadyWarnedAboutMissingFile then
  1344. begin
  1345. FAlreadyWarnedAboutMissingFile := True;
  1346. GLOKMessageBox(Format(strFailedOpenFileFromCurrentDir, [PictureFileName, GetCurrentDir]),strError);
  1347. end;
  1348. end;
  1349. Result := inherited GetBitmap32;
  1350. FWidth := Result.Width;
  1351. FHeight := Result.Height;
  1352. Picture.Graphic := nil;
  1353. finally
  1354. Picture.OnChange := PictureChanged;
  1355. end;
  1356. end
  1357. else
  1358. Result := inherited GetBitmap32;
  1359. end;
  1360. procedure TGLPicFileImage.SaveToFile(const fileName: string);
  1361. begin
  1362. FResourceFile := fileName;
  1363. SaveAnsiStringToFile(fileName, AnsiString(PictureFileName));
  1364. end;
  1365. procedure TGLPicFileImage.LoadFromFile(const fileName: string);
  1366. var
  1367. buf: string;
  1368. begin
  1369. inherited;
  1370. // attempt to autodetect if we are pointed to a file containing
  1371. // a filename or directly to an image
  1372. if SizeOfFile(fileName) < 512 then
  1373. begin
  1374. buf := string(LoadAnsiStringFromFile(fileName));
  1375. if Pos(#0, buf) > 0 then
  1376. PictureFileName := fileName
  1377. else
  1378. PictureFileName := buf;
  1379. end
  1380. else
  1381. PictureFileName := fileName;
  1382. FResourceFile := FPictureFileName;
  1383. end;
  1384. class function TGLPicFileImage.FriendlyName: string;
  1385. begin
  1386. Result := 'PicFile Image';
  1387. end;
  1388. class function TGLPicFileImage.FriendlyDescription: string;
  1389. begin
  1390. Result := 'Image data is retrieved from a file.';
  1391. end;
  1392. // ------------------
  1393. // ------------------ TGLCubeMapImage ------------------
  1394. // ------------------
  1395. constructor TGLCubeMapImage.Create(AOwner: TPersistent);
  1396. var
  1397. i: TGLCubeMapTarget;
  1398. begin
  1399. inherited;
  1400. for i := Low(FPicture) to High(FPicture) do
  1401. begin
  1402. FPicture[i] := TPicture.Create;
  1403. FPicture[i].OnChange := PictureChanged;
  1404. end;
  1405. end;
  1406. destructor TGLCubeMapImage.Destroy;
  1407. var
  1408. i: TGLCubeMapTarget;
  1409. begin
  1410. ReleaseBitmap32;
  1411. for i := Low(FPicture) to High(FPicture) do
  1412. FPicture[i].Free;
  1413. inherited Destroy;
  1414. end;
  1415. procedure TGLCubeMapImage.Assign(Source: TPersistent);
  1416. var
  1417. i: TGLCubeMapTarget;
  1418. begin
  1419. if Assigned(Source) then
  1420. begin
  1421. if (Source is TGLCubeMapImage) then
  1422. begin
  1423. for i := Low(FPicture) to High(FPicture) do
  1424. FPicture[i].Assign(TGLCubeMapImage(Source).FPicture[i]);
  1425. Invalidate;
  1426. end
  1427. else
  1428. inherited;
  1429. end
  1430. else
  1431. inherited;
  1432. end;
  1433. function TGLCubeMapImage.GetWidth: Integer;
  1434. begin
  1435. Result := FPicture[cmtPX].Width;
  1436. end;
  1437. function TGLCubeMapImage.GetHeight: Integer;
  1438. begin
  1439. Result := FPicture[cmtPX].Height;
  1440. end;
  1441. function TGLCubeMapImage.GetDepth: Integer;
  1442. begin
  1443. Result := 0;
  1444. end;
  1445. function TGLCubeMapImage.GetBitmap32: TGLImage;
  1446. var
  1447. I: Integer;
  1448. LImage: TGLImage;
  1449. begin
  1450. if Assigned(FImage) then
  1451. FImage.Free;
  1452. LImage := TGLImage.Create;
  1453. LImage.VerticalReverseOnAssignFromBitmap := True;
  1454. try
  1455. for I := 0 to 5 do
  1456. begin
  1457. FPicture[TGLCubeMapTarget(I)].OnChange := nil;
  1458. try
  1459. LImage.Assign(FPicture[TGLCubeMapTarget(I)].Graphic);
  1460. if not Assigned(FImage) then
  1461. begin
  1462. FImage := TGLImage.Create;
  1463. FImage.Blank := True;
  1464. FImage.Width := LImage.Width;
  1465. FImage.Height := LImage.Height;
  1466. FImage.SetColorFormatDataType(LImage.ColorFormat, LImage.DataType);
  1467. FImage.CubeMap := True;
  1468. FImage.Blank := False;
  1469. end;
  1470. Move(LImage.Data^, TFriendlyImage(FImage).GetLevelAddress(0, I)^, LImage.LevelSizeInByte[0]);
  1471. finally
  1472. FPicture[TGLCubeMapTarget(I)].OnChange := PictureChanged;
  1473. end;
  1474. end;
  1475. finally
  1476. LImage.Destroy;
  1477. end;
  1478. Result := FImage;
  1479. end;
  1480. procedure TGLCubeMapImage.ReleaseBitmap32;
  1481. begin
  1482. if Assigned(FImage) then
  1483. begin
  1484. FImage.Free;
  1485. FImage := nil;
  1486. end;
  1487. end;
  1488. procedure TGLCubeMapImage.BeginUpdate;
  1489. var
  1490. i: TGLCubeMapTarget;
  1491. begin
  1492. Inc(FUpdateCounter);
  1493. for i := Low(FPicture) to High(FPicture) do
  1494. FPicture[i].OnChange := nil;
  1495. end;
  1496. procedure TGLCubeMapImage.EndUpdate;
  1497. var
  1498. i: TGLCubeMapTarget;
  1499. begin
  1500. Assert(FUpdateCounter > 0, ClassName + ': Unbalanced Begin/EndUpdate');
  1501. Dec(FUpdateCounter);
  1502. for i := Low(FPicture) to High(FPicture) do
  1503. FPicture[i].OnChange := PictureChanged;
  1504. if FUpdateCounter = 0 then
  1505. PictureChanged(FPicture[cmtPX]);
  1506. end;
  1507. procedure TGLCubeMapImage.SaveToFile(const fileName: string);
  1508. var
  1509. fs: TFileStream;
  1510. bmp: TBitmap;
  1511. i: TGLCubeMapTarget;
  1512. version: Word;
  1513. begin
  1514. fs := TFileStream.Create(fileName, fmCreate);
  1515. bmp := TBitmap.Create;
  1516. try
  1517. version := $0100;
  1518. fs.Write(version, 2);
  1519. for i := Low(FPicture) to High(FPicture) do
  1520. begin
  1521. bmp.Assign(FPicture[i].Graphic);
  1522. bmp.SaveToStream(fs);
  1523. end;
  1524. finally
  1525. bmp.Free;
  1526. fs.Free;
  1527. end;
  1528. end;
  1529. procedure TGLCubeMapImage.LoadFromFile(const fileName: string);
  1530. var
  1531. fs: TFileStream;
  1532. bmp: TBitmap;
  1533. i: TGLCubeMapTarget;
  1534. version: Word;
  1535. begin
  1536. fs := TFileStream.Create(fileName, fmOpenRead + fmShareDenyWrite);
  1537. bmp := TBitmap.Create;
  1538. try
  1539. fs.Read(version, 2);
  1540. Assert(version = $0100);
  1541. for i := Low(FPicture) to High(FPicture) do
  1542. begin
  1543. bmp.LoadFromStream(fs);
  1544. FPicture[i].Graphic := bmp;
  1545. end;
  1546. finally
  1547. bmp.Free;
  1548. fs.Free;
  1549. end;
  1550. end;
  1551. class function TGLCubeMapImage.FriendlyName: string;
  1552. begin
  1553. Result := 'CubeMap Image';
  1554. end;
  1555. class function TGLCubeMapImage.FriendlyDescription: string;
  1556. begin
  1557. Result := 'Image data is contain 6 pictures of cubemap faces.';
  1558. end;
  1559. procedure TGLCubeMapImage.PictureChanged(Sender: TObject);
  1560. begin
  1561. Invalidate;
  1562. end;
  1563. function TGLCubeMapImage.GetTextureTarget: TGLTextureTarget;
  1564. begin
  1565. Result := ttTextureCube;
  1566. end;
  1567. procedure TGLCubeMapImage.SetPicture(index: TGLCubeMapTarget; const val: TPicture);
  1568. begin
  1569. FPicture[index].Assign(val);
  1570. end;
  1571. function TGLCubeMapImage.GetPicture(index: TGLCubeMapTarget): TPicture;
  1572. begin
  1573. Result := FPicture[index];
  1574. end;
  1575. // ------------------
  1576. // ------------------ TGLTexture ------------------
  1577. // ------------------
  1578. constructor TGLTexture.Create(AOwner: TPersistent);
  1579. begin
  1580. inherited;
  1581. FDisabled := True;
  1582. FImage := TGLPersistentImage.Create(Self);
  1583. FImage.OnTextureNeeded := DoOnTextureNeeded;
  1584. FImageAlpha := tiaDefault;
  1585. FImageBrightness := 1.0;
  1586. FImageGamma := 1.0;
  1587. FMagFilter := maLinear;
  1588. FMinFilter := miLinearMipMapLinear;
  1589. FFilteringQuality := tfIsotropic;
  1590. FRequiredMemorySize := -1;
  1591. FTextureHandle := TGLTextureHandle.Create;
  1592. FSamplerHandle := TGLVirtualHandle.Create;
  1593. FSamplerHandle.OnAllocate := OnSamplerAllocate;
  1594. FSamplerHandle.OnDestroy := OnSamplerDestroy;
  1595. FMappingMode := tmmUser;
  1596. FEnvColor := TGLColor.CreateInitialized(Self, clrTransparent);
  1597. FBorderColor := TGLColor.CreateInitialized(Self, clrTransparent);
  1598. FNormalMapScale := cDefaultNormalMapScale;
  1599. FTextureCompareMode := tcmNone;
  1600. FTextureCompareFunc := cfLequal;
  1601. FDepthTextureMode := dtmLuminance;
  1602. TextureFormat := tfDefault;
  1603. FCompression := tcDefault;
  1604. FKeepImageAfterTransfer := False;
  1605. end;
  1606. destructor TGLTexture.Destroy;
  1607. begin
  1608. FEnvColor.Free;
  1609. FBorderColor.Free;
  1610. FMapSCoordinates.Free;
  1611. FMapTCoordinates.Free;
  1612. FMapRCoordinates.Free;
  1613. FMapQCoordinates.Free;
  1614. DestroyHandles;
  1615. FTextureHandle.Free;
  1616. FSamplerHandle.Free;
  1617. FImage.Free;
  1618. inherited Destroy;
  1619. end;
  1620. procedure TGLTexture.Assign(Source: TPersistent);
  1621. begin
  1622. if Assigned(Source) then
  1623. begin
  1624. if (Source is TGLTexture) then
  1625. begin
  1626. if Source <> Self then
  1627. begin
  1628. FImageAlpha := TGLTexture(Source).FImageAlpha;
  1629. FTextureMode := TGLTexture(Source).FTextureMode;
  1630. FTextureWrap := TGLTexture(Source).FTextureWrap;
  1631. FTextureFormat := TGLTexture(Source).FTextureFormat;
  1632. FCompression := TGLTexture(Source).FCompression;
  1633. FMinFilter := TGLTexture(Source).FMinFilter;
  1634. FMagFilter := TGLTexture(Source).FMagFilter;
  1635. FMappingMode := TGLTexture(Source).FMappingMode;
  1636. MappingSCoordinates.Assign(TGLTexture(Source).MappingSCoordinates);
  1637. MappingTCoordinates.Assign(TGLTexture(Source).MappingTCoordinates);
  1638. MappingRCoordinates.Assign(TGLTexture(Source).MappingRCoordinates);
  1639. MappingQCoordinates.Assign(TGLTexture(Source).MappingQCoordinates);
  1640. FDisabled := TGLTexture(Source).FDisabled;
  1641. SetImage(TGLTexture(Source).FImage);
  1642. FImageBrightness := TGLTexture(Source).FImageBrightness;
  1643. FImageGamma := TGLTexture(Source).FImageGamma;
  1644. FFilteringQuality := TGLTexture(Source).FFilteringQuality;
  1645. FEnvColor.Assign(TGLTexture(Source).FEnvColor);
  1646. FBorderColor.Assign(TGLTexture(Source).FBorderColor);
  1647. FNormalMapScale := TGLTexture(Source).FNormalMapScale;
  1648. // Probably don't need to assign these....
  1649. // FOnTextureNeeded := TGLTexture(Source).FImageGamma;
  1650. // FRequiredMemorySize : Integer;
  1651. // FTexWidth, FTexHeight : Integer;
  1652. FTextureHandle.NotifyChangesOfData;
  1653. FSamplerHandle.NotifyChangesOfData;
  1654. end;
  1655. end
  1656. else if (Source is TGraphic) then
  1657. Image.Assign(Source)
  1658. else if (Source is TPicture) then
  1659. Image.Assign(TPicture(Source).Graphic)
  1660. else
  1661. inherited Assign(Source);
  1662. end
  1663. else
  1664. begin
  1665. FDisabled := True;
  1666. SetImage(nil);
  1667. FTextureHandle.NotifyChangesOfData;
  1668. FSamplerHandle.NotifyChangesOfData;
  1669. end;
  1670. end;
  1671. procedure TGLTexture.NotifyChange(Sender: TObject);
  1672. begin
  1673. if Assigned(Owner) then
  1674. begin
  1675. if Owner is TGLTextureExItem then
  1676. TGLTextureExItem(Owner).NotifyChange(Self);
  1677. end;
  1678. if Sender is TGLTextureImage then
  1679. FTextureHandle.NotifyChangesOfData;
  1680. inherited;
  1681. end;
  1682. procedure TGLTexture.NotifyImageChange;
  1683. begin
  1684. FTextureHandle.NotifyChangesOfData;
  1685. NotifyChange(Self);
  1686. end;
  1687. procedure TGLTexture.NotifyParamsChange;
  1688. begin
  1689. FSamplerHandle.NotifyChangesOfData;
  1690. NotifyChange(Self);
  1691. end;
  1692. procedure TGLTexture.SetImage(AValue: TGLTextureImage);
  1693. begin
  1694. if Assigned(aValue) then
  1695. begin
  1696. if FImage.ClassType <> AValue.ClassType then
  1697. begin
  1698. FImage.Free;
  1699. FImage := TGLTextureImageClass(AValue.ClassType).Create(Self);
  1700. FImage.OnTextureNeeded := DoOnTextureNeeded;
  1701. end;
  1702. FImage.Assign(AValue);
  1703. end
  1704. else
  1705. begin
  1706. FImage.Free;
  1707. FImage := TGLPersistentImage.Create(Self);
  1708. FImage.OnTextureNeeded := DoOnTextureNeeded;
  1709. end;
  1710. end;
  1711. procedure TGLTexture.SetImageClassName(const val: string);
  1712. var
  1713. newImage: TGLTextureImage;
  1714. newImageClass: TGLTextureImageClass;
  1715. begin
  1716. if val <> '' then
  1717. if FImage.ClassName <> val then
  1718. begin
  1719. newImageClass := FindGLTextureImageClass(val);
  1720. Assert(newImageClass <> nil, 'Make sure you include the unit for ' + val +
  1721. ' in your uses clause');
  1722. if newImageClass = nil then
  1723. exit;
  1724. newImage := newImageClass.Create(Self);
  1725. newImage.OnTextureNeeded := DoOnTextureNeeded;
  1726. FImage.Free;
  1727. FImage := newImage;
  1728. end;
  1729. end;
  1730. function TGLTexture.GetImageClassName: string;
  1731. begin
  1732. Result := FImage.ClassName;
  1733. end;
  1734. function TGLTexture.TextureImageRequiredMemory: Integer;
  1735. var
  1736. w, h, e, levelSize: Integer;
  1737. begin
  1738. if FRequiredMemorySize < 0 then
  1739. begin
  1740. if IsCompressedFormat(fTextureFormat) then
  1741. begin
  1742. w := (Image.Width + 3) div 4;
  1743. h := (Image.Height + 3) div 4;
  1744. end
  1745. else
  1746. begin
  1747. w := Image.Width;
  1748. h := Image.Height;
  1749. end;
  1750. e := GetTextureElementSize(fTextureFormat);
  1751. FRequiredMemorySize := w * h * e;
  1752. if Image.Depth > 0 then
  1753. FRequiredMemorySize := FRequiredMemorySize * Image.Depth;
  1754. if not (MinFilter in [miNearest, miLinear]) then
  1755. begin
  1756. levelSize := FRequiredMemorySize;
  1757. while e < levelSize do
  1758. begin
  1759. levelSize := levelSize div 4;
  1760. FRequiredMemorySize := FRequiredMemorySize + levelSize;
  1761. end;
  1762. end;
  1763. if Image.NativeTextureTarget = ttTextureCube then
  1764. FRequiredMemorySize := FRequiredMemorySize * 6;
  1765. end;
  1766. Result := FRequiredMemorySize;
  1767. end;
  1768. procedure TGLTexture.SetImageAlpha(const val: TGLTextureImageAlpha);
  1769. begin
  1770. if FImageAlpha <> val then
  1771. begin
  1772. FImageAlpha := val;
  1773. NotifyImageChange;
  1774. end;
  1775. end;
  1776. procedure TGLTexture.SetImageBrightness(const val: Single);
  1777. begin
  1778. if FImageBrightness <> val then
  1779. begin
  1780. FImageBrightness := val;
  1781. NotifyImageChange;
  1782. end;
  1783. end;
  1784. function TGLTexture.StoreBrightness: Boolean;
  1785. begin
  1786. Result := (FImageBrightness <> 1.0);
  1787. end;
  1788. procedure TGLTexture.SetImageGamma(const val: Single);
  1789. begin
  1790. if FImageGamma <> val then
  1791. begin
  1792. FImageGamma := val;
  1793. NotifyImageChange;
  1794. end;
  1795. end;
  1796. function TGLTexture.StoreGamma: Boolean;
  1797. begin
  1798. Result := (FImageGamma <> 1.0);
  1799. end;
  1800. procedure TGLTexture.SetMagFilter(AValue: TGLMagFilter);
  1801. begin
  1802. if AValue <> FMagFilter then
  1803. begin
  1804. FMagFilter := AValue;
  1805. NotifyParamsChange;
  1806. end;
  1807. end;
  1808. procedure TGLTexture.SetMinFilter(AValue: TGLMinFilter);
  1809. begin
  1810. if AValue <> FMinFilter then
  1811. begin
  1812. FMinFilter := AValue;
  1813. NotifyParamsChange;
  1814. end;
  1815. end;
  1816. procedure TGLTexture.SetTextureMode(AValue: TGLTextureMode);
  1817. begin
  1818. if AValue <> FTextureMode then
  1819. begin
  1820. FTextureMode := AValue;
  1821. NotifyParamsChange;
  1822. end;
  1823. end;
  1824. procedure TGLTexture.SetDisabled(AValue: Boolean);
  1825. var
  1826. intf: IGLTextureNotifyAble;
  1827. begin
  1828. if AValue <> FDisabled then
  1829. begin
  1830. FDisabled := AValue;
  1831. if Supports(Owner, IGLTextureNotifyAble, intf) then
  1832. intf.NotifyTexMapChange(Self)
  1833. else
  1834. NotifyChange(Self);
  1835. end;
  1836. end;
  1837. procedure TGLTexture.SetEnabled(const val: Boolean);
  1838. begin
  1839. Disabled := not val;
  1840. end;
  1841. function TGLTexture.GetEnabled: Boolean;
  1842. begin
  1843. Result := not Disabled;
  1844. end;
  1845. procedure TGLTexture.SetEnvColor(const val: TGLColor);
  1846. begin
  1847. FEnvColor.Assign(val);
  1848. NotifyParamsChange;
  1849. end;
  1850. procedure TGLTexture.SetBorderColor(const val: TGLColor);
  1851. begin
  1852. FBorderColor.Assign(val);
  1853. NotifyParamsChange;
  1854. end;
  1855. procedure TGLTexture.SetNormalMapScale(const val: Single);
  1856. begin
  1857. if val <> FNormalMapScale then
  1858. begin
  1859. FNormalMapScale := val;
  1860. if TextureFormat = tfNormalMap then
  1861. NotifyImageChange;
  1862. end;
  1863. end;
  1864. function TGLTexture.StoreNormalMapScale: Boolean;
  1865. begin
  1866. Result := (FNormalMapScale <> cDefaultNormalMapScale);
  1867. end;
  1868. procedure TGLTexture.SetTextureWrap(AValue: TGLTextureWrap);
  1869. begin
  1870. if AValue <> FTextureWrap then
  1871. begin
  1872. FTextureWrap := AValue;
  1873. NotifyParamsChange;
  1874. end;
  1875. end;
  1876. procedure TGLTexture.SetTextureWrapS(AValue: TGLSeparateTextureWrap);
  1877. begin
  1878. if AValue <> FTextureWrapS then
  1879. begin
  1880. FTextureWrapS := AValue;
  1881. NotifyParamsChange;
  1882. end;
  1883. end;
  1884. procedure TGLTexture.SetTextureWrapT(AValue: TGLSeparateTextureWrap);
  1885. begin
  1886. if AValue <> FTextureWrapT then
  1887. begin
  1888. FTextureWrapT := AValue;
  1889. NotifyParamsChange;
  1890. end;
  1891. end;
  1892. procedure TGLTexture.SetTextureWrapR(AValue: TGLSeparateTextureWrap);
  1893. begin
  1894. if AValue <> FTextureWrapR then
  1895. begin
  1896. FTextureWrapR := AValue;
  1897. NotifyParamsChange;
  1898. end;
  1899. end;
  1900. function TGLTexture.GetTextureFormat: TGLTextureFormat;
  1901. var
  1902. i: TGLTextureFormat;
  1903. begin
  1904. if vDefaultTextureFormat = FTextureFormat then
  1905. begin
  1906. Result := tfDefault;
  1907. Exit;
  1908. end;
  1909. for i := tfRGB to tfRGBAFloat32 do
  1910. begin
  1911. if cOldTextureFormatToInternalFormat[i] = FTextureFormat then
  1912. begin
  1913. Result := i;
  1914. Exit;
  1915. end;
  1916. end;
  1917. Result := tfExtended;
  1918. end;
  1919. procedure TGLTexture.SetTextureFormat(const val: TGLTextureFormat);
  1920. begin
  1921. if val = tfDefault then
  1922. begin
  1923. FTextureFormat := vDefaultTextureFormat;
  1924. end
  1925. else if val < tfExtended then
  1926. begin
  1927. FTextureFormat := cOldTextureFormatToInternalFormat[val];
  1928. end;
  1929. end;
  1930. procedure TGLTexture.SetTextureFormatEx(const val: TGLInternalFormat);
  1931. begin
  1932. if val <> FTextureFormat then
  1933. begin
  1934. FTextureFormat := val;
  1935. NotifyImageChange;
  1936. end;
  1937. end;
  1938. function TGLTexture.StoreTextureFormatEx: Boolean;
  1939. begin
  1940. Result := GetTextureFormat >= tfExtended;
  1941. end;
  1942. procedure TGLTexture.SetCompression(const val: TGLTextureCompression);
  1943. begin
  1944. if val <> FCompression then
  1945. begin
  1946. FCompression := val;
  1947. NotifyParamsChange;
  1948. end;
  1949. end;
  1950. procedure TGLTexture.SetFilteringQuality(const val: TGLTextureFilteringQuality);
  1951. begin
  1952. if val <> FFilteringQuality then
  1953. begin
  1954. FFilteringQuality := val;
  1955. NotifyParamsChange;
  1956. end;
  1957. end;
  1958. procedure TGLTexture.SetMappingMode(const val: TGLTextureMappingMode);
  1959. var
  1960. texMapChange: Boolean;
  1961. intf: IGLTextureNotifyAble;
  1962. begin
  1963. if val <> FMappingMode then
  1964. begin
  1965. texMapChange := ((val = tmmUser) and (FMappingMode <> tmmUser))
  1966. or ((val = tmmUser) and (FMappingMode <> tmmUser));
  1967. FMappingMode := val;
  1968. if texMapChange then
  1969. begin
  1970. // when switching between texGen modes and user mode, the geometry
  1971. // must be rebuilt in whole (to specify/remove texCoord data!)
  1972. if Supports(Owner, IGLTextureNotifyAble, intf) then
  1973. intf.NotifyTexMapChange(Self);
  1974. end
  1975. else
  1976. NotifyChange(Self);
  1977. end;
  1978. end;
  1979. procedure TGLTexture.SetMappingSCoordinates(const val: TGCoordinates4);
  1980. begin
  1981. MappingSCoordinates.Assign(val);
  1982. end;
  1983. function TGLTexture.GetMappingSCoordinates: TGCoordinates4;
  1984. begin
  1985. if not Assigned(FMapSCoordinates) then
  1986. FMapSCoordinates := TGCoordinates4.CreateInitialized(Self, XHmgVector, csVector);
  1987. Result := FMapSCoordinates;
  1988. end;
  1989. function TGLTexture.StoreMappingSCoordinates: Boolean;
  1990. begin
  1991. if Assigned(FMapSCoordinates) then
  1992. Result := not VectorEquals(FMapSCoordinates.AsVector, XHmgVector)
  1993. else
  1994. Result := false;
  1995. end;
  1996. procedure TGLTexture.SetMappingTCoordinates(const val: TGCoordinates4);
  1997. begin
  1998. MappingTCoordinates.Assign(val);
  1999. end;
  2000. function TGLTexture.GetMappingTCoordinates: TGCoordinates4;
  2001. begin
  2002. if not Assigned(FMapTCoordinates) then
  2003. FMapTCoordinates := TGCoordinates4.CreateInitialized(Self, YHmgVector,
  2004. csVector);
  2005. Result := FMapTCoordinates;
  2006. end;
  2007. function TGLTexture.StoreMappingTCoordinates: Boolean;
  2008. begin
  2009. if Assigned(FMapTCoordinates) then
  2010. Result := not VectorEquals(FMapTCoordinates.AsVector, YHmgVector)
  2011. else
  2012. Result := false;
  2013. end;
  2014. procedure TGLTexture.SetMappingRCoordinates(const val: TGCoordinates4);
  2015. begin
  2016. MappingRCoordinates.Assign(val);
  2017. end;
  2018. function TGLTexture.GetMappingRCoordinates: TGCoordinates4;
  2019. begin
  2020. if not Assigned(FMapRCoordinates) then
  2021. FMapRCoordinates := TGCoordinates4.CreateInitialized(Self, ZHmgVector,
  2022. csVector);
  2023. Result := FMapRCoordinates;
  2024. end;
  2025. function TGLTexture.StoreMappingRCoordinates: Boolean;
  2026. begin
  2027. if Assigned(FMapRCoordinates) then
  2028. Result := not VectorEquals(FMapRCoordinates.AsVector, ZHmgVector)
  2029. else
  2030. Result := false;
  2031. end;
  2032. procedure TGLTexture.SetMappingQCoordinates(const val: TGCoordinates4);
  2033. begin
  2034. MappingQCoordinates.Assign(val);
  2035. end;
  2036. function TGLTexture.GetMappingQCoordinates: TGCoordinates4;
  2037. begin
  2038. if not Assigned(FMapQCoordinates) then
  2039. FMapQCoordinates := TGCoordinates4.CreateInitialized(Self, WHmgVector,
  2040. csVector);
  2041. Result := FMapQCoordinates;
  2042. end;
  2043. function TGLTexture.StoreMappingQCoordinates: Boolean;
  2044. begin
  2045. if Assigned(FMapQCoordinates) then
  2046. Result := not VectorEquals(FMapQCoordinates.AsVector, WHmgVector)
  2047. else
  2048. Result := false;
  2049. end;
  2050. function TGLTexture.StoreImageClassName: Boolean;
  2051. begin
  2052. Result := (FImage.ClassName <> TGLPersistentImage.ClassName);
  2053. end;
  2054. procedure TGLTexture.SetTextureCompareMode(const val: TGLTextureCompareMode);
  2055. begin
  2056. if val <> fTextureCompareMode then
  2057. begin
  2058. fTextureCompareMode := val;
  2059. NotifyParamsChange;
  2060. end;
  2061. end;
  2062. procedure TGLTexture.SetTextureCompareFunc(const val: TGLDepthCompareFunc);
  2063. begin
  2064. if val <> fTextureCompareFunc then
  2065. begin
  2066. fTextureCompareFunc := val;
  2067. NotifyParamsChange;
  2068. end;
  2069. end;
  2070. procedure TGLTexture.SetDepthTextureMode(const val: TGLDepthTextureMode);
  2071. begin
  2072. if val <> fDepthTextureMode then
  2073. begin
  2074. fDepthTextureMode := val;
  2075. NotifyParamsChange;
  2076. end;
  2077. end;
  2078. procedure TGLTexture.PrepareBuildList;
  2079. begin
  2080. GetHandle;
  2081. end;
  2082. procedure TGLTexture.ApplyMappingMode;
  2083. var
  2084. R_Dim: Boolean;
  2085. begin
  2086. R_Dim := gl.ARB_texture_cube_map or gl.EXT_texture3D;
  2087. case MappingMode of
  2088. tmmUser: ; // nothing to do, but checked first (common case)
  2089. tmmObjectLinear:
  2090. begin
  2091. gl.TexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  2092. gl.TexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  2093. gl.TexGenfv(GL_S, GL_OBJECT_PLANE, @MappingSCoordinates.DirectVector);
  2094. gl.TexGenfv(GL_T, GL_OBJECT_PLANE, @MappingTCoordinates.DirectVector);
  2095. gl.Enable(GL_TEXTURE_GEN_S);
  2096. gl.Enable(GL_TEXTURE_GEN_T);
  2097. if R_Dim then
  2098. begin
  2099. gl.TexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  2100. gl.TexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  2101. gl.TexGenfv(GL_R, GL_OBJECT_PLANE, @MappingRCoordinates.DirectVector);
  2102. gl.TexGenfv(GL_Q, GL_OBJECT_PLANE, @MappingQCoordinates.DirectVector);
  2103. gl.Enable(GL_TEXTURE_GEN_R);
  2104. gl.Enable(GL_TEXTURE_GEN_Q);
  2105. end;
  2106. end;
  2107. tmmEyeLinear:
  2108. begin
  2109. gl.TexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  2110. gl.TexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  2111. // specify planes in eye space, not world space
  2112. gl.MatrixMode(GL_MODELVIEW);
  2113. gl.PushMatrix;
  2114. gl.LoadIdentity;
  2115. gl.TexGenfv(GL_S, GL_EYE_PLANE, @MappingSCoordinates.DirectVector);
  2116. gl.TexGenfv(GL_T, GL_EYE_PLANE, @MappingTCoordinates.DirectVector);
  2117. gl.Enable(GL_TEXTURE_GEN_S);
  2118. gl.Enable(GL_TEXTURE_GEN_T);
  2119. if R_Dim then
  2120. begin
  2121. gl.TexGenfv(GL_R, GL_EYE_PLANE, @MappingRCoordinates.DirectVector);
  2122. gl.TexGenfv(GL_Q, GL_EYE_PLANE, @MappingQCoordinates.DirectVector);
  2123. gl.Enable(GL_TEXTURE_GEN_R);
  2124. gl.Enable(GL_TEXTURE_GEN_Q);
  2125. end;
  2126. gl.PopMatrix;
  2127. end;
  2128. tmmSphere:
  2129. begin
  2130. gl.TexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
  2131. gl.TexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
  2132. gl.Enable(GL_TEXTURE_GEN_S);
  2133. gl.Enable(GL_TEXTURE_GEN_T);
  2134. end;
  2135. tmmCubeMapReflection, tmmCubeMapCamera: if gl.ARB_texture_cube_map then
  2136. begin
  2137. gl.TexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
  2138. gl.TexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
  2139. gl.TexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
  2140. gl.Enable(GL_TEXTURE_GEN_S);
  2141. gl.Enable(GL_TEXTURE_GEN_T);
  2142. gl.Enable(GL_TEXTURE_GEN_R);
  2143. end;
  2144. tmmCubeMapNormal, tmmCubeMapLight0: if gl.ARB_texture_cube_map then
  2145. begin
  2146. gl.TexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
  2147. gl.TexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
  2148. gl.TexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
  2149. gl.Enable(GL_TEXTURE_GEN_S);
  2150. gl.Enable(GL_TEXTURE_GEN_T);
  2151. gl.Enable(GL_TEXTURE_GEN_R);
  2152. end;
  2153. else
  2154. Assert(False);
  2155. end;
  2156. end;
  2157. procedure TGLTexture.UnApplyMappingMode;
  2158. begin
  2159. if MappingMode <> tmmUser then
  2160. begin
  2161. gl.Disable(GL_TEXTURE_GEN_S);
  2162. gl.Disable(GL_TEXTURE_GEN_T);
  2163. if gl.EXT_texture3D or gl.ARB_texture_cube_map then
  2164. begin
  2165. gl.Disable(GL_TEXTURE_GEN_R);
  2166. gl.Disable(GL_TEXTURE_GEN_Q);
  2167. end;
  2168. end;
  2169. end;
  2170. procedure TGLTexture.Apply(var rci: TGLRenderContextInfo);
  2171. procedure SetCubeMapTextureMatrix;
  2172. var
  2173. m, mm: TGLMatrix;
  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.GLStates.SetTextureMatrix(m);
  2183. end;
  2184. tmmCubeMapLight0:
  2185. begin
  2186. with TGLScene(rci.scene).Lights do
  2187. if Count > 0 then
  2188. begin
  2189. m := TGLLightSource(Items[0]).AbsoluteMatrix;
  2190. NormalizeMatrix(m);
  2191. mm := rci.PipelineTransformation.ViewMatrix^;
  2192. NormalizeMatrix(mm);
  2193. TransposeMatrix(mm);
  2194. m := MatrixMultiply(m, mm);
  2195. rci.GLStates.SetTextureMatrix(m);
  2196. end;
  2197. end;
  2198. tmmCubeMapCamera:
  2199. begin
  2200. m.V[0] := VectorCrossProduct(rci.cameraUp, rci.cameraDirection);
  2201. m.V[1] := VectorNegate(rci.cameraDirection);
  2202. m.V[2] := rci.cameraUp;
  2203. m.V[3] := WHmgPoint;
  2204. mm := rci.PipelineTransformation.ViewMatrix^;
  2205. NormalizeMatrix(mm);
  2206. TransposeMatrix(mm);
  2207. m := MatrixMultiply(m, mm);
  2208. rci.GLStates.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.GLStates do
  2223. begin
  2224. ActiveTexture := 0;
  2225. TextureBinding[0, FTextureHandle.Target] := H;
  2226. ActiveTextureEnabled[FTextureHandle.Target] := True;
  2227. end;
  2228. { if not rci.GLStates.ForwardContext then}
  2229. begin
  2230. if FTextureHandle.Target = ttTextureCube then
  2231. SetCubeMapTextureMatrix;
  2232. gl.TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
  2233. cTextureMode[FTextureMode]);
  2234. gl.TexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, FEnvColor.AsAddress);
  2235. ApplyMappingMode;
  2236. xgl.MapTexCoordToMain;
  2237. end;
  2238. end
  2239. else {if not rci.GLStates.ForwardContext then}
  2240. begin // default
  2241. xgl.MapTexCoordToMain;
  2242. end;
  2243. end;
  2244. procedure TGLTexture.UnApply(var rci: TGLRenderContextInfo);
  2245. begin
  2246. if not Disabled
  2247. {and not rci.GLStates.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.GLStates 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 TGLTexture.ApplyAsTexture2(var rci: TGLRenderContextInfo; textureMatrix:
  2263. PGLMatrix = nil);
  2264. begin
  2265. ApplyAsTextureN(2, rci, textureMatrix);
  2266. end;
  2267. procedure TGLTexture.UnApplyAsTexture2(var rci: TGLRenderContextInfo;
  2268. reloadIdentityTextureMatrix: boolean);
  2269. begin
  2270. UnApplyAsTextureN(2, rci, reloadIdentityTextureMatrix);
  2271. end;
  2272. procedure TGLTexture.ApplyAsTextureN(n: Integer; var rci: TGLRenderContextInfo;
  2273. textureMatrix: PGLMatrix = nil);
  2274. var
  2275. m: TGLMatrix;
  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.GLStates 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.GLStates.SetTextureMatrix(m);
  2296. end;
  2297. {if not ForwardContext then}
  2298. begin
  2299. gl.TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, cTextureMode[FTextureMode]);
  2300. gl.TexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, FEnvColor.AsAddress);
  2301. ApplyMappingMode;
  2302. ActiveTexture := 0;
  2303. end;
  2304. end;
  2305. end;
  2306. end;
  2307. procedure TGLTexture.UnApplyAsTextureN(n: Integer; var rci: TGLRenderContextInfo;
  2308. reloadIdentityTextureMatrix: boolean);
  2309. begin
  2310. { if not rci.GLStates.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.GLStates 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 TGLTexture.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 CurrentGLContext.GLStates 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 TGLTexture.IsHandleAllocated: Boolean;
  2363. begin
  2364. Result := (FTextureHandle.Handle <> 0);
  2365. end;
  2366. function TGLTexture.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 CurrentGLContext.GLStates 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 CurrentGLContext.GLStates do
  2387. for t := Low(TGLTextureTarget) to High(TGLTextureTarget) do
  2388. TextureBinding[ActiveTexture, t] := LBinding[t];
  2389. end;
  2390. begin
  2391. with CurrentGLContext.GLStates 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 TGLTexture.DestroyHandles;
  2418. begin
  2419. FTextureHandle.DestroyHandle;
  2420. FSamplerHandle.DestroyHandle;
  2421. FRequiredMemorySize := -1;
  2422. end;
  2423. function TGLTexture.IsFloatType: Boolean;
  2424. begin
  2425. Result := IsFloatFormat(TextureFormatEx);
  2426. end;
  2427. function TGLTexture.OpenGLTextureFormat: Integer;
  2428. var
  2429. texComp: TGLTextureCompression;
  2430. begin
  2431. if gl.ARB_texture_compression 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 CurrentGLContext.GLStates 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 TGLTexture.PrepareImage(target: Cardinal);
  2461. var
  2462. bitmap32: TGLImage;
  2463. texComp: TGLTextureCompression;
  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
  2526. and (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 CurrentGLContext.GLStates 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.RegisterAsOpenGLTexture(
  2555. FTextureHandle,
  2556. not (FMinFilter in [miNearest, miLinear]),
  2557. glFormat,
  2558. FTexWidth,
  2559. FTexHeight,
  2560. FTexDepth);
  2561. end;
  2562. if gl.GetError <> GL_NO_ERROR then
  2563. FRequiredMemorySize := -1;
  2564. TextureImageRequiredMemory;
  2565. if not IsDesignTime and not FKeepImageAfterTransfer then
  2566. Image.ReleaseBitmap32;
  2567. end;
  2568. procedure TGLTexture.PrepareParams(target: Cardinal);
  2569. const
  2570. cTextureSWrap: array [twBoth .. twHorizontal] of Cardinal = (GL_REPEAT, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_REPEAT);
  2571. cTextureTWrap: array [twBoth .. twHorizontal] of Cardinal = (GL_REPEAT, GL_CLAMP_TO_EDGE, GL_REPEAT, GL_CLAMP_TO_EDGE);
  2572. cTextureRWrap: array [twBoth .. twHorizontal] of Cardinal = (GL_REPEAT, GL_CLAMP_TO_EDGE, GL_REPEAT, GL_CLAMP_TO_EDGE);
  2573. cTextureSWrapOld: array [twBoth .. twHorizontal] of Cardinal = (GL_REPEAT, GL_CLAMP, GL_CLAMP, GL_REPEAT);
  2574. cTextureTWrapOld: array [twBoth .. twHorizontal] of Cardinal = (GL_REPEAT, GL_CLAMP, GL_REPEAT, GL_CLAMP);
  2575. cTextureMagFilter: array [maNearest .. maLinear] of Cardinal = (GL_NEAREST, GL_LINEAR);
  2576. cTextureMinFilter: array [miNearest .. miLinearMipmapLinear] of Cardinal = (GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST,
  2577. GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR);
  2578. cFilteringQuality: array [tfIsotropic .. tfAnisotropic] of Integer = (1, 2);
  2579. cSeparateTextureWrap: array [twRepeat .. twMirrorClampToBorder] of Cardinal = (GL_REPEAT, GL_CLAMP_TO_EDGE,
  2580. GL_CLAMP_TO_BORDER, GL_MIRRORED_REPEAT, GL_MIRROR_CLAMP_TO_EDGE_ATI, GL_MIRROR_CLAMP_TO_BORDER_EXT);
  2581. cTextureCompareMode: array [tcmNone .. tcmCompareRtoTexture] of Cardinal = (GL_NONE, GL_COMPARE_R_TO_TEXTURE);
  2582. cDepthTextureMode: array [dtmLuminance .. dtmAlpha] of Cardinal = (GL_LUMINANCE, GL_INTENSITY, GL_ALPHA);
  2583. var
  2584. R_Dim: Boolean;
  2585. lMinFilter: TGLMinFilter;
  2586. begin
  2587. if (target = GL_TEXTURE_2D_MULTISAMPLE)
  2588. or (target = GL_TEXTURE_2D_MULTISAMPLE_ARRAY) then
  2589. Exit;
  2590. R_Dim := gl.ARB_texture_cube_map or gl.EXT_texture3D;
  2591. with CurrentGLContext.GLStates do
  2592. begin
  2593. UnpackAlignment := 1;
  2594. UnpackRowLength := 0;
  2595. UnpackSkipRows := 0;
  2596. UnpackSkipPixels := 0;
  2597. end;
  2598. gl.TexParameterfv(target, GL_TEXTURE_BORDER_COLOR, FBorderColor.AsAddress);
  2599. if (gl.VERSION_1_2 or gl.EXT_texture_edge_clamp) then
  2600. begin
  2601. if FTextureWrap = twSeparate then
  2602. begin
  2603. gl.TexParameteri(target, GL_TEXTURE_WRAP_S,
  2604. cSeparateTextureWrap[FTextureWrapS]);
  2605. gl.TexParameteri(target, GL_TEXTURE_WRAP_T,
  2606. cSeparateTextureWrap[FTextureWrapT]);
  2607. if R_Dim then
  2608. gl.TexParameteri(target, GL_TEXTURE_WRAP_R,
  2609. cSeparateTextureWrap[FTextureWrapR]);
  2610. end
  2611. else
  2612. begin
  2613. gl.TexParameteri(target, GL_TEXTURE_WRAP_S, cTextureSWrap[FTextureWrap]);
  2614. gl.TexParameteri(target, GL_TEXTURE_WRAP_T, cTextureTWrap[FTextureWrap]);
  2615. if R_Dim then
  2616. gl.TexParameteri(target, GL_TEXTURE_WRAP_R, cTextureRWrap[FTextureWrap]);
  2617. end;
  2618. end
  2619. else
  2620. begin
  2621. gl.TexParameteri(target, GL_TEXTURE_WRAP_S, cTextureSWrapOld[FTextureWrap]);
  2622. gl.TexParameteri(target, GL_TEXTURE_WRAP_T, cTextureTWrapOld[FTextureWrap]);
  2623. end;
  2624. lMinFilter := FMinFilter;
  2625. // Down paramenter to rectangular texture supported
  2626. if (target = GL_TEXTURE_RECTANGLE)
  2627. or not (gl.EXT_texture_lod or gl.SGIS_texture_lod) then
  2628. begin
  2629. if lMinFilter in [miNearestMipmapNearest, miNearestMipmapLinear] then
  2630. lMinFilter := miNearest;
  2631. if FMinFilter in [miLinearMipmapNearest, miLinearMipmapLinear] then
  2632. lMinFilter := miLinear;
  2633. end;
  2634. gl.TexParameteri(target, GL_TEXTURE_MIN_FILTER, cTextureMinFilter[lMinFilter]);
  2635. gl.TexParameteri(target, GL_TEXTURE_MAG_FILTER, cTextureMagFilter[FMagFilter]);
  2636. if gl.EXT_texture_filter_anisotropic then
  2637. gl.TexParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT,
  2638. cFilteringQuality[FFilteringQuality]);
  2639. if IsDepthFormat(fTextureFormat) then
  2640. begin
  2641. gl.TexParameteri(target, GL_TEXTURE_COMPARE_MODE,
  2642. cTextureCompareMode[fTextureCompareMode]);
  2643. gl.TexParameteri(target, GL_TEXTURE_COMPARE_FUNC,
  2644. cGLComparisonFunctionToGLEnum[fTextureCompareFunc]);
  2645. { if not FTextureHandle.RenderingContext.GLStates.ForwardContext then}
  2646. gl.TexParameteri(target, GL_DEPTH_TEXTURE_MODE,
  2647. cDepthTextureMode[fDepthTextureMode]);
  2648. end;
  2649. end;
  2650. procedure TGLTexture.DoOnTextureNeeded(Sender: TObject; var textureFileName:
  2651. string);
  2652. begin
  2653. if Assigned(FOnTextureNeeded) then
  2654. FOnTextureNeeded(Sender, textureFileName);
  2655. end;
  2656. procedure TGLTexture.OnSamplerAllocate(Sender: TGLVirtualHandle; var Handle: Cardinal);
  2657. begin
  2658. Handle := 1;
  2659. end;
  2660. procedure TGLTexture.OnSamplerDestroy(Sender: TGLVirtualHandle; var Handle: Cardinal);
  2661. begin
  2662. Handle := 0;
  2663. end;
  2664. procedure TGLTexture.SetTextureErrorImage;
  2665. var
  2666. img: TGLImage;
  2667. begin
  2668. img := TGLImage.Create;
  2669. img.SetErrorImage;
  2670. ImageClassName := TGLBlankImage.className;
  2671. TGLBlankImage(Image).Assign(img);
  2672. img.Free;
  2673. MagFilter := maNearest;
  2674. MinFilter := miNearest;
  2675. TextureWrap := twBoth;
  2676. MappingMode := tmmUser;
  2677. Compression := tcNone;
  2678. AllocateHandle;
  2679. end;
  2680. // ---------------
  2681. // --------------- TGLTextureExItem ---------------
  2682. // ---------------
  2683. constructor TGLTextureExItem.Create(ACollection: TCollection);
  2684. begin
  2685. inherited;
  2686. FTexture := TGLTexture.Create(Self);
  2687. FTextureOffset := TGCoordinates.CreateInitialized(Self, NullHMGVector,
  2688. csPoint);
  2689. FTextureOffset.OnNotifyChange := OnNotifyChange;
  2690. FTextureScale := TGCoordinates.CreateInitialized(Self, XYZHmgVector,
  2691. csPoint);
  2692. FTextureScale.OnNotifyChange := OnNotifyChange;
  2693. FTextureIndex := ID;
  2694. FTextureMatrix := IdentityHMGMatrix;
  2695. //DanB - hmmm, not very flexible code, assumes it's owned by a material,
  2696. // that has a Texture property, but may need to re-implement it somehow
  2697. { if ACollection is TGLTextureEx then
  2698. if TGLTextureEx(ACollection).FOwner <> nil then
  2699. FTexture.OnTextureNeeded := TGLTextureEx(ACollection).FOwner.Texture.OnTextureNeeded;
  2700. }
  2701. end;
  2702. destructor TGLTextureExItem.Destroy;
  2703. begin
  2704. FTexture.Free;
  2705. FTextureOffset.Free;
  2706. FTextureScale.Free;
  2707. inherited;
  2708. end;
  2709. function TGLTextureExItem.QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
  2710. begin
  2711. if GetInterface(IID, Obj) then
  2712. Result := S_OK
  2713. else
  2714. Result := E_NOINTERFACE;
  2715. end;
  2716. function TGLTextureExItem._AddRef: Integer; stdcall;
  2717. begin
  2718. Result := -1; //ignore
  2719. end;
  2720. function TGLTextureExItem._Release: Integer; stdcall;
  2721. begin
  2722. Result := -1; //ignore
  2723. end;
  2724. procedure TGLTextureExItem.Assign(Source: TPersistent);
  2725. begin
  2726. if Source is TGLTextureExItem then
  2727. begin
  2728. Texture := TGLTextureExItem(Source).Texture;
  2729. TextureIndex := TGLTextureExItem(Source).TextureIndex;
  2730. TextureOffset := TGLTextureExItem(Source).TextureOffset;
  2731. TextureScale := TGLTextureExItem(Source).TextureScale;
  2732. NotifyChange(Self);
  2733. end
  2734. else
  2735. inherited;
  2736. end;
  2737. procedure TGLTextureExItem.NotifyChange(Sender: TObject);
  2738. begin
  2739. if Assigned(Collection) then
  2740. TGLTextureEx(Collection).NotifyChange(Self);
  2741. end;
  2742. procedure TGLTextureExItem.Apply(var rci: TGLRenderContextInfo);
  2743. begin
  2744. FApplied := False;
  2745. if FTexture.Enabled then
  2746. begin
  2747. rci.GLStates.ActiveTexture := FTextureIndex;
  2748. gl.MatrixMode(GL_TEXTURE);
  2749. gl.PushMatrix;
  2750. if FTextureMatrixIsIdentity then
  2751. gl.LoadIdentity
  2752. else
  2753. gl.LoadMatrixf(@FTextureMatrix.V[0].X);
  2754. gl.MatrixMode(GL_MODELVIEW);
  2755. rci.GLStates.ActiveTexture := 0;
  2756. if FTextureIndex = 0 then
  2757. FTexture.Apply(rci)
  2758. else if FTextureIndex = 1 then
  2759. FTexture.ApplyAsTexture2(rci, nil)
  2760. else if FTextureIndex >= 2 then
  2761. FTexture.ApplyAsTextureN(FTextureIndex + 1, rci, nil);
  2762. FApplied := True;
  2763. end;
  2764. end;
  2765. procedure TGLTextureExItem.UnApply(var rci: TGLRenderContextInfo);
  2766. begin
  2767. if FApplied then
  2768. begin
  2769. if FTextureIndex = 0 then
  2770. FTexture.UnApply(rci)
  2771. else if FTextureIndex = 1 then
  2772. FTexture.UnApplyAsTexture2(rci, false)
  2773. else if FTextureIndex >= 2 then
  2774. FTexture.UnApplyAsTextureN(FTextureIndex + 1, rci, false);
  2775. rci.GLStates.ActiveTexture := FTextureIndex;
  2776. gl.MatrixMode(GL_TEXTURE);
  2777. gl.PopMatrix;
  2778. gl.MatrixMode(GL_MODELVIEW);
  2779. rci.GLStates.ActiveTexture := 0;
  2780. FApplied := False;
  2781. end;
  2782. end;
  2783. function TGLTextureExItem.GetDisplayName: string;
  2784. begin
  2785. Result := Format('Tex [%d]', [FTextureIndex]);
  2786. end;
  2787. function TGLTextureExItem.GetOwner: TPersistent;
  2788. begin
  2789. Result := Collection;
  2790. end;
  2791. procedure TGLTextureExItem.NotifyTexMapChange(Sender: TObject);
  2792. var
  2793. intf: IGLTextureNotifyAble;
  2794. begin
  2795. if Supports(TObject(TGLTextureEx(Collection).FOwner), IGLTextureNotifyAble,
  2796. intf) then
  2797. intf.NotifyTexMapChange(Sender);
  2798. end;
  2799. procedure TGLTextureExItem.SetTexture(const Value: TGLTexture);
  2800. begin
  2801. FTexture.Assign(Value);
  2802. NotifyChange(Self);
  2803. end;
  2804. procedure TGLTextureExItem.SetTextureIndex(const Value: Integer);
  2805. var
  2806. temp: Integer;
  2807. begin
  2808. temp := Value;
  2809. if temp < 0 then
  2810. temp := 0;
  2811. if temp <> FTextureIndex then
  2812. begin
  2813. FTextureIndex := temp;
  2814. NotifyChange(Self);
  2815. end;
  2816. end;
  2817. procedure TGLTextureExItem.SetTextureOffset(const Value: TGCoordinates);
  2818. begin
  2819. FTextureOffset.Assign(Value);
  2820. NotifyChange(Self);
  2821. end;
  2822. procedure TGLTextureExItem.SetTextureScale(const Value: TGCoordinates);
  2823. begin
  2824. FTextureScale.Assign(Value);
  2825. NotifyChange(Self);
  2826. end;
  2827. procedure TGLTextureExItem.CalculateTextureMatrix;
  2828. begin
  2829. if TextureOffset.Equals(NullHmgVector) and TextureScale.Equals(XYZHmgVector) then
  2830. FTextureMatrixIsIdentity := True
  2831. else
  2832. begin
  2833. FTextureMatrixIsIdentity := False;
  2834. FTextureMatrix := CreateScaleAndTranslationMatrix(TextureScale.AsVector,
  2835. TextureOffset.AsVector);
  2836. end;
  2837. NotifyChange(Self);
  2838. end;
  2839. procedure TGLTextureExItem.OnNotifyChange(Sender: TObject);
  2840. begin
  2841. CalculateTextureMatrix;
  2842. end;
  2843. // ---------------
  2844. // --------------- TGLTextureEx ---------------
  2845. // ---------------
  2846. constructor TGLTextureEx.Create(AOwner: TGUpdateAbleObject);
  2847. begin
  2848. inherited Create(TGLTextureExItem);
  2849. FOwner := AOwner;
  2850. end;
  2851. procedure TGLTextureEx.NotifyChange(Sender: TObject);
  2852. begin
  2853. if Assigned(FOwner) then
  2854. FOwner.NotifyChange(Self);
  2855. end;
  2856. procedure TGLTextureEx.Apply(var rci: TGLRenderContextInfo);
  2857. var
  2858. i, texUnits: Integer;
  2859. units: Cardinal;
  2860. begin
  2861. if not gl.ARB_multitexture then
  2862. exit;
  2863. units := 0;
  2864. gl.GetIntegerv(GL_MAX_TEXTURE_UNITS, @texUnits);
  2865. for i := 0 to Count - 1 do
  2866. begin
  2867. if Items[i].TextureIndex < texUnits then
  2868. begin
  2869. Items[i].Apply(rci);
  2870. if Items[i].FApplied then
  2871. if (Items[i].TextureIndex > 0) and (Items[i].Texture.MappingMode =
  2872. tmmUser) then
  2873. units := units or (1 shl Items[i].TextureIndex);
  2874. end;
  2875. end;
  2876. if units > 0 then
  2877. xgl.MapTexCoordToArbitraryAdd(units);
  2878. end;
  2879. procedure TGLTextureEx.UnApply(var rci: TGLRenderContextInfo);
  2880. var
  2881. i: Integer;
  2882. begin
  2883. if not gl.ARB_multitexture then
  2884. exit;
  2885. for i := 0 to Count - 1 do
  2886. Items[i].UnApply(rci);
  2887. end;
  2888. function TGLTextureEx.Add: TGLTextureExItem;
  2889. begin
  2890. Result := TGLTextureExItem(inherited Add);
  2891. end;
  2892. procedure TGLTextureEx.Loaded;
  2893. var
  2894. i: Integer;
  2895. begin
  2896. for i := 0 to Count - 1 do
  2897. Items[i].CalculateTextureMatrix;
  2898. end;
  2899. function TGLTextureEx.GetOwner: TPersistent;
  2900. begin
  2901. Result := FOwner;
  2902. end;
  2903. procedure TGLTextureEx.SetItems(index: Integer; const Value: TGLTextureExItem);
  2904. begin
  2905. inherited SetItem(index, Value);
  2906. end;
  2907. function TGLTextureEx.GetItems(index: Integer): TGLTextureExItem;
  2908. begin
  2909. Result := TGLTextureExItem(inherited GetItem(index));
  2910. end;
  2911. function TGLTextureEx.IsTextureEnabled(Index: Integer): Boolean;
  2912. var
  2913. i: Integer;
  2914. begin
  2915. Result := False;
  2916. if Self = nil then
  2917. Exit;
  2918. for i := 0 to Count - 1 do
  2919. if Items[i].TextureIndex = Index then
  2920. Result := Result or Items[i].Texture.Enabled;
  2921. end;
  2922. // ------------------------------------------------------------------
  2923. initialization
  2924. // ------------------------------------------------------------------
  2925. RegisterGLTextureImageClass(TGLBlankImage);
  2926. RegisterGLTextureImageClass(TGLPersistentImage);
  2927. RegisterGLTextureImageClass(TGLPicFileImage);
  2928. RegisterGLTextureImageClass(TGLCubeMapImage);
  2929. RegisterTGraphicClassFileExtension('.bmp', TBitmap);
  2930. finalization
  2931. vGLTextureImageClasses.Free;
  2932. vGLTextureImageClasses := nil;
  2933. end.