GLS.Material.pas 90 KB

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