GLTexture.pas 95 KB

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