GXS.Material.pas 89 KB

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