GLS.Material.pas 90 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058
  1. //
  2. // The multimedia graphics platform GLScene https://github.com/glscene
  3. //
  4. unit GLS.Material;
  5. (* Handles all the material + material library stuff *)
  6. interface
  7. {$I GLScene.inc}
  8. uses
  9. System.Classes,
  10. System.SysUtils,
  11. System.Types,
  12. Vcl.Graphics,
  13. GLS.OpenGLTokens,
  14. GLS.VectorTypes,
  15. GLS.VectorGeometry,
  16. GLS.RenderContextInfo,
  17. GLS.BaseClasses,
  18. GLS.Context,
  19. GLS.Texture,
  20. GLS.Color,
  21. GLS.Coordinates,
  22. GLS.PersistentClasses,
  23. GLS.State,
  24. GLS.TextureFormat,
  25. GLS.XOpenGL,
  26. GLS.ApplicationFileIO,
  27. GLS.Graphics,
  28. GLS.Utils,
  29. GLS.Strings,
  30. GLS.Logger;
  31. {$UNDEF USE_MULTITHREAD}
  32. type
  33. TGLFaceProperties = class;
  34. TGLMaterial = class;
  35. TGLAbstractMaterialLibrary = class;
  36. TGLMaterialLibrary = class;
  37. //an interface for proper TGLLibMaterialNameProperty support
  38. IGLMaterialLibrarySupported = interface(IInterface)
  39. ['{8E442AF9-D212-4A5E-8A88-92F798BABFD1}']
  40. function GetMaterialLibrary: TGLAbstractMaterialLibrary;
  41. end;
  42. TGLAbstractLibMaterial = class;
  43. TGLLibMaterial = class;
  44. (* Define GLShader style application relatively to a material.
  45. ssHighLevel: shader is applied before material application, and unapplied
  46. after material unapplication
  47. ssLowLevel: shader is applied after material application, and unapplied
  48. before material unapplication
  49. ssReplace: shader is applied in place of the material (and material
  50. is completely ignored)*)
  51. TGLShaderStyle = (ssHighLevel, ssLowLevel, ssReplace);
  52. (* Defines what to do if for some reason shader failed to initialize.
  53. fiaSilentdisable: just disable it
  54. fiaRaiseHandledException: raise an exception, and handle it right away
  55. (usefull, when debigging within Delphi)
  56. fiaRaiseStardardException: raises the exception with a string from this
  57. function GetStardardNotSupportedMessage
  58. fiaReRaiseException: Re-raises the exception
  59. fiaGenerateEvent: Handles the exception, but generates an event
  60. that user can respond to. For example, he can
  61. try to compile a substitude shader, or replace
  62. it by a material.
  63. Note: HandleFailedInitialization does *not* create this event,
  64. it is left to user shaders which may chose to override this procedure.
  65. Commented out, because not sure if this option should exist,
  66. let other generations of developers decide ;) *)
  67. TGLShaderFailedInitAction = (
  68. fiaSilentDisable, fiaRaiseStandardException, fiaRaiseHandledException,
  69. fiaReRaiseException {,fiaGenerateEvent});
  70. (* Generic, abstract shader class.
  71. Shaders are modeled here as an abstract material-altering entity with
  72. transaction-like behaviour. The base class provides basic context and user
  73. tracking, as well as setup/application facilities.
  74. Subclasses are expected to provide implementation for DoInitialize,
  75. DoApply, DoUnApply and DoFinalize. *)
  76. TGLShader = class(TGLUpdateAbleComponent)
  77. private
  78. FEnabled: Boolean;
  79. FLibMatUsers: TList;
  80. FVirtualHandle: TGLVirtualHandle;
  81. FShaderStyle: TGLShaderStyle;
  82. FUpdateCount: Integer;
  83. FShaderActive: Boolean;
  84. FFailedInitAction: TGLShaderFailedInitAction;
  85. protected
  86. (*Invoked once, before the first call to DoApply.
  87. The call happens with the OpenGL context being active. *)
  88. procedure DoInitialize(var rci: TGLRenderContextInfo; Sender: TObject); virtual;
  89. (* Request to apply the shader.
  90. Always followed by a DoUnApply when the shader is no longer needed. *)
  91. procedure DoApply(var rci: TGLRenderContextInfo; Sender: TObject); virtual;
  92. (* Request to un-apply the shader.
  93. Subclasses can assume the shader has been applied previously.
  94. Return True to request a multipass. *)
  95. function DoUnApply(var rci: TGLRenderContextInfo): Boolean; virtual;
  96. (* Invoked once, before the destruction of context or release of shader.
  97. The call happens with the OpenGL context being active. *)
  98. procedure DoFinalize; virtual;
  99. function GetShaderInitialized: Boolean;
  100. procedure InitializeShader(var rci: TGLRenderContextInfo; Sender: TObject);
  101. procedure FinalizeShader;
  102. procedure OnVirtualHandleAllocate(sender: TGLVirtualHandle; var handle: Cardinal);
  103. procedure OnVirtualHandleDestroy(sender: TGLVirtualHandle; var handle: Cardinal);
  104. procedure SetEnabled(val: Boolean);
  105. property ShaderInitialized: Boolean read GetShaderInitialized;
  106. property ShaderActive: Boolean read FShaderActive;
  107. procedure RegisterUser(libMat: TGLLibMaterial);
  108. procedure UnRegisterUser(libMat: TGLLibMaterial);
  109. // Used by the DoInitialize procedure of descendant classes to raise errors.
  110. procedure HandleFailedInitialization(const LastErrorMessage: string = '');
  111. virtual;
  112. // May be this should be a function inside HandleFailedInitialization...
  113. function GetStardardNotSupportedMessage: string; virtual;
  114. public
  115. constructor Create(AOwner: TComponent); override;
  116. destructor Destroy; override;
  117. (* Subclasses should invoke this function when shader properties are altered.
  118. This procedure can also be used to reset/recompile the shader. *)
  119. procedure NotifyChange(Sender: TObject); override;
  120. procedure BeginUpdate;
  121. procedure EndUpdate;
  122. // Apply shader to OpenGL state machine.
  123. procedure Apply(var rci: TGLRenderContextInfo; Sender: TObject);
  124. (* UnApply shader.
  125. When returning True, the caller is expected to perform a multipass
  126. rendering by re-rendering then invoking UnApply again, until a
  127. "False" is returned. *)
  128. function UnApply(var rci: TGLRenderContextInfo): Boolean;
  129. // Shader application style (default is ssLowLevel).
  130. property ShaderStyle: TGLShaderStyle read FShaderStyle write FShaderStyle
  131. default ssLowLevel;
  132. procedure Assign(Source: TPersistent); override;
  133. (* Defines if shader is supported by hardware/drivers.
  134. Default - always supported. Descendants are encouraged to override
  135. this function. *)
  136. function ShaderSupported: Boolean; virtual;
  137. (* Defines what to do if for some reason shader failed to initialize.
  138. Note, that in some cases it cannon be determined by just checking the
  139. required OpenGL extentions. You need to try to compile and link the
  140. shader - only at that stage you might catch an error *)
  141. property FailedInitAction: TGLShaderFailedInitAction
  142. read FFailedInitAction write FFailedInitAction default
  143. fiaRaiseStandardException;
  144. published
  145. (* Turns on/off shader application.
  146. Note that this only turns on/off the shader application, if the
  147. ShaderStyle is ssReplace, the material won't be applied even if
  148. the shader is disabled. *)
  149. property Enabled: Boolean read FEnabled write SetEnabled default True;
  150. end;
  151. TGLShaderClass = class of TGLShader;
  152. TGLShininess = 0..128;
  153. (* Stores basic face lighting properties.
  154. The lighting is described with the standard ambient/diffuse/emission/specular
  155. properties that behave like those of most rendering tools.
  156. You also have control over shininess (governs specular lighting) and
  157. polygon mode (lines / fill). *)
  158. TGLFaceProperties = class(TGLUpdateAbleObject)
  159. private
  160. FAmbient, FDiffuse, FSpecular, FEmission: TGLColor;
  161. FShininess: TGLShininess;
  162. protected
  163. procedure SetAmbient(AValue: TGLColor);
  164. procedure SetDiffuse(AValue: TGLColor);
  165. procedure SetEmission(AValue: TGLColor);
  166. procedure SetSpecular(AValue: TGLColor);
  167. procedure SetShininess(AValue: TGLShininess);
  168. public
  169. constructor Create(AOwner: TPersistent); override;
  170. destructor Destroy; override;
  171. procedure Apply(var rci: TGLRenderContextInfo; aFace: TGLCullFaceMode); inline;
  172. procedure ApplyNoLighting(var rci: TGLRenderContextInfo; aFace: TGLCullFaceMode); inline;
  173. procedure Assign(Source: TPersistent); override;
  174. published
  175. property Ambient: TGLColor read FAmbient write SetAmbient;
  176. property Diffuse: TGLColor read FDiffuse write SetDiffuse;
  177. property Emission: TGLColor read FEmission write SetEmission;
  178. property Shininess: TGLShininess read FShininess write SetShininess default 0;
  179. property Specular: TGLColor read FSpecular write SetSpecular;
  180. end;
  181. TGLDepthProperties = class(TGLUpdateAbleObject)
  182. private
  183. FDepthTest: boolean;
  184. FDepthWrite: boolean;
  185. FZNear, FZFar: Single;
  186. FCompareFunc: TGLDepthfunction;
  187. FDepthClamp: Boolean;
  188. protected
  189. procedure SetZNear(Value: Single);
  190. procedure SetZFar(Value: Single);
  191. procedure SetCompareFunc(Value: TGLDepthCompareFunc);
  192. procedure SetDepthTest(Value: boolean);
  193. procedure SetDepthWrite(Value: boolean);
  194. procedure SetDepthClamp(Value: boolean);
  195. function StoreZNear: Boolean;
  196. function StoreZFar: Boolean;
  197. public
  198. constructor Create(AOwner: TPersistent); override;
  199. procedure Apply(var rci: TGLRenderContextInfo);
  200. procedure Assign(Source: TPersistent); override;
  201. published
  202. (* Specifies the mapping of the near clipping plane to
  203. window coordinates. The initial value is 0. *)
  204. property ZNear: Single read FZNear write SetZNear stored StoreZNear;
  205. (* Specifies the mapping of the far clipping plane to
  206. window coordinates. The initial value is 1. *)
  207. property ZFar: Single read FZFar write SetZFar stored StoreZFar;
  208. (* Specifies the function used to compare each
  209. incoming pixel depth value with the depth value present in
  210. the depth buffer. *)
  211. property DepthCompareFunction: TGLDepthFunction
  212. read FCompareFunc write SetCompareFunc default cfLequal;
  213. (* DepthTest enabling.
  214. When DepthTest is enabled, objects closer to the camera will hide
  215. farther ones (via use of Z-Buffering).
  216. When DepthTest is disabled, the latest objects drawn/rendered overlap
  217. all previous objects, whatever their distance to the camera.
  218. Even when DepthTest is enabled, objects may chose to ignore depth
  219. testing through the osIgnoreDepthBuffer of their ObjectStyle property. *)
  220. property DepthTest: boolean read FDepthTest write SetDepthTest default True;
  221. // If True, object will not write to Z-Buffer.
  222. property DepthWrite: boolean read FDepthWrite write SetDepthWrite default True;
  223. // Enable clipping depth to the near and far planes
  224. property DepthClamp: Boolean read FDepthClamp write SetDepthClamp default False;
  225. end;
  226. TGLLibMaterialName = string;
  227. TGlAlphaFunc = TGLComparisonFunction;
  228. TGLBlendingParameters = class(TGLUpdateAbleObject)
  229. private
  230. FUseAlphaFunc: Boolean;
  231. FUseBlendFunc: Boolean;
  232. FSeparateBlendFunc: Boolean;
  233. FAlphaFuncType: TGlAlphaFunc;
  234. FAlphaFuncRef: Single;
  235. FBlendFuncSFactor: TGLBlendFunction;
  236. FBlendFuncDFactor: TGLBlendFunction;
  237. FAlphaBlendFuncSFactor: TGLBlendFunction;
  238. FAlphaBlendFuncDFactor: TGLBlendFunction;
  239. procedure SetUseAlphaFunc(const Value: Boolean);
  240. procedure SetUseBlendFunc(const Value: Boolean);
  241. procedure SetSeparateBlendFunc(const Value: Boolean);
  242. procedure SetAlphaFuncRef(const Value: Single);
  243. procedure SetAlphaFuncType(const Value: TGlAlphaFunc);
  244. procedure SetBlendFuncDFactor(const Value: TGLBlendFunction);
  245. procedure SetBlendFuncSFactor(const Value: TGLBlendFunction);
  246. procedure SetAlphaBlendFuncDFactor(const Value: TGLBlendFunction);
  247. procedure SetAlphaBlendFuncSFactor(const Value: TGLBlendFunction);
  248. function StoreAlphaFuncRef: Boolean;
  249. public
  250. constructor Create(AOwner: TPersistent); override;
  251. procedure Apply(var rci: TGLRenderContextInfo); inline;
  252. published
  253. property UseAlphaFunc: Boolean read FUseAlphaFunc write SetUseAlphaFunc
  254. default False;
  255. property AlphaFunctType: TGlAlphaFunc read FAlphaFuncType write
  256. SetAlphaFuncType default cfGreater;
  257. property AlphaFuncRef: Single read FAlphaFuncRef write SetAlphaFuncRef
  258. stored StoreAlphaFuncRef;
  259. property UseBlendFunc: Boolean read FUseBlendFunc write SetUseBlendFunc
  260. default True;
  261. property SeparateBlendFunc: Boolean read FSeparateBlendFunc write SetSeparateBlendFunc
  262. default False;
  263. property BlendFuncSFactor: TGLBlendFunction read FBlendFuncSFactor write
  264. SetBlendFuncSFactor default bfSrcAlpha;
  265. property BlendFuncDFactor: TGLBlendFunction read FBlendFuncDFactor write
  266. SetBlendFuncDFactor default bfOneMinusSrcAlpha;
  267. property AlphaBlendFuncSFactor: TGLBlendFunction read FAlphaBlendFuncSFactor write
  268. SetAlphaBlendFuncSFactor default bfSrcAlpha;
  269. property AlphaBlendFuncDFactor: TGLBlendFunction read FAlphaBlendFuncDFactor write
  270. SetAlphaBlendFuncDFactor default bfOneMinusSrcAlpha;
  271. end;
  272. (* Simplified blending options.
  273. bmOpaque : disable blending
  274. bmTransparency : uses standard alpha blending
  275. bmAdditive : activates additive blending (with saturation)
  276. bmAlphaTest50 : uses opaque blending, with alpha-testing at 50% (full
  277. transparency if alpha is below 0.5, full opacity otherwise)
  278. bmAlphaTest100 : uses opaque blending, with alpha-testing at 100%
  279. bmModulate : uses modulation blending
  280. bmCustom : uses TGLBlendingParameters options *)
  281. TGLBlendingMode = (bmOpaque, bmTransparency, bmAdditive,
  282. bmAlphaTest50, bmAlphaTest100, bmModulate, bmCustom);
  283. TGLFaceCulling = (fcBufferDefault, fcCull, fcNoCull);
  284. (* Control special rendering options for a material.
  285. moIgnoreFog : fog is deactivated when the material is rendered *)
  286. TGLMaterialOption = (moIgnoreFog, moNoLighting);
  287. TGLMaterialOptions = set of TGLMaterialOption;
  288. (* Describes a rendering material.
  289. A material is basically a set of face properties (front and back) that take
  290. care of standard material rendering parameters (diffuse, ambient, emission
  291. and specular) and texture mapping.
  292. An instance of this class is available for almost all objects in GLScene
  293. to allow quick definition of material properties. It can link to a
  294. TGLLibMaterial (taken for a material library).
  295. The TGLLibMaterial has more advanced properties (like texture transforms)
  296. and provides a standard way of sharing definitions and texture maps. *)
  297. TGLMaterial = class(TGLUpdateAbleObject, IGLMaterialLibrarySupported, IGLTextureNotifyAble)
  298. private
  299. FFrontProperties, FBackProperties: TGLFaceProperties;
  300. FDepthProperties: TGLDepthProperties;
  301. FBlendingMode: TGLBlendingMode;
  302. FBlendingParams: TGLBlendingParameters;
  303. FTexture: TGLTexture;
  304. FTextureEx: TGLTextureEx;
  305. FMaterialLibrary: TGLAbstractMaterialLibrary;
  306. FLibMaterialName: TGLLibMaterialName;
  307. FMaterialOptions: TGLMaterialOptions;
  308. FFaceCulling: TGLFaceCulling;
  309. FPolygonMode: TGLPolygonMode;
  310. currentLibMaterial: TGLAbstractLibMaterial;
  311. // Implementing IGLMaterialLibrarySupported.
  312. function GetMaterialLibrary: TGLAbstractMaterialLibrary;
  313. protected
  314. function GetBackProperties: TGLFaceProperties; inline;
  315. procedure SetBackProperties(Values: TGLFaceProperties);
  316. procedure SetFrontProperties(Values: TGLFaceProperties);
  317. procedure SetDepthProperties(Values: TGLDepthProperties);
  318. procedure SetBlendingMode(const val: TGLBlendingMode);
  319. procedure SetMaterialOptions(const val: TGLMaterialOptions);
  320. function GetTexture: TGLTexture;
  321. procedure SetTexture(ATexture: TGLTexture);
  322. procedure SetMaterialLibrary(const val: TGLAbstractMaterialLibrary);
  323. procedure SetLibMaterialName(const val: TGLLibMaterialName);
  324. procedure SetFaceCulling(const val: TGLFaceCulling);
  325. procedure SetPolygonMode(AValue: TGLPolygonMode);
  326. function GetTextureEx: TGLTextureEx;
  327. procedure SetTextureEx(const value: TGLTextureEx);
  328. function StoreTextureEx: Boolean;
  329. procedure SetBlendingParams(const Value: TGLBlendingParameters);
  330. procedure NotifyLibMaterialDestruction;
  331. // Back, Front, Texture and blending not stored if linked to a LibMaterial
  332. function StoreMaterialProps: Boolean;
  333. public
  334. constructor Create(AOwner: TPersistent); override;
  335. destructor Destroy; override;
  336. procedure PrepareBuildList; inline;
  337. procedure Apply(var rci: TGLRenderContextInfo);
  338. (* Restore non-standard material states that were altered;
  339. A return value of True is a multipass request. *)
  340. function UnApply(var rci: TGLRenderContextInfo): Boolean; inline;
  341. procedure Assign(Source: TPersistent); override;
  342. procedure NotifyChange(Sender: TObject); override;
  343. procedure NotifyTexMapChange(Sender: TObject);
  344. procedure DestroyHandles;
  345. procedure Loaded;
  346. (* Returns True if the material is blended.
  347. Will return the libmaterial's blending if it is linked to a material library. *)
  348. function Blended: Boolean; inline;
  349. // True if the material has a secondary texture
  350. function HasSecondaryTexture: Boolean;
  351. // True if the material comes from the library instead of the texture property
  352. function MaterialIsLinkedToLib: Boolean; inline;
  353. // Gets the primary texture either from material library or the texture property
  354. function GetActualPrimaryTexture: TGLTexture;
  355. // Gets the primary Material either from material library or the texture property
  356. function GetActualPrimaryMaterial: TGLMaterial;
  357. // Return the LibMaterial (see LibMaterialName)
  358. function GetLibMaterial: TGLLibMaterial;
  359. procedure QuickAssignMaterial(const MaterialLibrary: TGLMaterialLibrary;
  360. const Material: TGLLibMaterial);
  361. published
  362. property BackProperties: TGLFaceProperties read GetBackProperties write
  363. SetBackProperties stored StoreMaterialProps;
  364. property FrontProperties: TGLFaceProperties read FFrontProperties write
  365. SetFrontProperties stored StoreMaterialProps;
  366. property DepthProperties: TGLDepthProperties read FDepthProperties write
  367. SetDepthProperties stored StoreMaterialProps;
  368. property BlendingMode: TGLBlendingMode read FBlendingMode write SetBlendingMode
  369. stored StoreMaterialProps default bmOpaque;
  370. property BlendingParams: TGLBlendingParameters read FBlendingParams
  371. write SetBlendingParams;
  372. property MaterialOptions: TGLMaterialOptions read FMaterialOptions
  373. write SetMaterialOptions default [];
  374. property Texture: TGLTexture read GetTexture write SetTexture stored StoreMaterialProps;
  375. property FaceCulling: TGLFaceCulling read FFaceCulling write SetFaceCulling default fcBufferDefault;
  376. property MaterialLibrary: TGLAbstractMaterialLibrary read FMaterialLibrary write SetMaterialLibrary;
  377. property LibMaterialName: TGLLibMaterialName read FLibMaterialName write SetLibMaterialName;
  378. property TextureEx: TGLTextureEx read GetTextureEx write SetTextureEx stored StoreTextureEx;
  379. property PolygonMode: TGLPolygonMode read FPolygonMode write SetPolygonMode default pmFill;
  380. end;
  381. TGLAbstractLibMaterial = class(
  382. TCollectionItem,
  383. IGLMaterialLibrarySupported,
  384. IGLNotifyAble)
  385. protected
  386. FUserList: TList;
  387. FName: TGLLibMaterialName;
  388. FNameHashKey: Integer;
  389. FTag: Integer;
  390. // Used for recursivity protection
  391. FNotifying: Boolean;
  392. {implementing IGLMaterialLibrarySupported}
  393. function GetMaterialLibrary: TGLAbstractMaterialLibrary;
  394. // Implementing IInterface
  395. function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
  396. function _AddRef: Integer; stdcall;
  397. function _Release: Integer; stdcall;
  398. protected
  399. function GetDisplayName: string; override;
  400. class function ComputeNameHashKey(const name: string): Integer;
  401. procedure SetName(const val: TGLLibMaterialName);
  402. procedure Loaded; virtual;
  403. public
  404. constructor Create(ACollection: TCollection); override;
  405. destructor Destroy; override;
  406. procedure Assign(Source: TPersistent); override;
  407. procedure Apply(var ARci: TGLRenderContextInfo); virtual;
  408. // Restore non-standard material states that were altered
  409. function UnApply(var ARci: TGLRenderContextInfo): Boolean; virtual;
  410. procedure RegisterUser(obj: TGLUpdateAbleObject); overload;
  411. procedure UnregisterUser(obj: TGLUpdateAbleObject); overload;
  412. procedure RegisterUser(comp: TGLUpdateAbleComponent); overload;
  413. procedure UnregisterUser(comp: TGLUpdateAbleComponent); overload;
  414. procedure RegisterUser(libMaterial: TGLLibMaterial); overload;
  415. procedure UnregisterUser(libMaterial: TGLLibMaterial); overload;
  416. procedure NotifyUsers;
  417. // Returns true if the texture has registed users
  418. function IsUsed: boolean;
  419. property NameHashKey: Integer read FNameHashKey;
  420. procedure NotifyChange(Sender: TObject); virtual;
  421. function Blended: Boolean; virtual;
  422. property MaterialLibrary: TGLAbstractMaterialLibrary read GetMaterialLibrary;
  423. published
  424. property Name: TGLLibMaterialName read FName write SetName;
  425. property Tag: Integer read FTag write FTag;
  426. end;
  427. (* Material in a material library.
  428. Introduces Texture transformations (offset and scale). Those transformations
  429. are available only for lib materials to minimize the memory cost of basic
  430. materials (which are used in almost all objects). *)
  431. TGLLibMaterial = class(TGLAbstractLibMaterial, IGLTextureNotifyAble)
  432. private
  433. FMaterial: TGLMaterial;
  434. FTextureOffset, FTextureScale: TGLCoordinates;
  435. FTextureRotate: Single;
  436. FTextureMatrixIsIdentity: Boolean;
  437. FTextureOverride: Boolean;
  438. FTextureMatrix: TGLMatrix;
  439. FTexture2Name: TGLLibMaterialName;
  440. FShader: TGLShader;
  441. libMatTexture2: TGLLibMaterial; // internal cache
  442. protected
  443. procedure Loaded; override;
  444. procedure SetMaterial(const val: TGLMaterial);
  445. procedure SetTextureOffset(const val: TGLCoordinates);
  446. procedure SetTextureScale(const val: TGLCoordinates);
  447. procedure SetTextureMatrix(const Value: TGLMatrix);
  448. procedure SetTexture2Name(const val: TGLLibMaterialName);
  449. procedure SetShader(const val: TGLShader);
  450. procedure SetTextureRotate(Value: Single);
  451. function StoreTextureRotate: Boolean;
  452. procedure CalculateTextureMatrix;
  453. procedure DestroyHandles;
  454. procedure DoOnTextureNeeded(Sender: TObject; var textureFileName: string);
  455. procedure OnNotifyChange(Sender: TObject);
  456. public
  457. constructor Create(ACollection: TCollection); override;
  458. destructor Destroy; override;
  459. procedure Assign(Source: TPersistent); override;
  460. procedure PrepareBuildList;
  461. procedure Apply(var ARci: TGLRenderContextInfo); override;
  462. { Restore non-standard material states that were altered}
  463. function UnApply(var ARci: TGLRenderContextInfo): Boolean; override;
  464. procedure NotifyUsersOfTexMapChange;
  465. property TextureMatrix: TGLMatrix read FTextureMatrix write SetTextureMatrix;
  466. property TextureMatrixIsIdentity: boolean read FTextureMatrixIsIdentity;
  467. procedure NotifyTexMapChange(Sender: TObject);
  468. function Blended: Boolean; override;
  469. published
  470. property Material: TGLMaterial read FMaterial write SetMaterial;
  471. // Texture offset in texture coordinates. The offset is applied after scaling
  472. property TextureOffset: TGLCoordinates read FTextureOffset write
  473. SetTextureOffset;
  474. (* Texture coordinates scaling.
  475. Scaling is applied <i>before</i> applying the offset, and is applied
  476. to the texture coordinates, meaning that a scale factor of (2, 2, 2)
  477. will make your texture look twice smaller *)
  478. property TextureScale: TGLCoordinates read FTextureScale write
  479. SetTextureScale;
  480. property TextureRotate: Single read FTextureRotate write
  481. SetTextureRotate stored StoreTextureRotate;
  482. (* Reference to the second texture.
  483. The referred LibMaterial *must* be in the same material library.
  484. Second textures are supported only through ARB multitexturing (ignored
  485. if not supported). *)
  486. property Texture2Name: TGLLibMaterialName read FTexture2Name write
  487. SetTexture2Name;
  488. {Optionnal shader for the material. }
  489. property Shader: TGLShader read FShader write SetShader;
  490. end;
  491. TGLAbstractLibMaterials = class(TOwnedCollection)
  492. protected
  493. procedure Loaded;
  494. function GetMaterial(const AName: TGLLibMaterialName): TGLAbstractLibMaterial; inline;
  495. public
  496. function MakeUniqueName(const nameRoot: TGLLibMaterialName):
  497. TGLLibMaterialName;
  498. end;
  499. // A collection of materials, mainly used in material libraries.
  500. TGLLibMaterials = class(TGLAbstractLibMaterials)
  501. protected
  502. procedure SetItems(index: Integer; const val: TGLLibMaterial);
  503. function GetItems(index: Integer): TGLLibMaterial;
  504. procedure DestroyHandles;
  505. public
  506. constructor Create(AOwner: TComponent);
  507. function Owner: TPersistent;
  508. function IndexOf(const Item: TGLLibMaterial): Integer;
  509. function Add: TGLLibMaterial;
  510. function FindItemID(ID: Integer): TGLLibMaterial;
  511. property Items[index: Integer]: TGLLibMaterial read GetItems write SetItems; default;
  512. function GetLibMaterialByName(const AName: TGLLibMaterialName): TGLLibMaterial;
  513. // Returns index of this Texture if it exists.
  514. function GetTextureIndex(const Texture: TGLTexture): Integer;
  515. // Returns index of this Material if it exists.
  516. function GetMaterialIndex(const Material: TGLMaterial): Integer;
  517. // Returns name of this Texture if it exists.
  518. function GetNameOfTexture(const Texture: TGLTexture): TGLLibMaterialName;
  519. // Returns name of this Material if it exists.
  520. function GetNameOfLibMaterial(const Material: TGLLibMaterial):
  521. TGLLibMaterialName;
  522. procedure PrepareBuildList;
  523. (* Deletes all the unused materials in the collection.
  524. A material is considered unused if no other material or updateable object references it.
  525. WARNING: For this to work, objects that use the textuere, have to REGISTER to the texture.*)
  526. procedure DeleteUnusedMaterials;
  527. end;
  528. TGLAbstractMaterialLibrary = class(TGLCadenceAbleComponent)
  529. protected
  530. FMaterials: TGLAbstractLibMaterials;
  531. FLastAppliedMaterial: TGLAbstractLibMaterial;
  532. FTexturePaths: string;
  533. FTexturePathList: TStringList;
  534. procedure SetTexturePaths(const val: string);
  535. property TexturePaths: string read FTexturePaths write SetTexturePaths;
  536. procedure Loaded; override;
  537. public
  538. procedure SetNamesToTStrings(AStrings: TStrings);
  539. (* Applies the material of given name.
  540. Returns False if the material could not be found. ake sure this
  541. call is balanced with a corresponding UnApplyMaterial (or an
  542. assertion will be triggered in the destructor).
  543. If a material is already applied, and has not yet been unapplied,
  544. an assertion will be triggered. *)
  545. function ApplyMaterial(const AName: string;
  546. var ARci: TGLRenderContextInfo): Boolean;
  547. (* Un-applies the last applied material.
  548. Use this function in conjunction with ApplyMaterial.
  549. If no material was applied, an assertion will be triggered. *)
  550. function UnApplyMaterial(var ARci: TGLRenderContextInfo): Boolean;
  551. end;
  552. (* Stores a set of materials, to be used and shared by scene objects.
  553. Use a material libraries for storing commonly used materials, it provides
  554. an efficient way to share texture and material data among many objects,
  555. thus reducing memory needs and rendering time.
  556. Materials in a material library also feature advanced control properties
  557. like texture coordinates transforms. *)
  558. TGLMaterialLibrary = class(TGLAbstractMaterialLibrary)
  559. private
  560. FDoNotClearMaterialsOnLoad: Boolean;
  561. FOnTextureNeeded: TGLTextureNeededEvent;
  562. protected
  563. function GetMaterials: TGLLibMaterials;
  564. procedure SetMaterials(const val: TGLLibMaterials);
  565. function StoreMaterials: Boolean;
  566. public
  567. constructor Create(AOwner: TComponent); override;
  568. destructor Destroy; override;
  569. procedure DestroyHandles;
  570. procedure WriteToFiler(writer: TGLVirtualWriter);
  571. procedure ReadFromFiler(reader: TGLVirtualReader);
  572. procedure SaveToStream(aStream: TStream); virtual;
  573. procedure LoadFromStream(aStream: TStream); virtual;
  574. procedure AddMaterialsFromStream(aStream: TStream);
  575. (* Save library content to a file.
  576. Recommended extension : .GLML
  577. Currently saves only texture, ambient, diffuse, emission
  578. and specular colors. *)
  579. procedure SaveToFile(const fileName: string);
  580. procedure LoadFromFile(const fileName: string);
  581. procedure AddMaterialsFromFile(const fileName: string);
  582. (* Add a "standard" texture material.
  583. "standard" means linear texturing mode with mipmaps and texture
  584. modulation mode with default-strength color components.
  585. If persistent is True, the image will be loaded persistently in memory
  586. (via a TGLPersistentImage), if false, it will be unloaded after upload
  587. to OpenGL (via TGLPicFileImage). *)
  588. function AddTextureMaterial(const materialName, fileName: string;
  589. persistent: Boolean = True): TGLLibMaterial; overload;
  590. // Add a "standard" texture material. TGLGraphic based variant.
  591. function AddTextureMaterial(const materialName: string; graphic:
  592. TGraphic): TGLLibMaterial; overload;
  593. // Returns libMaterial of given name if any exists.
  594. function LibMaterialByName(const AName: TGLLibMaterialName): TGLLibMaterial;
  595. // Returns Texture of given material's name if any exists.
  596. function TextureByName(const LibMatName: TGLLibMaterialName): TGLTexture;
  597. // Returns name of texture if any exists.
  598. function GetNameOfTexture(const Texture: TGLTexture): TGLLibMaterialName;
  599. // Returns name of Material if any exists.
  600. function GetNameOfLibMaterial(const LibMat: TGLLibMaterial): TGLLibMaterialName;
  601. published
  602. // The materials collection.
  603. property Materials: TGLLibMaterials read GetMaterials write SetMaterials stored
  604. StoreMaterials;
  605. (* This event is fired whenever a texture needs to be loaded from disk.
  606. The event is triggered before even attempting to load the texture,
  607. and before TexturePaths is used. *)
  608. property OnTextureNeeded: TGLTextureNeededEvent read FOnTextureNeeded write
  609. FOnTextureNeeded;
  610. (* Paths to lookup when attempting to load a texture.
  611. You can specify multiple paths when loading a texture, the separator
  612. being the semi-colon ';' character. Directories are looked up from
  613. first to last, the first file name match is used.
  614. The current directory is always implicit and checked last.
  615. Note that you can also use the OnTextureNeeded event to provide a
  616. filename. *)
  617. property TexturePaths;
  618. end;
  619. // ------------------------------------------------------------------------------
  620. implementation
  621. // ------------------------------------------------------------------------------
  622. procedure TGLShader.DoApply(var Rci: TGLRenderContextInfo; Sender: TObject);
  623. begin
  624. end;
  625. function TGLShader.DoUnApply(var Rci: TGLRenderContextInfo): Boolean;
  626. begin
  627. Result := True;
  628. end;
  629. procedure TGLAbstractLibMaterial.Loaded;
  630. begin
  631. end;
  632. procedure TGLAbstractLibMaterial.Apply(var ARci: TGLRenderContextInfo);
  633. begin
  634. end;
  635. function TGLAbstractLibMaterial.UnApply(var ARci: TGLRenderContextInfo): Boolean;
  636. begin
  637. Result := True;
  638. end;
  639. // ------------------
  640. // ------------------ TGLFaceProperties ------------------
  641. // ------------------
  642. constructor TGLFaceProperties.Create(aOwner: TPersistent);
  643. begin
  644. inherited;
  645. // OpenGL default colors
  646. FAmbient := TGLColor.CreateInitialized(Self, clrGray20);
  647. FDiffuse := TGLColor.CreateInitialized(Self, clrGray80);
  648. FEmission := TGLColor.Create(Self);
  649. FSpecular := TGLColor.Create(Self);
  650. FShininess := 0;
  651. end;
  652. destructor TGLFaceProperties.Destroy;
  653. begin
  654. FAmbient.Free;
  655. FDiffuse.Free;
  656. FEmission.Free;
  657. FSpecular.Free;
  658. inherited Destroy;
  659. end;
  660. procedure TGLFaceProperties.Apply(var rci: TGLRenderContextInfo;
  661. aFace: TGLCullFaceMode);
  662. begin
  663. with rci.GLStates do
  664. begin
  665. SetGLMaterialColors(aFace,
  666. Emission.Color, Ambient.Color, Diffuse.Color, Specular.Color, FShininess);
  667. end;
  668. end;
  669. procedure TGLFaceProperties.ApplyNoLighting(var rci: TGLRenderContextInfo;
  670. aFace: TGLCullFaceMode);
  671. begin
  672. gl.Color4fv(Diffuse.AsAddress);
  673. end;
  674. procedure TGLFaceProperties.Assign(Source: TPersistent);
  675. begin
  676. if Assigned(Source) and (Source is TGLFaceProperties) then
  677. begin
  678. FAmbient.DirectColor := TGLFaceProperties(Source).Ambient.Color;
  679. FDiffuse.DirectColor := TGLFaceProperties(Source).Diffuse.Color;
  680. FEmission.DirectColor := TGLFaceProperties(Source).Emission.Color;
  681. FSpecular.DirectColor := TGLFaceProperties(Source).Specular.Color;
  682. FShininess := TGLFaceProperties(Source).Shininess;
  683. NotifyChange(Self);
  684. end;
  685. end;
  686. procedure TGLFaceProperties.SetAmbient(AValue: TGLColor);
  687. begin
  688. FAmbient.DirectColor := AValue.Color;
  689. NotifyChange(Self);
  690. end;
  691. procedure TGLFaceProperties.SetDiffuse(AValue: TGLColor);
  692. begin
  693. FDiffuse.DirectColor := AValue.Color;
  694. NotifyChange(Self);
  695. end;
  696. procedure TGLFaceProperties.SetEmission(AValue: TGLColor);
  697. begin
  698. FEmission.DirectColor := AValue.Color;
  699. NotifyChange(Self);
  700. end;
  701. procedure TGLFaceProperties.SetSpecular(AValue: TGLColor);
  702. begin
  703. FSpecular.DirectColor := AValue.Color;
  704. NotifyChange(Self);
  705. end;
  706. procedure TGLFaceProperties.SetShininess(AValue: TGLShininess);
  707. begin
  708. if FShininess <> AValue then
  709. begin
  710. FShininess := AValue;
  711. NotifyChange(Self);
  712. end;
  713. end;
  714. // ------------------
  715. // ------------------ TGLDepthProperties ------------------
  716. // ------------------
  717. constructor TGLDepthProperties.Create(AOwner: TPersistent);
  718. begin
  719. inherited Create(AOwner);
  720. FDepthTest := True;
  721. FDepthWrite := True;
  722. FZNear := 0;
  723. FZFar := 1;
  724. FCompareFunc := cfLequal;
  725. FDepthClamp := False;
  726. end;
  727. procedure TGLDepthProperties.Apply(var rci: TGLRenderContextInfo);
  728. begin
  729. with rci.GLStates do
  730. begin
  731. if FDepthTest and rci.bufferDepthTest then
  732. Enable(stDepthTest)
  733. else
  734. Disable(stDepthTest);
  735. DepthWriteMask := FDepthWrite;
  736. DepthFunc := FCompareFunc;
  737. SetDepthRange(FZNear, FZFar);
  738. if GL.ARB_depth_clamp then
  739. if FDepthClamp then
  740. Enable(stDepthClamp)
  741. else
  742. Disable(stDepthClamp);
  743. end;
  744. end;
  745. procedure TGLDepthProperties.Assign(Source: TPersistent);
  746. begin
  747. if Assigned(Source) and (Source is TGLDepthProperties) then
  748. begin
  749. FDepthTest := TGLDepthProperties(Source).FDepthTest;
  750. FDepthWrite := TGLDepthProperties(Source).FDepthWrite;
  751. FZNear := TGLDepthProperties(Source).FZNear;
  752. FZFar := TGLDepthProperties(Source).FZFar;
  753. FCompareFunc := TGLDepthProperties(Source).FCompareFunc;
  754. NotifyChange(Self);
  755. end;
  756. end;
  757. procedure TGLDepthProperties.SetZNear(Value: Single);
  758. begin
  759. Value := ClampValue(Value, 0, 1);
  760. if Value <> FZNear then
  761. begin
  762. FZNear := Value;
  763. NotifyChange(Self);
  764. end;
  765. end;
  766. procedure TGLDepthProperties.SetZFar(Value: Single);
  767. begin
  768. Value := ClampValue(Value, 0, 1);
  769. if Value <> FZFar then
  770. begin
  771. FZFar := Value;
  772. NotifyChange(Self);
  773. end;
  774. end;
  775. procedure TGLDepthProperties.SetCompareFunc(Value: TGLDepthFunction);
  776. begin
  777. if Value <> FCompareFunc then
  778. begin
  779. FCompareFunc := Value;
  780. NotifyChange(Self);
  781. end;
  782. end;
  783. procedure TGLDepthProperties.SetDepthTest(Value: boolean);
  784. begin
  785. if Value <> FDepthTest then
  786. begin
  787. FDepthTest := Value;
  788. NotifyChange(Self);
  789. end;
  790. end;
  791. procedure TGLDepthProperties.SetDepthWrite(Value: boolean);
  792. begin
  793. if Value <> FDepthWrite then
  794. begin
  795. FDepthWrite := Value;
  796. NotifyChange(Self);
  797. end;
  798. end;
  799. procedure TGLDepthProperties.SetDepthClamp(Value: boolean);
  800. begin
  801. if Value <> FDepthClamp then
  802. begin
  803. FDepthClamp := Value;
  804. NotifyChange(Self);
  805. end;
  806. end;
  807. function TGLDepthProperties.StoreZNear: Boolean;
  808. begin
  809. Result := FZNear <> 0.0;
  810. end;
  811. function TGLDepthProperties.StoreZFar: Boolean;
  812. begin
  813. Result := FZFar <> 1.0;
  814. end;
  815. // ------------------
  816. // ------------------ TGLShader ------------------
  817. // ------------------
  818. constructor TGLShader.Create(AOwner: TComponent);
  819. begin
  820. FLibMatUsers := TList.Create;
  821. FVirtualHandle := TGLVirtualHandle.Create;
  822. FVirtualHandle.OnAllocate := OnVirtualHandleAllocate;
  823. FVirtualHandle.OnDestroy := OnVirtualHandleDestroy;
  824. FShaderStyle := ssLowLevel;
  825. FEnabled := True;
  826. FFailedInitAction := fiaRaiseStandardException;
  827. inherited;
  828. end;
  829. destructor TGLShader.Destroy;
  830. var
  831. i: Integer;
  832. list: TList;
  833. begin
  834. FVirtualHandle.DestroyHandle;
  835. FinalizeShader;
  836. inherited;
  837. list := FLibMatUsers;
  838. FLibMatUsers := nil;
  839. for i := list.Count - 1 downto 0 do
  840. TGLLibMaterial(list[i]).Shader := nil;
  841. list.Free;
  842. FVirtualHandle.Free;
  843. end;
  844. procedure TGLShader.NotifyChange(Sender: TObject);
  845. var
  846. i: Integer;
  847. begin
  848. if FUpdateCount = 0 then
  849. begin
  850. for i := FLibMatUsers.Count - 1 downto 0 do
  851. TGLLibMaterial(FLibMatUsers[i]).NotifyUsers;
  852. FinalizeShader;
  853. end;
  854. end;
  855. procedure TGLShader.BeginUpdate;
  856. begin
  857. Inc(FUpdateCount);
  858. end;
  859. procedure TGLShader.EndUpdate;
  860. begin
  861. Dec(FUpdateCount);
  862. if FUpdateCount = 0 then
  863. NotifyChange(Self);
  864. end;
  865. procedure TGLShader.DoInitialize(var rci: TGLRenderContextInfo; Sender: TObject);
  866. begin
  867. // nothing here
  868. end;
  869. procedure TGLShader.DoFinalize;
  870. begin
  871. // nothing here
  872. end;
  873. function TGLShader.GetShaderInitialized: Boolean;
  874. begin
  875. Result := (FVirtualHandle.Handle <> 0);
  876. end;
  877. procedure TGLShader.InitializeShader(var rci: TGLRenderContextInfo; Sender:
  878. TObject);
  879. begin
  880. FVirtualHandle.AllocateHandle;
  881. if FVirtualHandle.IsDataNeedUpdate then
  882. begin
  883. DoInitialize(rci, Sender);
  884. FVirtualHandle.NotifyDataUpdated;
  885. end;
  886. end;
  887. procedure TGLShader.FinalizeShader;
  888. begin
  889. FVirtualHandle.NotifyChangesOfData;
  890. DoFinalize;
  891. end;
  892. procedure TGLShader.Apply(var rci: TGLRenderContextInfo; Sender: TObject);
  893. begin
  894. {$IFNDEF USE_MULTITHREAD}
  895. Assert(not FShaderActive, 'Unbalanced shader application.');
  896. {$ENDIF}
  897. // Need to check it twice, because shader may refuse to initialize
  898. // and choose to disable itself during initialization.
  899. if FEnabled then
  900. if FVirtualHandle.IsDataNeedUpdate then
  901. InitializeShader(rci, Sender);
  902. if FEnabled then
  903. DoApply(rci, Sender);
  904. FShaderActive := True;
  905. end;
  906. function TGLShader.UnApply(var rci: TGLRenderContextInfo): Boolean;
  907. begin
  908. {$IFNDEF USE_MULTITHREAD}
  909. Assert(FShaderActive, 'Unbalanced shader application.');
  910. {$ENDIF}
  911. if Enabled then
  912. begin
  913. Result := DoUnApply(rci);
  914. if not Result then
  915. FShaderActive := False;
  916. end
  917. else
  918. begin
  919. FShaderActive := False;
  920. Result := False;
  921. end;
  922. end;
  923. procedure TGLShader.OnVirtualHandleDestroy(sender: TGLVirtualHandle; var handle:
  924. Cardinal);
  925. begin
  926. handle := 0;
  927. end;
  928. procedure TGLShader.OnVirtualHandleAllocate(sender: TGLVirtualHandle; var
  929. handle: Cardinal);
  930. begin
  931. handle := 1;
  932. end;
  933. procedure TGLShader.SetEnabled(val: Boolean);
  934. begin
  935. {$IFNDEF USE_MULTITHREAD}
  936. Assert(not FShaderActive, 'Shader is active.');
  937. {$ENDIF}
  938. if val <> FEnabled then
  939. begin
  940. FEnabled := val;
  941. NotifyChange(Self);
  942. end;
  943. end;
  944. procedure TGLShader.RegisterUser(libMat: TGLLibMaterial);
  945. var
  946. i: Integer;
  947. begin
  948. i := FLibMatUsers.IndexOf(libMat);
  949. if i < 0 then
  950. FLibMatUsers.Add(libMat);
  951. end;
  952. procedure TGLShader.UnRegisterUser(libMat: TGLLibMaterial);
  953. begin
  954. if Assigned(FLibMatUsers) then
  955. FLibMatUsers.Remove(libMat);
  956. end;
  957. procedure TGLShader.Assign(Source: TPersistent);
  958. begin
  959. if Source is TGLShader then
  960. begin
  961. FShaderStyle := TGLShader(Source).FShaderStyle;
  962. FFailedInitAction := TGLShader(Source).FFailedInitAction;
  963. Enabled := TGLShader(Source).FEnabled;
  964. end
  965. else
  966. inherited Assign(Source); //to the pit of doom ;)
  967. end;
  968. function TGLShader.ShaderSupported: Boolean;
  969. begin
  970. Result := True;
  971. end;
  972. procedure TGLShader.HandleFailedInitialization(const LastErrorMessage: string =
  973. '');
  974. begin
  975. case FailedInitAction of
  976. fiaSilentdisable: ; // Do nothing ;)
  977. fiaRaiseHandledException:
  978. try
  979. raise EGLShaderException.Create(GetStardardNotSupportedMessage);
  980. except
  981. end;
  982. fiaRaiseStandardException:
  983. raise EGLShaderException.Create(GetStardardNotSupportedMessage);
  984. fiaReRaiseException:
  985. begin
  986. if LastErrorMessage <> '' then
  987. raise EGLShaderException.Create(LastErrorMessage)
  988. else
  989. raise EGLShaderException.Create(GetStardardNotSupportedMessage)
  990. end;
  991. // fiaGenerateEvent:; // Do nothing. Event creation is left up to user shaders
  992. // // which may choose to override this procedure.
  993. else
  994. Assert(False, strErrorEx + strUnknownType);
  995. end;
  996. end;
  997. function TGLShader.GetStardardNotSupportedMessage: string;
  998. begin
  999. if Name <> '' then
  1000. Result := 'Your hardware/driver doesn''t support shader "' + Name + '"!'
  1001. else
  1002. Result := 'Your hardware/driver doesn''t support shader "' + ClassName +
  1003. '"!';
  1004. end;
  1005. // ------------------
  1006. //----------------- TGLMaterial -------------------------
  1007. // ------------------
  1008. constructor TGLMaterial.Create(AOwner: TPersistent);
  1009. begin
  1010. inherited;
  1011. FFrontProperties := TGLFaceProperties.Create(Self);
  1012. FBackProperties := TGLFaceProperties.Create(Self);
  1013. FTexture := nil; // AutoCreate
  1014. FFaceCulling := fcBufferDefault;
  1015. FPolygonMode := pmFill;
  1016. FBlendingParams := TGLBlendingParameters.Create(Self);
  1017. FDepthProperties := TGLDepthProperties.Create(Self)
  1018. end;
  1019. destructor TGLMaterial.Destroy;
  1020. begin
  1021. if Assigned(currentLibMaterial) then
  1022. currentLibMaterial.UnregisterUser(Self);
  1023. FBackProperties.Free;
  1024. FFrontProperties.Free;
  1025. FDepthProperties.Free;
  1026. FTexture.Free;
  1027. FTextureEx.Free;
  1028. FBlendingParams.Free;
  1029. inherited Destroy;
  1030. end;
  1031. function TGLMaterial.GetMaterialLibrary: TGLAbstractMaterialLibrary;
  1032. begin
  1033. Result := FMaterialLibrary;
  1034. end;
  1035. procedure TGLMaterial.SetBackProperties(Values: TGLFaceProperties);
  1036. begin
  1037. FBackProperties.Assign(Values);
  1038. NotifyChange(Self);
  1039. end;
  1040. function TGLMaterial.GetBackProperties: TGLFaceProperties;
  1041. begin
  1042. Result := FBackProperties;
  1043. end;
  1044. procedure TGLMaterial.SetFrontProperties(Values: TGLFaceProperties);
  1045. begin
  1046. FFrontProperties.Assign(Values);
  1047. NotifyChange(Self);
  1048. end;
  1049. procedure TGLMaterial.SetDepthProperties(Values: TGLDepthProperties);
  1050. begin
  1051. FDepthProperties.Assign(Values);
  1052. NotifyChange(Self);
  1053. end;
  1054. procedure TGLMaterial.SetBlendingMode(const val: TGLBlendingMode);
  1055. begin
  1056. if val <> FBlendingMode then
  1057. begin
  1058. FBlendingMode := val;
  1059. NotifyChange(Self);
  1060. end;
  1061. end;
  1062. procedure TGLMaterial.SetMaterialOptions(const val: TGLMaterialOptions);
  1063. begin
  1064. if val <> FMaterialOptions then
  1065. begin
  1066. FMaterialOptions := val;
  1067. NotifyChange(Self);
  1068. end;
  1069. end;
  1070. function TGLMaterial.GetTexture: TGLTexture;
  1071. begin
  1072. if not Assigned(FTexture) then
  1073. FTexture := TGLTexture.Create(Self);
  1074. Result := FTexture;
  1075. end;
  1076. procedure TGLMaterial.SetTexture(aTexture: TGLTexture);
  1077. begin
  1078. if Assigned(aTexture) then
  1079. Texture.Assign(ATexture)
  1080. else
  1081. FreeAndNil(FTexture);
  1082. end;
  1083. procedure TGLMaterial.SetFaceCulling(const val: TGLFaceCulling);
  1084. begin
  1085. if val <> FFaceCulling then
  1086. begin
  1087. FFaceCulling := val;
  1088. NotifyChange(Self);
  1089. end;
  1090. end;
  1091. procedure TGLMaterial.SetMaterialLibrary(const val: TGLAbstractMaterialLibrary);
  1092. begin
  1093. FMaterialLibrary := val;
  1094. SetLibMaterialName(LibMaterialName);
  1095. end;
  1096. procedure TGLMaterial.SetLibMaterialName(const val: TGLLibMaterialName);
  1097. var
  1098. oldLibrary: TGLMaterialLibrary;
  1099. function MaterialLoopFrom(curMat: TGLLibMaterial): Boolean;
  1100. var
  1101. loopCount: Integer;
  1102. begin
  1103. loopCount := 0;
  1104. while Assigned(curMat) and (loopCount < 16) do
  1105. begin
  1106. with curMat.Material do
  1107. begin
  1108. if Assigned(oldLibrary) then
  1109. curMat := oldLibrary.Materials.GetLibMaterialByName(LibMaterialName)
  1110. else
  1111. curMat := nil;
  1112. end;
  1113. Inc(loopCount)
  1114. end;
  1115. Result := (loopCount >= 16);
  1116. end;
  1117. var
  1118. newLibMaterial: TGLAbstractLibMaterial;
  1119. begin
  1120. // locate new libmaterial
  1121. if Assigned(FMaterialLibrary) then
  1122. newLibMaterial := FMaterialLibrary.FMaterials.GetMaterial(val)
  1123. else
  1124. newLibMaterial := nil;
  1125. // make sure new won't trigger an infinite loop
  1126. if FMaterialLibrary is TGLMaterialLibrary then
  1127. begin
  1128. oldLibrary := TGLMaterialLibrary(FMaterialLibrary);
  1129. if MaterialLoopFrom(TGLLibMaterial(newLibMaterial)) then
  1130. begin
  1131. if IsDesignTime then
  1132. InformationDlg(Format(strCyclicRefMat, [val]))
  1133. else
  1134. GLSLogger.LogErrorFmt(strCyclicRefMat, [val]);
  1135. exit;
  1136. end;
  1137. end;
  1138. FLibMaterialName := val;
  1139. // unregister if required
  1140. if newLibMaterial <> currentLibMaterial then
  1141. begin
  1142. // unregister from old
  1143. if Assigned(currentLibMaterial) then
  1144. currentLibMaterial.UnregisterUser(Self);
  1145. currentLibMaterial := newLibMaterial;
  1146. // register with new
  1147. if Assigned(currentLibMaterial) then
  1148. currentLibMaterial.RegisterUser(Self);
  1149. NotifyTexMapChange(Self);
  1150. end;
  1151. end;
  1152. function TGLMaterial.GetTextureEx: TGLTextureEx;
  1153. begin
  1154. if not Assigned(FTextureEx) then
  1155. FTextureEx := TGLTextureEx.Create(Self);
  1156. Result := FTextureEx;
  1157. end;
  1158. procedure TGLMaterial.SetTextureEx(const Value: TGLTextureEx);
  1159. begin
  1160. if Assigned(Value) or Assigned(FTextureEx) then
  1161. TextureEx.Assign(Value);
  1162. end;
  1163. function TGLMaterial.StoreTextureEx: Boolean;
  1164. begin
  1165. Result := (Assigned(FTextureEx) and (TextureEx.Count > 0));
  1166. end;
  1167. procedure TGLMaterial.SetBlendingParams(const Value: TGLBlendingParameters);
  1168. begin
  1169. FBlendingParams.Assign(Value);
  1170. NotifyChange(Self);
  1171. end;
  1172. procedure TGLMaterial.NotifyLibMaterialDestruction;
  1173. begin
  1174. FMaterialLibrary := nil;
  1175. FLibMaterialName := '';
  1176. currentLibMaterial := nil;
  1177. end;
  1178. procedure TGLMaterial.Loaded;
  1179. begin
  1180. inherited;
  1181. if Assigned(FTextureEx) then
  1182. TextureEx.Loaded;
  1183. end;
  1184. function TGLMaterial.StoreMaterialProps: Boolean;
  1185. begin
  1186. Result := not Assigned(currentLibMaterial);
  1187. end;
  1188. procedure TGLMaterial.PrepareBuildList;
  1189. begin
  1190. if Assigned(FTexture) and (not FTexture.Disabled) then
  1191. FTexture.PrepareBuildList;
  1192. end;
  1193. procedure TGLMaterial.Apply(var rci: TGLRenderContextInfo);
  1194. begin
  1195. if Assigned(currentLibMaterial) then
  1196. currentLibMaterial.Apply(rci)
  1197. else
  1198. with rci.GLStates do
  1199. begin
  1200. Disable(stColorMaterial);
  1201. PolygonMode := FPolygonMode;
  1202. if FPolygonMode = pmLines then
  1203. Disable(stLineStipple);
  1204. // Lighting switch
  1205. if (moNoLighting in MaterialOptions) or not rci.bufferLighting then
  1206. begin
  1207. Disable(stLighting);
  1208. FFrontProperties.ApplyNoLighting(rci, cmFront);
  1209. end
  1210. else
  1211. begin
  1212. Enable(stLighting);
  1213. FFrontProperties.Apply(rci, cmFront);
  1214. end;
  1215. // Apply FaceCulling and BackProperties (if needs be)
  1216. case FFaceCulling of
  1217. fcBufferDefault:
  1218. begin
  1219. if rci.bufferFaceCull then
  1220. Enable(stCullFace)
  1221. else
  1222. Disable(stCullFace);
  1223. BackProperties.Apply(rci, cmBack);
  1224. end;
  1225. fcCull: Enable(stCullFace);
  1226. fcNoCull:
  1227. begin
  1228. Disable(stCullFace);
  1229. BackProperties.Apply(rci, cmBack);
  1230. end;
  1231. end;
  1232. // note: Front + Back with different PolygonMode are no longer supported.
  1233. // Currently state cache just ignores back facing mode changes, changes to
  1234. // front affect both front + back PolygonMode
  1235. // Apply Blending mode
  1236. if not rci.ignoreBlendingRequests then
  1237. case FBlendingMode of
  1238. bmOpaque:
  1239. begin
  1240. Disable(stBlend);
  1241. Disable(stAlphaTest);
  1242. end;
  1243. bmTransparency:
  1244. begin
  1245. Enable(stBlend);
  1246. Enable(stAlphaTest);
  1247. SetBlendFunc(bfSrcAlpha, bfOneMinusSrcAlpha);
  1248. SetGLAlphaFunction(cfGreater, 0);
  1249. end;
  1250. bmAdditive:
  1251. begin
  1252. Enable(stBlend);
  1253. Enable(stAlphaTest);
  1254. SetBlendFunc(bfSrcAlpha, bfOne);
  1255. SetGLAlphaFunction(cfGreater, 0);
  1256. end;
  1257. bmAlphaTest50:
  1258. begin
  1259. Disable(stBlend);
  1260. Enable(stAlphaTest);
  1261. SetGLAlphaFunction(cfGEqual, 0.5);
  1262. end;
  1263. bmAlphaTest100:
  1264. begin
  1265. Disable(stBlend);
  1266. Enable(stAlphaTest);
  1267. SetGLAlphaFunction(cfGEqual, 1.0);
  1268. end;
  1269. bmModulate:
  1270. begin
  1271. Enable(stBlend);
  1272. Enable(stAlphaTest);
  1273. SetBlendFunc(bfDstColor, bfZero);
  1274. SetGLAlphaFunction(cfGreater, 0);
  1275. end;
  1276. bmCustom:
  1277. begin
  1278. FBlendingParams.Apply(rci);
  1279. end;
  1280. end;
  1281. // Fog switch
  1282. if (moIgnoreFog in MaterialOptions) or not rci.bufferFog then
  1283. Disable(stFog)
  1284. else
  1285. Enable(stFog);
  1286. if not Assigned(FTextureEx) then
  1287. begin
  1288. if Assigned(FTexture) then
  1289. FTexture.Apply(rci)
  1290. end
  1291. else
  1292. begin
  1293. if Assigned(FTexture) and not FTextureEx.IsTextureEnabled(0) then
  1294. FTexture.Apply(rci)
  1295. else if FTextureEx.Count > 0 then
  1296. FTextureEx.Apply(rci);
  1297. end;
  1298. // Apply depth properties
  1299. if not rci.ignoreDepthRequests then
  1300. FDepthProperties.Apply(rci);
  1301. end;
  1302. end;
  1303. function TGLMaterial.UnApply(var rci: TGLRenderContextInfo): Boolean;
  1304. begin
  1305. if Assigned(currentLibMaterial) then
  1306. Result := currentLibMaterial.UnApply(rci)
  1307. else
  1308. begin
  1309. if Assigned(FTexture) and (not FTexture.Disabled) and (not
  1310. FTextureEx.IsTextureEnabled(0)) then
  1311. FTexture.UnApply(rci)
  1312. else if Assigned(FTextureEx) then
  1313. FTextureEx.UnApply(rci);
  1314. Result := False;
  1315. end;
  1316. end;
  1317. procedure TGLMaterial.Assign(Source: TPersistent);
  1318. begin
  1319. if Assigned(Source) and (Source is TGLMaterial) then
  1320. begin
  1321. if Assigned(TGLMaterial(Source).FBackProperties) then
  1322. BackProperties.Assign(TGLMaterial(Source).BackProperties)
  1323. else
  1324. FreeAndNil(FBackProperties);
  1325. FFrontProperties.Assign(TGLMaterial(Source).FFrontProperties);
  1326. FPolygonMode := TGLMaterial(Source).FPolygonMode;
  1327. FBlendingMode := TGLMaterial(Source).FBlendingMode;
  1328. FMaterialOptions := TGLMaterial(Source).FMaterialOptions;
  1329. if Assigned(TGLMaterial(Source).FTexture) then
  1330. Texture.Assign(TGLMaterial(Source).FTexture)
  1331. else
  1332. FreeAndNil(FTexture);
  1333. FFaceCulling := TGLMaterial(Source).FFaceCulling;
  1334. FMaterialLibrary := TGLMaterial(Source).MaterialLibrary;
  1335. SetLibMaterialName(TGLMaterial(Source).LibMaterialName);
  1336. TextureEx.Assign(TGLMaterial(Source).TextureEx);
  1337. FDepthProperties.Assign(TGLMaterial(Source).DepthProperties);
  1338. NotifyChange(Self);
  1339. end
  1340. else
  1341. inherited;
  1342. end;
  1343. procedure TGLMaterial.NotifyChange(Sender: TObject);
  1344. var
  1345. intf: IGLNotifyAble;
  1346. begin
  1347. if Supports(Owner, IGLNotifyAble, intf) then
  1348. intf.NotifyChange(Self);
  1349. end;
  1350. procedure TGLMaterial.NotifyTexMapChange(Sender: TObject);
  1351. var
  1352. intf: IGLTextureNotifyAble;
  1353. begin
  1354. if Supports(Owner, IGLTextureNotifyAble, intf) then
  1355. intf.NotifyTexMapChange(Self)
  1356. else
  1357. NotifyChange(Self);
  1358. end;
  1359. procedure TGLMaterial.DestroyHandles;
  1360. begin
  1361. if Assigned(FTexture) then
  1362. FTexture.DestroyHandles;
  1363. end;
  1364. function TGLMaterial.Blended: Boolean;
  1365. begin
  1366. if Assigned(currentLibMaterial) then
  1367. begin
  1368. Result := currentLibMaterial.Blended
  1369. end
  1370. else
  1371. Result := not (BlendingMode in [bmOpaque, bmAlphaTest50, bmAlphaTest100, bmCustom]);
  1372. end;
  1373. function TGLMaterial.HasSecondaryTexture: Boolean;
  1374. begin
  1375. Result := Assigned(currentLibMaterial)
  1376. and (currentLibMaterial is TGLLibMaterial)
  1377. and Assigned(TGLLibMaterial(currentLibMaterial).libMatTexture2);
  1378. end;
  1379. function TGLMaterial.MaterialIsLinkedToLib: Boolean;
  1380. begin
  1381. Result := Assigned(currentLibMaterial);
  1382. end;
  1383. function TGLMaterial.GetActualPrimaryTexture: TGLTexture;
  1384. begin
  1385. if Assigned(currentLibMaterial) and (currentLibMaterial is TGLLibMaterial) then
  1386. Result := TGLLibMaterial(currentLibMaterial).Material.Texture
  1387. else
  1388. Result := Texture;
  1389. end;
  1390. function TGLMaterial.GetActualPrimaryMaterial: TGLMaterial;
  1391. begin
  1392. if Assigned(currentLibMaterial) and (currentLibMaterial is TGLLibMaterial) then
  1393. Result := TGLLibMaterial(currentLibMaterial).Material
  1394. else
  1395. Result := Self;
  1396. end;
  1397. function TGLMaterial.GetLibMaterial: TGLLibMaterial;
  1398. begin
  1399. if Assigned(currentLibMaterial) and (currentLibMaterial is TGLLibMaterial) then
  1400. Result := TGLLibMaterial(currentLibMaterial)
  1401. else
  1402. Result := nil;
  1403. end;
  1404. procedure TGLMaterial.QuickAssignMaterial(const MaterialLibrary:
  1405. TGLMaterialLibrary; const Material: TGLLibMaterial);
  1406. begin
  1407. FMaterialLibrary := MaterialLibrary;
  1408. FLibMaterialName := Material.FName;
  1409. if Material <> CurrentLibMaterial then
  1410. begin
  1411. // unregister from old
  1412. if Assigned(CurrentLibMaterial) then
  1413. currentLibMaterial.UnregisterUser(Self);
  1414. CurrentLibMaterial := Material;
  1415. // register with new
  1416. if Assigned(CurrentLibMaterial) then
  1417. CurrentLibMaterial.RegisterUser(Self);
  1418. NotifyTexMapChange(Self);
  1419. end;
  1420. end;
  1421. procedure TGLMaterial.SetPolygonMode(AValue: TGLPolygonMode);
  1422. begin
  1423. if AValue <> FPolygonMode then
  1424. begin
  1425. FPolygonMode := AValue;
  1426. NotifyChange(Self);
  1427. end;
  1428. end;
  1429. // ------------------
  1430. // ------------------ TGLAbstractLibMaterial ------------------
  1431. // ------------------
  1432. constructor TGLAbstractLibMaterial.Create(ACollection: TCollection);
  1433. begin
  1434. inherited Create(ACollection);
  1435. FUserList := TList.Create;
  1436. if Assigned(ACollection) then
  1437. begin
  1438. FName := TGLAbstractLibMaterials(ACollection).MakeUniqueName('LibMaterial');
  1439. FNameHashKey := ComputeNameHashKey(FName);
  1440. end;
  1441. end;
  1442. destructor TGLAbstractLibMaterial.Destroy;
  1443. begin
  1444. FUserList.Free;
  1445. inherited Destroy;
  1446. end;
  1447. procedure TGLAbstractLibMaterial.Assign(Source: TPersistent);
  1448. begin
  1449. if Source is TGLAbstractLibMaterial then
  1450. begin
  1451. FName :=
  1452. TGLLibMaterials(Collection).MakeUniqueName(TGLLibMaterial(Source).Name);
  1453. FNameHashKey := ComputeNameHashKey(FName);
  1454. end
  1455. else
  1456. inherited; // Raise AssignError
  1457. end;
  1458. function TGLAbstractLibMaterial.QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
  1459. begin
  1460. if GetInterface(IID, Obj) then
  1461. Result := S_OK
  1462. else
  1463. Result := E_NOINTERFACE;
  1464. end;
  1465. function TGLAbstractLibMaterial._AddRef: Integer; stdcall;
  1466. begin
  1467. Result := -1; //ignore
  1468. end;
  1469. function TGLAbstractLibMaterial._Release: Integer; stdcall;
  1470. begin
  1471. Result := -1; //ignore
  1472. end;
  1473. procedure TGLAbstractLibMaterial.RegisterUser(obj: TGLUpdateAbleObject);
  1474. begin
  1475. Assert(FUserList.IndexOf(obj) < 0);
  1476. FUserList.Add(obj);
  1477. end;
  1478. procedure TGLAbstractLibMaterial.UnRegisterUser(obj: TGLUpdateAbleObject);
  1479. begin
  1480. FUserList.Remove(obj);
  1481. end;
  1482. procedure TGLAbstractLibMaterial.RegisterUser(comp: TGLUpdateAbleComponent);
  1483. begin
  1484. Assert(FUserList.IndexOf(comp) < 0);
  1485. FUserList.Add(comp);
  1486. end;
  1487. procedure TGLAbstractLibMaterial.UnRegisterUser(comp: TGLUpdateAbleComponent);
  1488. begin
  1489. FUserList.Remove(comp);
  1490. end;
  1491. procedure TGLAbstractLibMaterial.RegisterUser(libMaterial: TGLLibMaterial);
  1492. begin
  1493. Assert(FUserList.IndexOf(libMaterial) < 0);
  1494. FUserList.Add(libMaterial);
  1495. end;
  1496. procedure TGLAbstractLibMaterial.UnRegisterUser(libMaterial: TGLLibMaterial);
  1497. begin
  1498. FUserList.Remove(libMaterial);
  1499. end;
  1500. procedure TGLAbstractLibMaterial.NotifyChange(Sender: TObject);
  1501. begin
  1502. NotifyUsers();
  1503. end;
  1504. procedure TGLAbstractLibMaterial.NotifyUsers;
  1505. var
  1506. i: Integer;
  1507. obj: TObject;
  1508. begin
  1509. if FNotifying then
  1510. Exit;
  1511. FNotifying := True;
  1512. try
  1513. for i := 0 to FUserList.Count - 1 do
  1514. begin
  1515. obj := TObject(FUserList[i]);
  1516. if obj is TGLUpdateAbleObject then
  1517. TGLUpdateAbleObject(FUserList[i]).NotifyChange(Self)
  1518. else if obj is TGLUpdateAbleComponent then
  1519. TGLUpdateAbleComponent(FUserList[i]).NotifyChange(Self)
  1520. else
  1521. begin
  1522. Assert(obj is TGLAbstractLibMaterial);
  1523. TGLAbstractLibMaterial(FUserList[i]).NotifyUsers;
  1524. end;
  1525. end;
  1526. finally
  1527. FNotifying := False;
  1528. end;
  1529. end;
  1530. function TGLAbstractLibMaterial.IsUsed: Boolean;
  1531. begin
  1532. Result := Assigned(Self) and (FUserlist.Count > 0);
  1533. end;
  1534. function TGLAbstractLibMaterial.GetDisplayName: string;
  1535. begin
  1536. Result := Name;
  1537. end;
  1538. function TGLAbstractLibMaterial.GetMaterialLibrary: TGLAbstractMaterialLibrary;
  1539. var
  1540. LOwner: TPersistent;
  1541. begin
  1542. Result := nil;
  1543. if Assigned(Collection) then
  1544. begin
  1545. LOwner := TGLAbstractLibMaterials(Collection).Owner;
  1546. if LOwner is TGLAbstractMaterialLibrary then
  1547. Result := TGLAbstractMaterialLibrary(LOwner);
  1548. end;
  1549. end;
  1550. function TGLAbstractLibMaterial.Blended: Boolean;
  1551. begin
  1552. Result := False;
  1553. end;
  1554. class function TGLAbstractLibMaterial.ComputeNameHashKey(const name: string): Integer;
  1555. var
  1556. i, n: Integer;
  1557. begin
  1558. n := Length(name);
  1559. Result := n;
  1560. for i := 1 to n do
  1561. Result := (Result shl 1) + Byte(name[i]);
  1562. end;
  1563. procedure TGLAbstractLibMaterial.SetName(const val: TGLLibMaterialName);
  1564. begin
  1565. if val <> FName then
  1566. begin
  1567. if not (csLoading in TComponent(Collection.Owner).ComponentState) then
  1568. begin
  1569. if TGLLibMaterials(Collection).GetLibMaterialByName(val) <> Self then
  1570. FName := TGLLibMaterials(Collection).MakeUniqueName(val)
  1571. else
  1572. FName := val;
  1573. end
  1574. else
  1575. FName := val;
  1576. FNameHashKey := ComputeNameHashKey(FName);
  1577. end;
  1578. end;
  1579. // ------------------
  1580. // ------------------ TGLLibMaterial ------------------
  1581. // ------------------
  1582. constructor TGLLibMaterial.Create(ACollection: TCollection);
  1583. begin
  1584. inherited Create(ACollection);
  1585. FMaterial := TGLMaterial.Create(Self);
  1586. FMaterial.Texture.OnTextureNeeded := DoOnTextureNeeded;
  1587. FTextureOffset := TGLCoordinates.CreateInitialized(Self, NullHmgVector, csPoint);
  1588. FTextureOffset.OnNotifyChange := OnNotifyChange;
  1589. FTextureScale := TGLCoordinates.CreateInitialized(Self, XYZHmgVector, csPoint);
  1590. FTextureScale.OnNotifyChange := OnNotifyChange;
  1591. FTextureRotate := 0;
  1592. FTextureOverride := False;
  1593. FTextureMatrixIsIdentity := True;
  1594. end;
  1595. destructor TGLLibMaterial.Destroy;
  1596. var
  1597. i: Integer;
  1598. matObj: TObject;
  1599. begin
  1600. Shader := nil; // drop dependency
  1601. Texture2Name := ''; // drop dependency
  1602. for i := 0 to FUserList.Count - 1 do
  1603. begin
  1604. matObj := TObject(FUserList[i]);
  1605. if matObj is TGLMaterial then
  1606. TGLMaterial(matObj).NotifyLibMaterialDestruction
  1607. else if matObj is TGLLibMaterial then
  1608. begin
  1609. TGLLibMaterial(matObj).libMatTexture2 := nil;
  1610. TGLLibMaterial(matObj).FTexture2Name := '';
  1611. end;
  1612. end;
  1613. FMaterial.Free;
  1614. FTextureOffset.Free;
  1615. FTextureScale.Free;
  1616. inherited;
  1617. end;
  1618. procedure TGLLibMaterial.Assign(Source: TPersistent);
  1619. begin
  1620. if Source is TGLLibMaterial then
  1621. begin
  1622. FMaterial.Assign(TGLLibMaterial(Source).Material);
  1623. FTextureOffset.Assign(TGLLibMaterial(Source).TextureOffset);
  1624. FTextureScale.Assign(TGLLibMaterial(Source).TextureScale);
  1625. FTextureRotate := TGLLibMaterial(Source).TextureRotate;
  1626. TextureMatrix := TGLLibMaterial(Source).TextureMatrix;
  1627. FTextureOverride := TGLLibMaterial(Source).FTextureOverride;
  1628. FTexture2Name := TGLLibMaterial(Source).Texture2Name;
  1629. FShader := TGLLibMaterial(Source).Shader;
  1630. end;
  1631. inherited;
  1632. end;
  1633. function TGLLibMaterial.Blended: Boolean;
  1634. begin
  1635. Result := Material.Blended;
  1636. end;
  1637. procedure TGLLibMaterial.PrepareBuildList;
  1638. begin
  1639. if Assigned(Self) then
  1640. Material.PrepareBuildList;
  1641. end;
  1642. procedure TGLLibMaterial.Apply(var ARci: TGLRenderContextInfo);
  1643. var
  1644. multitextured: Boolean;
  1645. begin
  1646. xgl.BeginUpdate;
  1647. if Assigned(FShader) then
  1648. begin
  1649. case Shader.ShaderStyle of
  1650. ssHighLevel: Shader.Apply(ARci, Self);
  1651. ssReplace:
  1652. begin
  1653. Shader.Apply(ARci, Self);
  1654. Exit;
  1655. end;
  1656. end;
  1657. end
  1658. else
  1659. ARci.GLStates.CurrentProgram := 0;
  1660. if (Texture2Name <> '') and GL.ARB_multitexture and (not
  1661. xgl.SecondTextureUnitForbidden) then
  1662. begin
  1663. if not Assigned(libMatTexture2) then
  1664. begin
  1665. libMatTexture2 :=
  1666. TGLLibMaterials(Collection).GetLibMaterialByName(Texture2Name);
  1667. if Assigned(libMatTexture2) then
  1668. libMatTexture2.RegisterUser(Self)
  1669. else
  1670. FTexture2Name := '';
  1671. end;
  1672. multitextured := Assigned(libMatTexture2)
  1673. and (not libMatTexture2.Material.Texture.Disabled);
  1674. end
  1675. else
  1676. multitextured := False;
  1677. if not multitextured then
  1678. begin
  1679. // no multitexturing ("standard" mode)
  1680. if not FTextureMatrixIsIdentity then
  1681. ARci.GLStates.SetGLTextureMatrix(FTextureMatrix);
  1682. Material.Apply(ARci);
  1683. end
  1684. else
  1685. begin
  1686. // multitexturing is ON
  1687. if not FTextureMatrixIsIdentity then
  1688. ARci.GLStates.SetGLTextureMatrix(FTextureMatrix);
  1689. Material.Apply(ARci);
  1690. if not libMatTexture2.FTextureMatrixIsIdentity then
  1691. libMatTexture2.Material.Texture.ApplyAsTexture2(ARci,
  1692. @libMatTexture2.FTextureMatrix.V[0].X)
  1693. else
  1694. libMatTexture2.Material.Texture.ApplyAsTexture2(ARci);
  1695. if (not Material.Texture.Disabled) and (Material.Texture.MappingMode =
  1696. tmmUser) then
  1697. if libMatTexture2.Material.Texture.MappingMode = tmmUser then
  1698. xgl.MapTexCoordToDual
  1699. else
  1700. xgl.MapTexCoordToMain
  1701. else if libMatTexture2.Material.Texture.MappingMode = tmmUser then
  1702. xgl.MapTexCoordToSecond
  1703. else
  1704. xgl.MapTexCoordToMain;
  1705. end;
  1706. if Assigned(FShader) then
  1707. begin
  1708. case Shader.ShaderStyle of
  1709. ssLowLevel: Shader.Apply(ARci, Self);
  1710. end;
  1711. end;
  1712. xgl.EndUpdate;
  1713. end;
  1714. function TGLLibMaterial.UnApply(var ARci: TGLRenderContextInfo): Boolean;
  1715. begin
  1716. Result := False;
  1717. if Assigned(FShader) then
  1718. begin
  1719. case Shader.ShaderStyle of
  1720. ssLowLevel: Result := Shader.UnApply(ARci);
  1721. ssReplace:
  1722. begin
  1723. Result := Shader.UnApply(ARci);
  1724. Exit;
  1725. end;
  1726. end;
  1727. end;
  1728. if not Result then
  1729. begin
  1730. if Assigned(libMatTexture2) and GL.ARB_multitexture and (not
  1731. xgl.SecondTextureUnitForbidden) then
  1732. begin
  1733. libMatTexture2.Material.Texture.UnApplyAsTexture2(ARci, (not
  1734. libMatTexture2.TextureMatrixIsIdentity));
  1735. xgl.MapTexCoordToMain;
  1736. end;
  1737. Material.UnApply(ARci);
  1738. if not Material.Texture.Disabled then
  1739. if not FTextureMatrixIsIdentity then
  1740. ARci.GLStates.ResetGLTextureMatrix;
  1741. if Assigned(FShader) then
  1742. begin
  1743. case Shader.ShaderStyle of
  1744. ssHighLevel: Result := Shader.UnApply(ARci);
  1745. end;
  1746. end;
  1747. end;
  1748. end;
  1749. procedure TGLLibMaterial.NotifyTexMapChange(Sender: TObject);
  1750. begin
  1751. NotifyUsersOfTexMapChange();
  1752. end;
  1753. procedure TGLLibMaterial.NotifyUsersOfTexMapChange;
  1754. var
  1755. i: Integer;
  1756. obj: TObject;
  1757. begin
  1758. if FNotifying then
  1759. Exit;
  1760. FNotifying := True;
  1761. try
  1762. for i := 0 to FUserList.Count - 1 do
  1763. begin
  1764. obj := TObject(FUserList[i]);
  1765. if obj is TGLMaterial then
  1766. TGLMaterial(FUserList[i]).NotifyTexMapChange(Self)
  1767. else if obj is TGLLibMaterial then
  1768. TGLLibMaterial(FUserList[i]).NotifyUsersOfTexMapChange
  1769. else if obj is TGLUpdateAbleObject then
  1770. TGLUpdateAbleObject(FUserList[i]).NotifyChange(Self)
  1771. else if obj is TGLUpdateAbleComponent then
  1772. TGLUpdateAbleComponent(FUserList[i]).NotifyChange(Self);
  1773. end;
  1774. finally
  1775. FNotifying := False;
  1776. end;
  1777. end;
  1778. procedure TGLLibMaterial.Loaded;
  1779. begin
  1780. CalculateTextureMatrix;
  1781. Material.Loaded;
  1782. end;
  1783. procedure TGLLibMaterial.SetMaterial(const val: TGLMaterial);
  1784. begin
  1785. FMaterial.Assign(val);
  1786. end;
  1787. procedure TGLLibMaterial.SetTextureOffset(const val: TGLCoordinates);
  1788. begin
  1789. FTextureOffset.AsVector := val.AsVector;
  1790. CalculateTextureMatrix;
  1791. end;
  1792. procedure TGLLibMaterial.SetTextureScale(const val: TGLCoordinates);
  1793. begin
  1794. FTextureScale.AsVector := val.AsVector;
  1795. CalculateTextureMatrix;
  1796. end;
  1797. procedure TGLLibMaterial.SetTextureMatrix(const Value: TGLMatrix);
  1798. begin
  1799. FTextureMatrixIsIdentity := CompareMem(@Value.V[0], @IdentityHmgMatrix.V[0], SizeOf(TGLMatrix));
  1800. FTextureMatrix := Value;
  1801. FTextureOverride := True;
  1802. NotifyUsers;
  1803. end;
  1804. procedure TGLLibMaterial.SetTextureRotate(Value: Single);
  1805. begin
  1806. if Value <> FTextureRotate then
  1807. begin
  1808. FTextureRotate := Value;
  1809. CalculateTextureMatrix;
  1810. end;
  1811. end;
  1812. function TGLLibMaterial.StoreTextureRotate: Boolean;
  1813. begin
  1814. Result := Abs(FTextureRotate) > EPSILON;
  1815. end;
  1816. procedure TGLLibMaterial.SetTexture2Name(const val: TGLLibMaterialName);
  1817. begin
  1818. if val <> Texture2Name then
  1819. begin
  1820. if Assigned(libMatTexture2) then
  1821. begin
  1822. libMatTexture2.UnregisterUser(Self);
  1823. libMatTexture2 := nil;
  1824. end;
  1825. FTexture2Name := val;
  1826. NotifyUsers;
  1827. end;
  1828. end;
  1829. procedure TGLLibMaterial.SetShader(const val: TGLShader);
  1830. begin
  1831. if val <> FShader then
  1832. begin
  1833. if Assigned(FShader) then
  1834. FShader.UnRegisterUser(Self);
  1835. FShader := val;
  1836. if Assigned(FShader) then
  1837. FShader.RegisterUser(Self);
  1838. NotifyUsers;
  1839. end;
  1840. end;
  1841. procedure TGLLibMaterial.CalculateTextureMatrix;
  1842. begin
  1843. if TextureOffset.Equals(NullHmgVector)
  1844. and TextureScale.Equals(XYZHmgVector)
  1845. and not StoreTextureRotate then
  1846. FTextureMatrixIsIdentity := True
  1847. else
  1848. begin
  1849. FTextureMatrixIsIdentity := False;
  1850. FTextureMatrix := CreateScaleAndTranslationMatrix(
  1851. TextureScale.AsVector,
  1852. TextureOffset.AsVector);
  1853. if StoreTextureRotate then
  1854. FTextureMatrix := MatrixMultiply(FTextureMatrix,
  1855. CreateRotationMatrixZ(DegToRadian(FTextureRotate)));
  1856. end;
  1857. FTextureOverride := False;
  1858. NotifyUsers;
  1859. end;
  1860. procedure TGLLibMaterial.DestroyHandles;
  1861. var
  1862. libMat: TGLLibMaterial;
  1863. begin
  1864. FMaterial.DestroyHandles;
  1865. if FTexture2Name <> '' then
  1866. begin
  1867. libMat := TGLLibMaterials(Collection).GetLibMaterialByName(Texture2Name);
  1868. if Assigned(libMat) then
  1869. libMat.DestroyHandles;
  1870. end;
  1871. end;
  1872. procedure TGLLibMaterial.OnNotifyChange(Sender: TObject);
  1873. begin
  1874. CalculateTextureMatrix;
  1875. end;
  1876. procedure TGLLibMaterial.DoOnTextureNeeded(Sender: TObject; var textureFileName:
  1877. string);
  1878. var
  1879. mLib: TGLMaterialLibrary;
  1880. i: Integer;
  1881. tryName: string;
  1882. begin
  1883. if not Assigned(Collection) then
  1884. exit;
  1885. mLib := TGLMaterialLibrary((Collection as TGLLibMaterials).GetOwner);
  1886. with mLib do
  1887. if Assigned(FOnTextureNeeded) then
  1888. FOnTextureNeeded(mLib, textureFileName);
  1889. // if a ':' is present, or if it starts with a '\', consider it as an absolute path
  1890. if (Pos(':', textureFileName) > 0) or (Copy(textureFileName, 1, 1) = PathDelim)
  1891. then
  1892. Exit;
  1893. // ok, not an absolute path, try given paths
  1894. with mLib do
  1895. begin
  1896. if FTexturePathList <> nil then
  1897. for i := 0 to FTexturePathList.Count - 1 do
  1898. begin
  1899. tryName := IncludeTrailingPathDelimiter(FTexturePathList[i]) +
  1900. textureFileName;
  1901. if (Assigned(vAFIOCreateFileStream) and FileStreamExists(tryName)) or
  1902. FileExists(tryName) then
  1903. begin
  1904. textureFileName := tryName;
  1905. Break;
  1906. end;
  1907. end;
  1908. end;
  1909. end;
  1910. // ------------------
  1911. // ------------------ TGLLibMaterials ------------------
  1912. // ------------------
  1913. function TGLAbstractLibMaterials.GetMaterial(const AName: TGLLibMaterialName):
  1914. TGLAbstractLibMaterial;
  1915. var
  1916. i, hk: Integer;
  1917. lm: TGLAbstractLibMaterial;
  1918. begin
  1919. hk := TGLAbstractLibMaterial.ComputeNameHashKey(AName);
  1920. for i := 0 to Count - 1 do
  1921. begin
  1922. lm := TGLAbstractLibMaterial(inherited Items[i]);
  1923. if (lm.NameHashKey = hk) and (lm.Name = AName) then
  1924. begin
  1925. Result := lm;
  1926. Exit;
  1927. end;
  1928. end;
  1929. Result := nil;
  1930. end;
  1931. procedure TGLAbstractLibMaterials.Loaded;
  1932. var
  1933. I: Integer;
  1934. begin
  1935. for I := Count - 1 downto 0 do
  1936. TGLAbstractLibMaterial(Items[I]).Loaded;
  1937. end;
  1938. function TGLAbstractLibMaterials.MakeUniqueName(const nameRoot: TGLLibMaterialName):
  1939. TGLLibMaterialName;
  1940. var
  1941. i: Integer;
  1942. begin
  1943. Result := nameRoot;
  1944. i := 1;
  1945. while GetMaterial(Result) <> nil do
  1946. begin
  1947. Result := nameRoot + IntToStr(i);
  1948. Inc(i);
  1949. end;
  1950. end;
  1951. constructor TGLLibMaterials.Create(AOwner: TComponent);
  1952. begin
  1953. inherited Create(AOwner, TGLLibMaterial);
  1954. end;
  1955. procedure TGLLibMaterials.SetItems(index: Integer; const val: TGLLibMaterial);
  1956. begin
  1957. inherited Items[index] := val;
  1958. end;
  1959. function TGLLibMaterials.GetItems(index: Integer): TGLLibMaterial;
  1960. begin
  1961. Result := TGLLibMaterial(inherited Items[index]);
  1962. end;
  1963. procedure TGLLibMaterials.DestroyHandles;
  1964. var
  1965. i: Integer;
  1966. begin
  1967. for i := 0 to Count - 1 do
  1968. Items[i].DestroyHandles;
  1969. end;
  1970. function TGLLibMaterials.Owner: TPersistent;
  1971. begin
  1972. Result := GetOwner;
  1973. end;
  1974. function TGLLibMaterials.Add: TGLLibMaterial;
  1975. begin
  1976. Result := (inherited Add) as TGLLibMaterial;
  1977. end;
  1978. function TGLLibMaterials.FindItemID(ID: Integer): TGLLibMaterial;
  1979. begin
  1980. Result := (inherited FindItemID(ID)) as TGLLibMaterial;
  1981. end;
  1982. function TGLLibMaterials.GetLibMaterialByName(const AName: TGLLibMaterialName):
  1983. TGLLibMaterial;
  1984. var
  1985. LMaterial: TGLAbstractLibMaterial;
  1986. begin
  1987. LMaterial := GetMaterial(AName);
  1988. if Assigned(LMaterial) and (LMaterial is TGLLibMaterial) then
  1989. Result := TGLLibMaterial(LMaterial)
  1990. else
  1991. Result := nil;
  1992. end;
  1993. function TGLLibMaterials.GetTextureIndex(const Texture: TGLTexture): Integer;
  1994. var
  1995. I: Integer;
  1996. begin
  1997. if Count <> 0 then
  1998. for I := 0 to Count - 1 do
  1999. if GetItems(I).Material.Texture = Texture then
  2000. begin
  2001. Result := I;
  2002. Exit;
  2003. end;
  2004. Result := -1;
  2005. end;
  2006. function TGLLibMaterials.GetMaterialIndex(const Material: TGLMaterial): Integer;
  2007. var
  2008. I: Integer;
  2009. begin
  2010. if Count <> 0 then
  2011. for I := 0 to Count - 1 do
  2012. if GetItems(I).Material = Material then
  2013. begin
  2014. Result := I;
  2015. Exit;
  2016. end;
  2017. Result := -1;
  2018. end;
  2019. function TGLLibMaterials.GetNameOfTexture(const Texture: TGLTexture):
  2020. TGLLibMaterialName;
  2021. var
  2022. MatIndex: Integer;
  2023. begin
  2024. MatIndex := GetTextureIndex(Texture);
  2025. if MatIndex <> -1 then
  2026. Result := GetItems(MatIndex).Name
  2027. else
  2028. Result := '';
  2029. end;
  2030. function TGLLibMaterials.GetNameOfLibMaterial(const Material: TGLLibMaterial):
  2031. TGLLibMaterialName;
  2032. var
  2033. MatIndex: Integer;
  2034. begin
  2035. MatIndex := IndexOf(Material);
  2036. if MatIndex <> -1 then
  2037. Result := GetItems(MatIndex).Name
  2038. else
  2039. Result := '';
  2040. end;
  2041. function TGLLibMaterials.IndexOf(const Item: TGLLibMaterial): Integer;
  2042. var
  2043. I: Integer;
  2044. begin
  2045. Result := -1;
  2046. if Count <> 0 then
  2047. for I := 0 to Count - 1 do
  2048. if GetItems(I) = Item then
  2049. begin
  2050. Result := I;
  2051. Exit;
  2052. end;
  2053. end;
  2054. procedure TGLLibMaterials.PrepareBuildList;
  2055. var
  2056. i: Integer;
  2057. begin
  2058. for i := 0 to Count - 1 do
  2059. TGLLibMaterial(inherited Items[i]).PrepareBuildList;
  2060. end;
  2061. procedure TGLLibMaterials.DeleteUnusedMaterials;
  2062. var
  2063. i: Integer;
  2064. gotNone: Boolean;
  2065. begin
  2066. BeginUpdate;
  2067. repeat
  2068. gotNone := True;
  2069. for i := Count - 1 downto 0 do
  2070. begin
  2071. if TGLLibMaterial(inherited Items[i]).FUserList.Count = 0 then
  2072. begin
  2073. TGLLibMaterial(inherited Items[i]).Free;
  2074. gotNone := False;
  2075. end;
  2076. end;
  2077. until gotNone;
  2078. EndUpdate;
  2079. end;
  2080. //--------------------------------------------------------
  2081. // ---------------------TGLAbstractMaterialLibrary
  2082. //--------------------------------------------------------
  2083. procedure TGLAbstractMaterialLibrary.SetTexturePaths(const val: string);
  2084. var
  2085. i, lp: Integer;
  2086. procedure AddCurrent;
  2087. var
  2088. buf: string;
  2089. begin
  2090. buf := Trim(Copy(val, lp + 1, i - lp - 1));
  2091. if Length(buf) > 0 then
  2092. begin
  2093. // make sure '\' is the terminator
  2094. buf := IncludeTrailingPathDelimiter(buf);
  2095. FTexturePathList.Add(buf);
  2096. end;
  2097. end;
  2098. begin
  2099. FTexturePathList.Free;
  2100. FTexturePathList := nil;
  2101. FTexturePaths := val;
  2102. if val <> '' then
  2103. begin
  2104. FTexturePathList := TStringList.Create;
  2105. lp := 0;
  2106. for i := 1 to Length(val) do
  2107. begin
  2108. if val[i] = ';' then
  2109. begin
  2110. AddCurrent;
  2111. lp := i;
  2112. end;
  2113. end;
  2114. i := Length(val) + 1;
  2115. AddCurrent;
  2116. end;
  2117. end;
  2118. function TGLAbstractMaterialLibrary.ApplyMaterial(const AName: string;
  2119. var ARci: TGLRenderContextInfo): Boolean;
  2120. begin
  2121. FLastAppliedMaterial := FMaterials.GetMaterial(AName);
  2122. Result := Assigned(FLastAppliedMaterial);
  2123. if Result then
  2124. FLastAppliedMaterial.Apply(ARci);
  2125. end;
  2126. function TGLAbstractMaterialLibrary.UnApplyMaterial(
  2127. var ARci: TGLRenderContextInfo): Boolean;
  2128. begin
  2129. if Assigned(FLastAppliedMaterial) then
  2130. begin
  2131. Result := FLastAppliedMaterial.UnApply(ARci);
  2132. if not Result then
  2133. FLastAppliedMaterial := nil;
  2134. end
  2135. else
  2136. Result := False;
  2137. end;
  2138. procedure TGLAbstractMaterialLibrary.SetNamesToTStrings(AStrings: TStrings);
  2139. var
  2140. i: Integer;
  2141. lm: TGLAbstractLibMaterial;
  2142. begin
  2143. with AStrings do
  2144. begin
  2145. BeginUpdate;
  2146. Clear;
  2147. for i := 0 to FMaterials.Count - 1 do
  2148. begin
  2149. lm := TGLAbstractLibMaterial(FMaterials.Items[i]);
  2150. AddObject(lm.Name, lm);
  2151. end;
  2152. EndUpdate;
  2153. end;
  2154. end;
  2155. procedure TGLAbstractMaterialLibrary.Loaded;
  2156. begin
  2157. inherited;
  2158. FMaterials.Loaded;
  2159. end;
  2160. // ------------------
  2161. // ------------------ TGLMaterialLibrary ------------------
  2162. // ------------------
  2163. constructor TGLMaterialLibrary.Create(AOwner: TComponent);
  2164. begin
  2165. inherited;
  2166. FMaterials := TGLLibMaterials.Create(Self);
  2167. end;
  2168. destructor TGLMaterialLibrary.Destroy;
  2169. begin
  2170. Assert(FLastAppliedMaterial = nil, 'Unbalanced material application');
  2171. FTexturePathList.Free;
  2172. FMaterials.Free;
  2173. FMaterials := nil;
  2174. inherited;
  2175. end;
  2176. procedure TGLMaterialLibrary.DestroyHandles;
  2177. begin
  2178. if Assigned(FMaterials) then
  2179. Materials.DestroyHandles;
  2180. end;
  2181. procedure TGLMaterialLibrary.SetMaterials(const val: TGLLibMaterials);
  2182. begin
  2183. FMaterials.Assign(val);
  2184. end;
  2185. function TGLMaterialLibrary.StoreMaterials: Boolean;
  2186. begin
  2187. Result := (FMaterials.Count > 0);
  2188. end;
  2189. procedure TGLMaterialLibrary.WriteToFiler(writer: TGLVirtualWriter);
  2190. var
  2191. i, j: Integer;
  2192. libMat: TGLLibMaterial;
  2193. tex: TGLTexture;
  2194. img: TGLTextureImage;
  2195. pim: TGLPersistentImage;
  2196. ss: TStringStream;
  2197. bmp: TBitmap;
  2198. texExItem: TGLTextureExItem;
  2199. begin
  2200. with writer do
  2201. begin
  2202. WriteInteger(4); // archive version 0, texture persistence only
  2203. // archive version 1, libmat properties
  2204. // archive version 2, Material.TextureEx properties
  2205. // archive version 3, Material.Texture properties
  2206. // archive version 4, Material.TextureRotate
  2207. WriteInteger(Materials.Count);
  2208. for i := 0 to Materials.Count - 1 do
  2209. begin
  2210. // version 0
  2211. libMat := Materials[i];
  2212. WriteString(libMat.Name);
  2213. tex := libMat.Material.Texture;
  2214. img := tex.Image;
  2215. pim := TGLPersistentImage(img);
  2216. if tex.Enabled and (img is TGLPersistentImage) and (pim.Picture.Graphic <>
  2217. nil) then
  2218. begin
  2219. WriteBoolean(true);
  2220. ss := TStringStream.Create('');
  2221. try
  2222. bmp := TBitmap.Create;
  2223. try
  2224. bmp.Assign(pim.Picture.Graphic);
  2225. bmp.SaveToStream(ss);
  2226. finally
  2227. bmp.Free;
  2228. end;
  2229. WriteString(ss.DataString);
  2230. finally
  2231. ss.Free;
  2232. end;
  2233. // version 3
  2234. with libMat.Material.Texture do
  2235. begin
  2236. Write(BorderColor.AsAddress^, SizeOf(Single) * 4);
  2237. WriteInteger(Integer(Compression));
  2238. WriteInteger(Integer(DepthTextureMode));
  2239. Write(EnvColor.AsAddress^, SizeOf(Single) * 4);
  2240. WriteInteger(Integer(FilteringQuality));
  2241. WriteInteger(Integer(ImageAlpha));
  2242. WriteFloat(ImageBrightness);
  2243. WriteFloat(ImageGamma);
  2244. WriteInteger(Integer(MagFilter));
  2245. WriteInteger(Integer(MappingMode));
  2246. Write(MappingSCoordinates.AsAddress^, SizeOf(Single) * 4);
  2247. Write(MappingTCoordinates.AsAddress^, SizeOf(Single) * 4);
  2248. Write(MappingRCoordinates.AsAddress^, SizeOf(Single) * 4);
  2249. Write(MappingQCoordinates.AsAddress^, SizeOf(Single) * 4);
  2250. WriteInteger(Integer(MinFilter));
  2251. WriteFloat(NormalMapScale);
  2252. WriteInteger(Integer(TextureCompareFunc));
  2253. WriteInteger(Integer(TextureCompareMode));
  2254. WriteInteger(Integer(TextureFormat));
  2255. WriteInteger(Integer(TextureMode));
  2256. WriteInteger(Integer(TextureWrap));
  2257. WriteInteger(Integer(TextureWrapR));
  2258. WriteInteger(Integer(TextureWrapS));
  2259. WriteInteger(Integer(TextureWrapT));
  2260. end;
  2261. // version 3 end
  2262. end
  2263. else
  2264. WriteBoolean(False);
  2265. with libMat.Material.FrontProperties do
  2266. begin
  2267. Write(Ambient.AsAddress^, SizeOf(Single) * 3);
  2268. Write(Diffuse.AsAddress^, SizeOf(Single) * 4);
  2269. Write(Emission.AsAddress^, SizeOf(Single) * 3);
  2270. Write(Specular.AsAddress^, SizeOf(Single) * 3);
  2271. end;
  2272. //version 1
  2273. with libMat.Material.FrontProperties do
  2274. begin
  2275. Write(FShininess, 1);
  2276. WriteInteger(Integer(libMat.Material.PolygonMode));
  2277. end;
  2278. with libMat.Material.BackProperties do
  2279. begin
  2280. Write(Ambient.AsAddress^, SizeOf(Single) * 3);
  2281. Write(Diffuse.AsAddress^, SizeOf(Single) * 4);
  2282. Write(Emission.AsAddress^, SizeOf(Single) * 3);
  2283. Write(Specular.AsAddress^, SizeOf(Single) * 3);
  2284. Write(Byte(FShininess), 1);
  2285. WriteInteger(Integer(libMat.Material.PolygonMode));
  2286. end;
  2287. WriteInteger(Integer(libMat.Material.BlendingMode));
  2288. // version 3
  2289. with libMat.Material do
  2290. begin
  2291. if BlendingMode = bmCustom then
  2292. begin
  2293. WriteBoolean(TRUE);
  2294. with BlendingParams do
  2295. begin
  2296. WriteFloat(AlphaFuncRef);
  2297. WriteInteger(Integer(AlphaFunctType));
  2298. WriteInteger(Integer(BlendFuncDFactor));
  2299. WriteInteger(Integer(BlendFuncSFactor));
  2300. WriteBoolean(UseAlphaFunc);
  2301. WriteBoolean(UseBlendFunc);
  2302. end;
  2303. end
  2304. else
  2305. WriteBoolean(FALSE);
  2306. WriteInteger(Integer(FaceCulling));
  2307. end;
  2308. // version 3 end
  2309. WriteInteger(SizeOf(TGLMaterialOptions));
  2310. Write(libMat.Material.MaterialOptions, SizeOf(TGLMaterialOptions));
  2311. Write(libMat.TextureOffset.AsAddress^, SizeOf(Single) * 3);
  2312. Write(libMat.TextureScale.AsAddress^, SizeOf(Single) * 3);
  2313. WriteString(libMat.Texture2Name);
  2314. // version 4
  2315. WriteFloat(libMat.TextureRotate);
  2316. // version 2
  2317. WriteInteger(libMat.Material.TextureEx.Count);
  2318. for j := 0 to libMat.Material.TextureEx.Count - 1 do
  2319. begin
  2320. texExItem := libMat.Material.TextureEx[j];
  2321. img := texExItem.Texture.Image;
  2322. pim := TGLPersistentImage(img);
  2323. if texExItem.Texture.Enabled and (img is TGLPersistentImage)
  2324. and (pim.Picture.Graphic <> nil) then
  2325. begin
  2326. WriteBoolean(True);
  2327. ss := TStringStream.Create('');
  2328. try
  2329. bmp := TBitmap.Create;
  2330. try
  2331. bmp.Assign(pim.Picture.Graphic);
  2332. bmp.SaveToStream(ss);
  2333. finally
  2334. bmp.Free;
  2335. end;
  2336. WriteString(ss.DataString);
  2337. finally
  2338. ss.Free;
  2339. end;
  2340. end
  2341. else
  2342. WriteBoolean(False);
  2343. WriteInteger(texExItem.TextureIndex);
  2344. Write(texExItem.TextureOffset.AsAddress^, SizeOf(Single) * 3);
  2345. Write(texExItem.TextureScale.AsAddress^, SizeOf(Single) * 3);
  2346. end;
  2347. end;
  2348. end;
  2349. end;
  2350. procedure TGLMaterialLibrary.ReadFromFiler(reader: TGLVirtualReader);
  2351. var
  2352. archiveVersion: Integer;
  2353. libMat: TGLLibMaterial;
  2354. i, n, size, tex, texCount: Integer;
  2355. LName: string;
  2356. ss: TStringStream;
  2357. bmp: TBitmap;
  2358. texExItem: TGLTextureExItem;
  2359. begin
  2360. archiveVersion := reader.ReadInteger;
  2361. if (archiveVersion >= 0) and (archiveVersion <= 4) then
  2362. with reader do
  2363. begin
  2364. if not FDoNotClearMaterialsOnLoad then
  2365. Materials.Clear;
  2366. n := ReadInteger;
  2367. for i := 0 to n - 1 do
  2368. begin
  2369. // version 0
  2370. LName := ReadString;
  2371. if FDoNotClearMaterialsOnLoad then
  2372. libMat := LibMaterialByName(LName)
  2373. else
  2374. libMat := nil;
  2375. if ReadBoolean then
  2376. begin
  2377. ss := TStringStream.Create(ReadString);
  2378. try
  2379. bmp := TBitmap.Create;
  2380. try
  2381. bmp.LoadFromStream(ss);
  2382. if libMat = nil then
  2383. libMat := AddTextureMaterial(LName, bmp)
  2384. else
  2385. libMat.Material.Texture.Image.Assign(bmp);
  2386. finally
  2387. bmp.Free;
  2388. end;
  2389. finally
  2390. ss.Free;
  2391. end;
  2392. // version 3
  2393. if archiveVersion >= 3 then
  2394. with libMat.Material.Texture do
  2395. begin
  2396. Read(BorderColor.AsAddress^, SizeOf(Single) * 4);
  2397. Compression := TGLTextureCompression(ReadInteger);
  2398. DepthTextureMode := TGLDepthTextureMode(ReadInteger);
  2399. Read(EnvColor.AsAddress^, SizeOf(Single) * 4);
  2400. FilteringQuality := TGLTextureFilteringQuality(ReadInteger);
  2401. ImageAlpha := TGLTextureImageAlpha(ReadInteger);
  2402. ImageBrightness := ReadFloat;
  2403. ImageGamma := ReadFloat;
  2404. MagFilter := TGLMagFilter(ReadInteger);
  2405. MappingMode := TGLTextureMappingMode(ReadInteger);
  2406. Read(MappingSCoordinates.AsAddress^, SizeOf(Single) * 4);
  2407. Read(MappingTCoordinates.AsAddress^, SizeOf(Single) * 4);
  2408. Read(MappingRCoordinates.AsAddress^, SizeOf(Single) * 4);
  2409. Read(MappingQCoordinates.AsAddress^, SizeOf(Single) * 4);
  2410. MinFilter := TGLMinFilter(ReadInteger);
  2411. NormalMapScale := ReadFloat;
  2412. TextureCompareFunc := TGLDepthCompareFunc(ReadInteger);
  2413. TextureCompareMode := TGLTextureCompareMode(ReadInteger);
  2414. TextureFormat := TGLTextureFormat(ReadInteger);
  2415. TextureMode := TGLTextureMode(ReadInteger);
  2416. TextureWrap := TGLTextureWrap(ReadInteger);
  2417. TextureWrapR := TGLSeparateTextureWrap(ReadInteger);
  2418. TextureWrapS := TGLSeparateTextureWrap(ReadInteger);
  2419. TextureWrapT := TGLSeparateTextureWrap(ReadInteger);
  2420. end;
  2421. // version 3 end
  2422. end
  2423. else
  2424. begin
  2425. if libMat = nil then
  2426. begin
  2427. libMat := Materials.Add;
  2428. libMat.Name := LName;
  2429. end;
  2430. end;
  2431. with libMat.Material.FrontProperties do
  2432. begin
  2433. Read(Ambient.AsAddress^, SizeOf(Single) * 3);
  2434. Read(Diffuse.AsAddress^, SizeOf(Single) * 4);
  2435. Read(Emission.AsAddress^, SizeOf(Single) * 3);
  2436. Read(Specular.AsAddress^, SizeOf(Single) * 3);
  2437. end;
  2438. // version 1
  2439. if archiveVersion >= 1 then
  2440. begin
  2441. with libMat.Material.FrontProperties do
  2442. begin
  2443. Read(FShininess, 1);
  2444. libMat.Material.PolygonMode := TGLPolygonMode(ReadInteger);
  2445. end;
  2446. with libMat.Material.BackProperties do
  2447. begin
  2448. Read(Ambient.AsAddress^, SizeOf(Single) * 3);
  2449. Read(Diffuse.AsAddress^, SizeOf(Single) * 4);
  2450. Read(Emission.AsAddress^, SizeOf(Single) * 3);
  2451. Read(Specular.AsAddress^, SizeOf(Single) * 3);
  2452. Read(FShininess, 1);
  2453. {PolygonMode := TPolygonMode(} ReadInteger;
  2454. end;
  2455. libMat.Material.BlendingMode := TGLBlendingMode(ReadInteger);
  2456. // version 3
  2457. if archiveVersion >= 3 then
  2458. begin
  2459. if ReadBoolean then
  2460. with libMat.Material.BlendingParams do
  2461. begin
  2462. AlphaFuncRef := ReadFloat;
  2463. AlphaFunctType := TGlAlphaFunc(ReadInteger);
  2464. BlendFuncDFactor := TGLBlendFunction(ReadInteger);
  2465. BlendFuncSFactor := TGLBlendFunction(ReadInteger);
  2466. UseAlphaFunc := ReadBoolean;
  2467. UseBlendFunc := ReadBoolean;
  2468. end;
  2469. libMat.Material.FaceCulling := TGLFaceCulling(ReadInteger);
  2470. end;
  2471. // version 3 end
  2472. size := ReadInteger;
  2473. Read(libMat.Material.FMaterialOptions, size);
  2474. Read(libMat.TextureOffset.AsAddress^, SizeOf(Single) * 3);
  2475. Read(libMat.TextureScale.AsAddress^, SizeOf(Single) * 3);
  2476. libMat.Texture2Name := ReadString;
  2477. // version 4
  2478. if archiveVersion >= 4 then
  2479. libMat.TextureRotate := ReadFloat;
  2480. end;
  2481. // version 2
  2482. if archiveVersion >= 2 then
  2483. begin
  2484. texCount := ReadInteger;
  2485. for tex := 0 to texCount - 1 do
  2486. begin
  2487. texExItem := libMat.Material.TextureEx.Add;
  2488. if ReadBoolean then
  2489. begin
  2490. ss := TStringStream.Create(ReadString);
  2491. bmp := TBitmap.Create;
  2492. try
  2493. bmp.LoadFromStream(ss);
  2494. texExItem.Texture.Image.Assign(bmp);
  2495. texExItem.Texture.Enabled := True;
  2496. finally
  2497. bmp.Free;
  2498. ss.Free;
  2499. end;
  2500. end;
  2501. texExItem.TextureIndex := ReadInteger;
  2502. Read(texExItem.TextureOffset.AsAddress^, SizeOf(Single) * 3);
  2503. Read(texExItem.TextureScale.AsAddress^, SizeOf(Single) * 3);
  2504. end;
  2505. end;
  2506. end;
  2507. end
  2508. else
  2509. RaiseFilerException(Self.ClassType, archiveVersion);
  2510. end;
  2511. procedure TGLMaterialLibrary.SaveToStream(aStream: TStream);
  2512. var
  2513. wr: TGLBinaryWriter;
  2514. begin
  2515. wr := TGLBinaryWriter.Create(aStream);
  2516. try
  2517. Self.WriteToFiler(wr);
  2518. finally
  2519. wr.Free;
  2520. end;
  2521. end;
  2522. procedure TGLMaterialLibrary.LoadFromStream(aStream: TStream);
  2523. var
  2524. rd: TGLBinaryReader;
  2525. begin
  2526. rd := TGLBinaryReader.Create(aStream);
  2527. try
  2528. Self.ReadFromFiler(rd);
  2529. finally
  2530. rd.Free;
  2531. end;
  2532. end;
  2533. procedure TGLMaterialLibrary.AddMaterialsFromStream(aStream: TStream);
  2534. begin
  2535. FDoNotClearMaterialsOnLoad := True;
  2536. try
  2537. LoadFromStream(aStream);
  2538. finally
  2539. FDoNotClearMaterialsOnLoad := False;
  2540. end;
  2541. end;
  2542. procedure TGLMaterialLibrary.SaveToFile(const fileName: string);
  2543. var
  2544. fs: TStream;
  2545. begin
  2546. fs := TFileStream.Create(fileName, fmCreate);
  2547. try
  2548. SaveToStream(fs);
  2549. finally
  2550. fs.Free;
  2551. end;
  2552. end;
  2553. procedure TGLMaterialLibrary.LoadFromFile(const fileName: string);
  2554. var
  2555. fs: TStream;
  2556. begin
  2557. fs := TFileStream.Create(fileName, fmOpenRead + fmShareDenyNone);
  2558. try
  2559. LoadFromStream(fs);
  2560. finally
  2561. fs.Free;
  2562. end;
  2563. end;
  2564. procedure TGLMaterialLibrary.AddMaterialsFromFile(const fileName: string);
  2565. var
  2566. fs: TStream;
  2567. begin
  2568. fs := TFileStream.Create(fileName, fmOpenRead + fmShareDenyNone);
  2569. try
  2570. AddMaterialsFromStream(fs);
  2571. finally
  2572. fs.Free;
  2573. end;
  2574. end;
  2575. function TGLMaterialLibrary.AddTextureMaterial(const materialName, fileName:
  2576. string;
  2577. persistent: Boolean = True): TGLLibMaterial;
  2578. begin
  2579. Result := Materials.Add;
  2580. with Result do
  2581. begin
  2582. Name := materialName;
  2583. with Material.Texture do
  2584. begin
  2585. MinFilter := miLinearMipmapLinear;
  2586. MagFilter := maLinear;
  2587. TextureMode := tmModulate;
  2588. Disabled := False;
  2589. if persistent then
  2590. begin
  2591. ImageClassName := TGLPersistentImage.ClassName;
  2592. if fileName <> '' then
  2593. Image.LoadFromFile(fileName);
  2594. end
  2595. else
  2596. begin
  2597. ImageClassName := TGLPicFileImage.ClassName;
  2598. TGLPicFileImage(Image).PictureFileName := fileName;
  2599. end;
  2600. end;
  2601. end;
  2602. end;
  2603. function TGLMaterialLibrary.AddTextureMaterial(const materialName: string;
  2604. graphic: TGraphic): TGLLibMaterial;
  2605. begin
  2606. Result := Materials.Add;
  2607. with Result do
  2608. begin
  2609. Name := materialName;
  2610. with Material.Texture do
  2611. begin
  2612. MinFilter := miLinearMipmapLinear;
  2613. MagFilter := maLinear;
  2614. TextureMode := tmModulate;
  2615. Disabled := False;
  2616. Image.Assign(graphic);
  2617. end;
  2618. end;
  2619. end;
  2620. function TGLMaterialLibrary.LibMaterialByName(const AName: TGLLibMaterialName):
  2621. TGLLibMaterial;
  2622. begin
  2623. if Assigned(Self) then
  2624. Result := Materials.GetLibMaterialByName(AName)
  2625. else
  2626. Result := nil;
  2627. end;
  2628. function TGLMaterialLibrary.TextureByName(const LibMatName: TGLLibMaterialName):
  2629. TGLTexture;
  2630. var
  2631. LibMat: TGLLibMaterial;
  2632. begin
  2633. if Self = nil then
  2634. raise ETexture.Create(strErrorEx + strMatLibNotDefined)
  2635. else if LibMatName = '' then
  2636. Result := nil
  2637. else
  2638. begin
  2639. LibMat := LibMaterialByName(LibMatName);
  2640. if LibMat = nil then
  2641. raise ETexture.CreateFmt(strErrorEx + strMaterialNotFoundInMatlibEx,
  2642. [LibMatName])
  2643. else
  2644. Result := LibMat.Material.Texture;
  2645. end;
  2646. end;
  2647. function TGLMaterialLibrary.GetNameOfTexture(const Texture: TGLTexture):
  2648. TGLLibMaterialName;
  2649. begin
  2650. if (Self = nil) or (Texture = nil) then
  2651. Result := ''
  2652. else
  2653. Result := Materials.GetNameOfTexture(Texture);
  2654. end;
  2655. function TGLMaterialLibrary.GetMaterials: TGLLibMaterials;
  2656. begin
  2657. Result := TGLLibMaterials(FMaterials);
  2658. end;
  2659. function TGLMaterialLibrary.GetNameOfLibMaterial(const LibMat: TGLLibMaterial):
  2660. TGLLibMaterialName;
  2661. begin
  2662. if (Self = nil) or (LibMat = nil) then
  2663. Result := ''
  2664. else
  2665. Result := Materials.GetNameOfLibMaterial(LibMat);
  2666. end;
  2667. procedure TGLBlendingParameters.Apply(var rci: TGLRenderContextInfo);
  2668. begin
  2669. if FUseAlphaFunc then
  2670. begin
  2671. rci.GLStates.Enable(stAlphaTest);
  2672. rci.GLStates.SetGLAlphaFunction(FAlphaFuncType, FAlphaFuncRef);
  2673. end
  2674. else
  2675. rci.GLStates.Disable(stAlphaTest);
  2676. if FUseBlendFunc then
  2677. begin
  2678. rci.GLStates.Enable(stBlend);
  2679. if FSeparateBlendFunc then
  2680. rci.GLStates.SetBlendFuncSeparate(FBlendFuncSFactor, FBlendFuncDFactor,
  2681. FAlphaBlendFuncSFactor, FAlphaBlendFuncDFactor)
  2682. else
  2683. rci.GLStates.SetBlendFunc(FBlendFuncSFactor, FBlendFuncDFactor);
  2684. end
  2685. else
  2686. rci.GLStates.Disable(stBlend);
  2687. end;
  2688. constructor TGLBlendingParameters.Create(AOwner: TPersistent);
  2689. begin
  2690. inherited;
  2691. FUseAlphaFunc := False;
  2692. FAlphaFuncType := cfGreater;
  2693. FAlphaFuncRef := 0;
  2694. FUseBlendFunc := True;
  2695. FSeparateBlendFunc := False;
  2696. FBlendFuncSFactor := bfSrcAlpha;
  2697. FBlendFuncDFactor := bfOneMinusSrcAlpha;
  2698. FAlphaBlendFuncSFactor := bfSrcAlpha;
  2699. FAlphaBlendFuncDFactor := bfOneMinusSrcAlpha;
  2700. end;
  2701. procedure TGLBlendingParameters.SetAlphaFuncRef(const Value: Single);
  2702. begin
  2703. if (FAlphaFuncRef <> Value) then
  2704. begin
  2705. FAlphaFuncRef := Value;
  2706. NotifyChange(Self);
  2707. end;
  2708. end;
  2709. procedure TGLBlendingParameters.SetAlphaFuncType(
  2710. const Value: TGlAlphaFunc);
  2711. begin
  2712. if (FAlphaFuncType <> Value) then
  2713. begin
  2714. FAlphaFuncType := Value;
  2715. NotifyChange(Self);
  2716. end;
  2717. end;
  2718. procedure TGLBlendingParameters.SetBlendFuncDFactor(
  2719. const Value: TGLBlendFunction);
  2720. begin
  2721. if (FBlendFuncDFactor <> Value) then
  2722. begin
  2723. FBlendFuncDFactor := Value;
  2724. if not FSeparateBlendFunc then
  2725. FAlphaBlendFuncDFactor := Value;
  2726. NotifyChange(Self);
  2727. end;
  2728. end;
  2729. procedure TGLBlendingParameters.SetBlendFuncSFactor(
  2730. const Value: TGLBlendFunction);
  2731. begin
  2732. if (FBlendFuncSFactor <> Value) then
  2733. begin
  2734. FBlendFuncSFactor := Value;
  2735. if not FSeparateBlendFunc then
  2736. FAlphaBlendFuncSFactor := Value;
  2737. NotifyChange(Self);
  2738. end;
  2739. end;
  2740. procedure TGLBlendingParameters.SetAlphaBlendFuncDFactor(const Value: TGLBlendFunction);
  2741. begin
  2742. if FSeparateBlendFunc and (FAlphaBlendFuncDFactor <> Value) then
  2743. begin
  2744. FAlphaBlendFuncDFactor := Value;
  2745. NotifyChange(Self);
  2746. end;
  2747. end;
  2748. procedure TGLBlendingParameters.SetAlphaBlendFuncSFactor(const Value: TGLBlendFunction);
  2749. begin
  2750. if FSeparateBlendFunc and (FAlphaBlendFuncSFactor <> Value) then
  2751. begin
  2752. FAlphaBlendFuncSFactor := Value;
  2753. NotifyChange(Self);
  2754. end;
  2755. end;
  2756. procedure TGLBlendingParameters.SetUseAlphaFunc(const Value: Boolean);
  2757. begin
  2758. if (FUseAlphaFunc <> Value) then
  2759. begin
  2760. FUseAlphaFunc := Value;
  2761. NotifyChange(Self);
  2762. end;
  2763. end;
  2764. procedure TGLBlendingParameters.SetUseBlendFunc(const Value: Boolean);
  2765. begin
  2766. if (FUseBlendFunc <> Value) then
  2767. begin
  2768. FUseBlendFunc := Value;
  2769. NotifyChange(Self);
  2770. end;
  2771. end;
  2772. procedure TGLBlendingParameters.SetSeparateBlendFunc(const Value: Boolean);
  2773. begin
  2774. if (FSeparateBlendFunc <> Value) then
  2775. begin
  2776. FSeparateBlendFunc := Value;
  2777. if not Value then
  2778. begin
  2779. FAlphaBlendFuncSFactor := FBlendFuncSFactor;
  2780. FAlphaBlendFuncDFactor := FBlendFuncDFactor;
  2781. end;
  2782. NotifyChange(Self);
  2783. end;
  2784. end;
  2785. function TGLBlendingParameters.StoreAlphaFuncRef: Boolean;
  2786. begin
  2787. Result := (Abs(AlphaFuncRef) > 0.001);
  2788. end;
  2789. //-----------------------------------------------
  2790. initialization
  2791. //-----------------------------------------------
  2792. RegisterClasses([TGLMaterialLibrary, TGLMaterial, TGLShader]);
  2793. end.