GXSL.TextureShaders.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873
  1. //
  2. // The graphics engine GXScene https://github.com/glscene
  3. //
  4. unit GXSL.TextureShaders;
  5. (*
  6. This shader allows to apply multiple textures, gathering them from existing materials.
  7. This allows saving resources, since you can reference the textures of any material in
  8. any materialLibrary.
  9. Note that actually the component references a Material (not a texture) but
  10. it uses that material's texture. The referenced material settings will be ignored,
  11. but the texture's settings (like TextureMode, ImageGamma, ImageBrightness) will be used.
  12. Instead the local material settings (listed in the collection) will be used.
  13. *)
  14. interface
  15. uses
  16. Winapi.OpenGL,
  17. Winapi.OpenGLext,
  18. System.Classes,
  19. System.SysUtils,
  20. GXS.Scene,
  21. GXS.Context,
  22. GXS.Texture,
  23. Stage.VectorTypes,
  24. GXS.XOpenGL,
  25. Stage.VectorGeometry,
  26. GXS.Color,
  27. GXS.Material,
  28. Stage.Strings,
  29. GXS.VectorFileObjects,
  30. GXS.State,
  31. GXS.PersistentClasses,
  32. GXS.Coordinates,
  33. GXS.TextureCombiners,
  34. GXS.RenderContextInfo,
  35. GXS.ImageUtils;
  36. type
  37. TgxShaderTextureSharing = class;
  38. TgxShaderTextureSharingMaterial = class(TgxInterfacedCollectionItem, IgxMaterialLibrarySupported)
  39. private
  40. FTextureMatrix: TMatrix4f;
  41. FNeedToUpdateTextureMatrix: Boolean;
  42. FTextureMatrixIsUnitary: Boolean;
  43. FLibMaterial: TgxLibMaterial;
  44. FTexOffset: TgxCoordinates2;
  45. FTexScale: TgxCoordinates2;
  46. FBlendingMode: TgxBlendingMode;
  47. FSpecular: TgxColor;
  48. FAmbient: TgxColor;
  49. FDiffuse: TgxColor;
  50. FEmission: TgxColor;
  51. FShininess: TgxShininess;
  52. FMaterialLibrary: TgxMaterialLibrary;
  53. FLibMaterialName: TgxLibMaterialName;
  54. procedure SetAmbient(const Value: TgxColor);
  55. procedure SetDiffuse(const Value: TgxColor);
  56. procedure SetEmission(const Value: TgxColor);
  57. procedure SetShininess(const Value: TgxShininess);
  58. procedure SetSpecular(const Value: TgxColor);
  59. procedure SetMaterialLibrary(const Value: TgxMaterialLibrary);
  60. procedure SetLibMaterialName(const Value: TgxLibMaterialName);
  61. procedure SetBlendingMode(const Value: TgxBlendingMode);
  62. procedure SetLibMaterial(const Value: TgxLibMaterial);
  63. procedure SetTexOffset(const Value: TgxCoordinates2);
  64. procedure SetTexScale(const Value: TgxCoordinates2);
  65. function GetTextureMatrix: TMatrix4f;
  66. function GetTextureMatrixIsUnitary: Boolean;
  67. protected
  68. procedure coordNotifychange(Sender: TObject);
  69. procedure OtherNotifychange(Sender: TObject);
  70. function GetDisplayName: string; override;
  71. function GetTextureSharingShader: TgxShaderTextureSharing;
  72. // Implementing IgxMaterialLibrarySupported.
  73. function GetMaterialLibrary: TgxAbstractMaterialLibrary; virtual;
  74. public
  75. procedure Apply(var rci: TgxRenderContextInfo);
  76. procedure UnApply(var rci: TgxRenderContextInfo);
  77. constructor Create(Collection: TCollection); override;
  78. destructor Destroy; override;
  79. property LibMaterial: TgxLibMaterial read FLibMaterial write SetLibMaterial;
  80. property TextureMatrix: TMatrix4f read GetTextureMatrix;
  81. property TextureMatrixIsUnitary: Boolean read GetTextureMatrixIsUnitary;
  82. published
  83. property TexOffset: TgxCoordinates2 read FTexOffset write SetTexOffset;
  84. property TexScale: TgxCoordinates2 read FTexScale write SetTexScale;
  85. property BlendingMode: TgxBlendingMode read FBlendingMode write SetBlendingMode;
  86. property Emission: TgxColor read FEmission write SetEmission;
  87. property Ambient: TgxColor read FAmbient write SetAmbient;
  88. property Diffuse: TgxColor read FDiffuse write SetDiffuse;
  89. property Specular: TgxColor read FSpecular write SetSpecular;
  90. property Shininess: TgxShininess read FShininess write SetShininess;
  91. property MaterialLibrary: TgxMaterialLibrary read FMaterialLibrary write SetMaterialLibrary;
  92. property LibMaterialName: TgxLibMaterialName read FLibMaterialName write SetLibMaterialName;
  93. end;
  94. TgxShaderTextureSharingMaterials = class(TOwnedCollection)
  95. protected
  96. function GetItems(const AIndex: Integer): TgxShaderTextureSharingMaterial;
  97. procedure SetItems(const AIndex: Integer; const Value: TgxShaderTextureSharingMaterial);
  98. function GetParent: TgxShaderTextureSharing;
  99. public
  100. function Add: TgxShaderTextureSharingMaterial;
  101. constructor Create(AOwner: TgxShaderTextureSharing);
  102. property Items[const AIndex: Integer]: TgxShaderTextureSharingMaterial read GetItems write SetItems; default;
  103. end;
  104. TgxShaderTextureSharing = class(TgxShader)
  105. private
  106. FMaterials: TgxShaderTextureSharingMaterials;
  107. FCurrentPass: Integer;
  108. procedure SetMaterials(const Value: TgxShaderTextureSharingMaterials);
  109. protected
  110. procedure DoApply(var rci: TgxRenderContextInfo; Sender: TObject); override;
  111. function DoUnApply(var rci: TgxRenderContextInfo): Boolean; override;
  112. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  113. public
  114. constructor Create(AOwner: TComponent); override;
  115. destructor Destroy; override;
  116. function AddLibMaterial(const ALibMaterial: TgxLibMaterial): TgxShaderTextureSharingMaterial;
  117. function FindLibMaterial(const ALibMaterial: TgxLibMaterial): TgxShaderTextureSharingMaterial;
  118. published
  119. property Materials: TgxShaderTextureSharingMaterials read FMaterials write SetMaterials;
  120. end;
  121. // A shader that can setup the texture combiner.
  122. TgxTexCombineShader = class(TgxShader)
  123. private
  124. FCombiners: TStringList;
  125. FCommandCache: TgxCombinerCache;
  126. FCombinerIsValid: Boolean; // to avoid reparsing invalid stuff
  127. FDesignTimeEnabled: Boolean;
  128. FMaterialLibrary: TgxMaterialLibrary;
  129. FLibMaterial3Name: TgxLibMaterialName;
  130. CurrentLibMaterial3: TgxLibMaterial;
  131. FLibMaterial4Name: TgxLibMaterialName;
  132. CurrentLibMaterial4: TgxLibMaterial;
  133. FApplied3, FApplied4: Boolean;
  134. protected
  135. procedure SetCombiners(const val: TStringList);
  136. procedure SetDesignTimeEnabled(const val: Boolean);
  137. procedure SetMaterialLibrary(const val: TgxMaterialLibrary);
  138. procedure SetLibMaterial3Name(const val: TgxLibMaterialName);
  139. procedure SetLibMaterial4Name(const val: TgxLibMaterialName);
  140. procedure NotifyLibMaterial3Destruction;
  141. procedure NotifyLibMaterial4Destruction;
  142. procedure DoInitialize(var rci: TgxRenderContextInfo; Sender: TObject); override;
  143. procedure DoApply(var rci: TgxRenderContextInfo; Sender: TObject); override;
  144. function DoUnApply(var rci: TgxRenderContextInfo): Boolean; override;
  145. procedure DoFinalize; override;
  146. public
  147. constructor Create(AOwner: TComponent); override;
  148. destructor Destroy; override;
  149. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  150. procedure NotifyChange(Sender: TObject); override;
  151. published
  152. property Combiners: TStringList read FCombiners write SetCombiners;
  153. property DesignTimeEnabled: Boolean read FDesignTimeEnabled write SetDesignTimeEnabled;
  154. property MaterialLibrary: TgxMaterialLibrary read FMaterialLibrary write SetMaterialLibrary;
  155. property LibMaterial3Name: TgxLibMaterialName read FLibMaterial3Name write SetLibMaterial3Name;
  156. property LibMaterial4Name: TgxLibMaterialName read FLibMaterial4Name write SetLibMaterial4Name;
  157. end;
  158. //=======================================================================
  159. implementation
  160. //=======================================================================
  161. //----------------------------------------------------------------------------
  162. // TgxShaderTextureSharingMaterial
  163. //----------------------------------------------------------------------------
  164. procedure TgxShaderTextureSharingMaterial.Apply(var rci: TgxRenderContextInfo);
  165. begin
  166. if not Assigned(FLibMaterial) then
  167. Exit;
  168. xglBeginUpdate;
  169. if Assigned(FLibMaterial.Shader) then
  170. begin
  171. case FLibMaterial.Shader.ShaderStyle of
  172. ssHighLevel: FLibMaterial.Shader.Apply(rci, FLibMaterial);
  173. ssReplace:
  174. begin
  175. FLibMaterial.Shader.Apply(rci, FLibMaterial);
  176. Exit;
  177. end;
  178. end;
  179. end;
  180. if not FLibMaterial.Material.Texture.Disabled then
  181. begin
  182. if not (GetTextureMatrixIsUnitary) then
  183. begin
  184. rci.gxStates.SetTextureMatrix(TextureMatrix);
  185. end;
  186. end;
  187. if moNoLighting in FLibMaterial.Material.MaterialOptions then
  188. rci.gxStates.Disable(stLighting);
  189. if stLighting in rci.gxStates.States then
  190. begin
  191. rci.gxStates.SetMaterialColors(cmFront,
  192. Emission.Color, Ambient.Color, Diffuse.Color, Specular.Color, Shininess);
  193. rci.gxStates.PolygonMode :=FLibMaterial.Material.PolygonMode;
  194. end
  195. else
  196. FLibMaterial.Material.FrontProperties.ApplyNoLighting(rci, cmFront);
  197. if (stCullFace in rci.gxStates.States) then
  198. begin
  199. case FLibMaterial.Material.FaceCulling of
  200. fcBufferDefault: if not rci.bufferFaceCull then
  201. begin
  202. rci.gxStates.Disable(stCullFace);
  203. FLibMaterial.Material.BackProperties.Apply(rci, cmBack);
  204. end;
  205. fcCull: ; // nothing to do
  206. fcNoCull:
  207. begin
  208. rci.gxStates.Disable(stCullFace);
  209. FLibMaterial.Material.BackProperties.Apply(rci, cmBack);
  210. end;
  211. else
  212. Assert(False);
  213. end;
  214. end
  215. else
  216. begin
  217. // currently NOT culling
  218. case FLibMaterial.Material.FaceCulling of
  219. fcBufferDefault:
  220. begin
  221. if rci.bufferFaceCull then
  222. rci.gxStates.Enable(stCullFace)
  223. else
  224. FLibMaterial.Material.BackProperties.Apply(rci, cmBack);
  225. end;
  226. fcCull: rci.gxStates.Enable(stCullFace);
  227. fcNoCull: FLibMaterial.Material.BackProperties.Apply(rci, cmBack);
  228. else
  229. Assert(False);
  230. end;
  231. end;
  232. // Apply Blending mode
  233. if not rci.ignoreBlendingRequests then
  234. case BlendingMode of
  235. bmOpaque:
  236. begin
  237. rci.gxStates.Disable(stBlend);
  238. rci.gxStates.Disable(stAlphaTest);
  239. end;
  240. bmTransparency:
  241. begin
  242. rci.gxStates.Enable(stBlend);
  243. rci.gxStates.Enable(stAlphaTest);
  244. rci.gxStates.SetBlendFunc(bfSrcAlpha, bfOneMinusSrcAlpha);
  245. end;
  246. bmAdditive:
  247. begin
  248. rci.gxStates.Enable(stBlend);
  249. rci.gxStates.Enable(stAlphaTest);
  250. rci.gxStates.SetBlendFunc(bfSrcAlpha, bfOne);
  251. end;
  252. bmAlphaTest50:
  253. begin
  254. rci.gxStates.Disable(stBlend);
  255. rci.gxStates.Enable(stAlphaTest);
  256. rci.gxStates.SetAlphaFunction(cfGEqual, 0.5);
  257. end;
  258. bmAlphaTest100:
  259. begin
  260. rci.gxStates.Disable(stBlend);
  261. rci.gxStates.Enable(stAlphaTest);
  262. rci.gxStates.SetAlphaFunction(cfGEqual, 1.0);
  263. end;
  264. bmModulate:
  265. begin
  266. rci.gxStates.Enable(stBlend);
  267. rci.gxStates.Enable(stAlphaTest);
  268. rci.gxStates.SetBlendFunc(bfDstColor, bfZero);
  269. end;
  270. else
  271. Assert(False);
  272. end;
  273. // Fog switch
  274. if moIgnoreFog in FLibMaterial.Material.MaterialOptions then
  275. begin
  276. if stFog in rci.gxStates.States then
  277. begin
  278. rci.gxStates.Disable(stFog);
  279. Inc(rci.fogDisabledCounter);
  280. end;
  281. end;
  282. if not Assigned(FLibMaterial.Material.TextureEx) then
  283. begin
  284. if Assigned(FLibMaterial.Material.Texture) then
  285. FLibMaterial.Material.Texture.Apply(rci);
  286. end
  287. else
  288. begin
  289. if Assigned(FLibMaterial.Material.Texture) and not FLibMaterial.Material.TextureEx.IsTextureEnabled(0) then
  290. FLibMaterial.Material.Texture.Apply(rci)
  291. else
  292. if FLibMaterial.Material.TextureEx.Count > 0 then
  293. FLibMaterial.Material.TextureEx.Apply(rci);
  294. end;
  295. if Assigned(FLibMaterial.Shader) then
  296. begin
  297. case FLibMaterial.Shader.ShaderStyle of
  298. ssLowLevel: FLibMaterial.Shader.Apply(rci, FLibMaterial);
  299. end;
  300. end;
  301. xglEndUpdate;
  302. end;
  303. procedure TgxShaderTextureSharingMaterial.coordNotifychange(Sender: TObject);
  304. begin
  305. FNeedToUpdateTextureMatrix := True;
  306. GetTextureSharingShader.NotifyChange(Self);
  307. end;
  308. constructor TgxShaderTextureSharingMaterial.Create(Collection: TCollection);
  309. begin
  310. inherited;
  311. FSpecular := TgxColor.Create(Self);
  312. FSpecular.OnNotifyChange := OtherNotifychange;
  313. FAmbient := TgxColor.Create(Self);
  314. FAmbient.OnNotifyChange := OtherNotifychange;
  315. FDiffuse := TgxColor.Create(Self);
  316. FDiffuse.OnNotifyChange := OtherNotifychange;
  317. FEmission := TgxColor.Create(Self);
  318. FEmission.OnNotifyChange := OtherNotifychange;
  319. FTexOffset := TgxCoordinates2.CreateInitialized(Self, NullHmgVector, csPoint2d);
  320. FTexOffset.OnNotifyChange := coordNotifychange;
  321. FTexScale := TgxCoordinates2.CreateInitialized(Self, XYZHmgVector, csPoint2d);
  322. FTexScale.OnNotifyChange := coordNotifychange;
  323. FNeedToUpdateTextureMatrix := True;
  324. end;
  325. destructor TgxShaderTextureSharingMaterial.Destroy;
  326. begin
  327. FSpecular.Free;
  328. FAmbient.Free;
  329. FDiffuse.Free;
  330. FEmission.Free;
  331. FTexOffset.Free;
  332. FTexScale.Free;
  333. inherited;
  334. end;
  335. function TgxShaderTextureSharingMaterial.GetDisplayName: string;
  336. var
  337. st: string;
  338. begin
  339. if Assigned(MaterialLibrary) then
  340. st := MaterialLibrary.Name
  341. else
  342. st := '';
  343. Result := '[' + st + '.' + Self.LibMaterialName + ']';
  344. end;
  345. function TgxShaderTextureSharingMaterial.GetMaterialLibrary: TgxAbstractMaterialLibrary;
  346. begin
  347. Result := FMaterialLibrary;
  348. end;
  349. function TgxShaderTextureSharingMaterial.GetTextureMatrix: TMatrix4f;
  350. begin
  351. if FNeedToUpdateTextureMatrix then
  352. begin
  353. if not (TexOffset.Equals(NullHmgVector) and TexScale.Equals(XYZHmgVector)) then
  354. begin
  355. FTextureMatrixIsUnitary := False;
  356. FTextureMatrix := CreateScaleAndTranslationMatrix(TexScale.AsVector, TexOffset.AsVector)
  357. end
  358. else
  359. FTextureMatrixIsUnitary := True;
  360. FNeedToUpdateTextureMatrix := False;
  361. end;
  362. Result := FTextureMatrix;
  363. end;
  364. function TgxShaderTextureSharingMaterial.GetTextureMatrixIsUnitary: Boolean;
  365. begin
  366. if FNeedToUpdateTextureMatrix then
  367. GetTextureMatrix;
  368. Result := FTextureMatrixIsUnitary;
  369. end;
  370. function TgxShaderTextureSharingMaterial.GetTextureSharingShader: TgxShaderTextureSharing;
  371. begin
  372. if Collection is TgxShaderTextureSharingMaterials then
  373. Result := TgxShaderTextureSharingMaterials(Collection).GetParent
  374. else
  375. Result := nil;
  376. end;
  377. procedure TgxShaderTextureSharingMaterial.OtherNotifychange(Sender: TObject);
  378. begin
  379. GetTextureSharingShader.NotifyChange(Self);
  380. end;
  381. procedure TgxShaderTextureSharingMaterial.SetAmbient(const Value: TgxColor);
  382. begin
  383. FAmbient.Assign(Value);
  384. end;
  385. procedure TgxShaderTextureSharingMaterial.SetBlendingMode(const Value: TgxBlendingMode);
  386. begin
  387. FBlendingMode := Value;
  388. end;
  389. procedure TgxShaderTextureSharingMaterial.SetDiffuse(const Value: TgxColor);
  390. begin
  391. FDiffuse.Assign(Value);
  392. end;
  393. procedure TgxShaderTextureSharingMaterial.SetEmission(const Value: TgxColor);
  394. begin
  395. FEmission.Assign(Value);
  396. end;
  397. procedure TgxShaderTextureSharingMaterial.SetLibMaterialName(const Value: TgxLibMaterialName);
  398. begin
  399. FLibMaterialName := Value;
  400. if (FLibMaterialName = '') or (FMaterialLibrary = nil) then
  401. FLibMaterial := nil
  402. else
  403. SetLibMaterial(FMaterialLibrary.LibMaterialByName(FLibMaterialName));
  404. end;
  405. procedure TgxShaderTextureSharingMaterial.SetLibMaterial(const Value: TgxLibMaterial);
  406. begin
  407. FLibMaterial := Value;
  408. if FLibMaterial <> nil then
  409. begin
  410. FLibMaterialName := FLibMaterial.DisplayName;
  411. FMaterialLibrary := TgxMaterialLibrary(TgxLibMaterials(Value.Collection).Owner);
  412. if not (csloading in GetTextureSharingShader.ComponentState) then
  413. begin
  414. FTexOffset.Assign(FLibMaterial.TextureOffset);
  415. FTexScale.Assign(FLibMaterial.TextureScale);
  416. FBlendingMode := FLibMaterial.Material.BlendingMode;
  417. fEmission.Assign(FLibMaterial.Material.FrontProperties.Emission);
  418. fAmbient.Assign(FLibMaterial.Material.FrontProperties.Ambient);
  419. fDiffuse.Assign(FLibMaterial.Material.FrontProperties.Diffuse);
  420. fSpecular.Assign(FLibMaterial.Material.FrontProperties.Specular);
  421. fShininess := FLibMaterial.Material.FrontProperties.Shininess;
  422. end;
  423. end;
  424. end;
  425. procedure TgxShaderTextureSharingMaterial.SetMaterialLibrary(const Value: TgxMaterialLibrary);
  426. begin
  427. FMaterialLibrary := Value;
  428. if (FLibMaterialName = '') or (FMaterialLibrary = nil) then
  429. FLibMaterial := nil
  430. else
  431. SetLibMaterial(FMaterialLibrary.LibMaterialByName(FLibMaterialName));
  432. end;
  433. procedure TgxShaderTextureSharingMaterial.SetShininess(const Value: TgxShininess);
  434. begin
  435. FShininess := Value;
  436. end;
  437. procedure TgxShaderTextureSharingMaterial.SetSpecular(const Value: TgxColor);
  438. begin
  439. FSpecular.Assign(Value);
  440. end;
  441. procedure TgxShaderTextureSharingMaterial.SetTexOffset(const Value: TgxCoordinates2);
  442. begin
  443. FTexOffset.Assign(Value);
  444. FNeedToUpdateTextureMatrix := True;
  445. end;
  446. procedure TgxShaderTextureSharingMaterial.SetTexScale(const Value: TgxCoordinates2);
  447. begin
  448. FTexScale.Assign(Value);
  449. FNeedToUpdateTextureMatrix := True;
  450. end;
  451. procedure TgxShaderTextureSharingMaterial.UnApply(var rci: TgxRenderContextInfo);
  452. begin
  453. if not Assigned(FLibMaterial) then
  454. Exit;
  455. if Assigned(FLibMaterial.Shader) then
  456. begin
  457. case FLibMaterial.Shader.ShaderStyle of
  458. ssLowLevel: FLibMaterial.Shader.UnApply(rci);
  459. ssReplace:
  460. begin
  461. FLibMaterial.Shader.UnApply(rci);
  462. Exit;
  463. end;
  464. end;
  465. end;
  466. FLibMaterial.Material.UnApply(rci);
  467. if not FLibMaterial.Material.Texture.Disabled then
  468. if not (GetTextureMatrixIsUnitary) then
  469. begin
  470. rci.gxStates.ResetTextureMatrix;
  471. end;
  472. if Assigned(FLibMaterial.Shader) then
  473. begin
  474. case FLibMaterial.Shader.ShaderStyle of
  475. ssHighLevel: FLibMaterial.Shader.UnApply(rci);
  476. end;
  477. end;
  478. end;
  479. //----------------------------
  480. // TgxShaderTextureSharing
  481. //----------------------------
  482. function TgxShaderTextureSharing.AddLibMaterial(const ALibMaterial: TgxLibMaterial): TgxShaderTextureSharingMaterial;
  483. begin
  484. Result := FMaterials.Add;
  485. Result.SetLibMaterial(ALibMaterial);
  486. end;
  487. constructor TgxShaderTextureSharing.Create(AOwner: TComponent);
  488. begin
  489. inherited;
  490. FMaterials := TgxShaderTextureSharingMaterials.Create(Self);
  491. ShaderStyle := ssReplace;
  492. end;
  493. destructor TgxShaderTextureSharing.Destroy;
  494. begin
  495. FMaterials.Free;
  496. inherited;
  497. end;
  498. procedure TgxShaderTextureSharing.DoApply(var rci: TgxRenderContextInfo; Sender: TObject);
  499. begin
  500. if Materials.Count > 0 then
  501. begin
  502. rci.gxStates.Enable(stDepthTest);
  503. rci.gxStates.DepthFunc := cfLEqual;
  504. Materials[0].Apply(rci);
  505. FCurrentPass := 1;
  506. end;
  507. end;
  508. function TgxShaderTextureSharing.DoUnApply(var rci: TgxRenderContextInfo): Boolean;
  509. begin
  510. Result := False;
  511. if Materials.Count > 0 then
  512. begin
  513. Materials[FCurrentPass - 1].UnApply(rci);
  514. if FCurrentPass < Materials.Count then
  515. begin
  516. Materials[FCurrentPass].Apply(rci);
  517. Inc(FCurrentPass);
  518. Result := True;
  519. end
  520. else
  521. begin
  522. rci.gxStates.DepthFunc := cfLess;
  523. rci.gxStates.Disable(stBlend);
  524. rci.gxStates.Disable(stAlphaTest);
  525. FCurrentPass := 0;
  526. end;
  527. end;
  528. end;
  529. function TgxShaderTextureSharing.FindLibMaterial(const ALibMaterial: TgxLibMaterial): TgxShaderTextureSharingMaterial;
  530. var
  531. I: Integer;
  532. begin
  533. Result := nil;
  534. for I := 0 to FMaterials.Count - 1 do
  535. if FMaterials[I].FLibMaterial = ALibMaterial then
  536. begin
  537. Result := FMaterials[I];
  538. Break;
  539. end;
  540. end;
  541. procedure TgxShaderTextureSharing.Notification(AComponent: TComponent; Operation: TOperation);
  542. var
  543. I: Integer;
  544. begin
  545. inherited;
  546. if Operation = opRemove then
  547. begin
  548. if AComponent is TgxMaterialLibrary then
  549. begin
  550. for I := 0 to Materials.Count - 1 do
  551. begin
  552. if Materials.Items[I].MaterialLibrary = AComponent then
  553. Materials.Items[I].MaterialLibrary := nil;
  554. end;
  555. end;
  556. end;
  557. end;
  558. procedure TgxShaderTextureSharing.SetMaterials(const Value: TgxShaderTextureSharingMaterials);
  559. begin
  560. FMaterials.Assign(Value);
  561. end;
  562. //----------------------------------------
  563. // TgxShaderTextureSharingMaterials
  564. //----------------------------------------
  565. function TgxShaderTextureSharingMaterials.Add: TgxShaderTextureSharingMaterial;
  566. begin
  567. Result := (inherited Add) as TgxShaderTextureSharingMaterial;
  568. end;
  569. constructor TgxShaderTextureSharingMaterials.Create(AOwner: TgxShaderTextureSharing);
  570. begin
  571. inherited Create(AOwner, TgxShaderTextureSharingMaterial);
  572. end;
  573. function TgxShaderTextureSharingMaterials.GetItems(const AIndex: Integer): TgxShaderTextureSharingMaterial;
  574. begin
  575. Result := (inherited Items[AIndex]) as TgxShaderTextureSharingMaterial;
  576. end;
  577. function TgxShaderTextureSharingMaterials.GetParent: TgxShaderTextureSharing;
  578. begin
  579. Result := TgxShaderTextureSharing(GetOwner);
  580. end;
  581. procedure TgxShaderTextureSharingMaterials.SetItems(const AIndex: Integer; const Value: TgxShaderTextureSharingMaterial);
  582. begin
  583. inherited Items[AIndex] := Value;
  584. end;
  585. // ------------------
  586. // ------------------ TgxTexCombineShader ------------------
  587. // ------------------
  588. constructor TgxTexCombineShader.Create(AOwner: TComponent);
  589. begin
  590. inherited;
  591. ShaderStyle := ssLowLevel;
  592. FCombiners := TStringList.Create;
  593. TStringList(FCombiners).OnChange := NotifyChange;
  594. FCombinerIsValid := True;
  595. FCommandCache := nil;
  596. end;
  597. destructor TgxTexCombineShader.Destroy;
  598. begin
  599. if Assigned(currentLibMaterial3) then
  600. currentLibMaterial3.UnregisterUser(Self);
  601. if Assigned(currentLibMaterial4) then
  602. currentLibMaterial4.UnregisterUser(Self);
  603. inherited;
  604. FCombiners.Free;
  605. end;
  606. procedure TgxTexCombineShader.Notification(AComponent: TComponent; Operation: TOperation);
  607. begin
  608. if (FMaterialLibrary = AComponent) and (Operation = opRemove) then
  609. begin
  610. NotifyLibMaterial3Destruction;
  611. NotifyLibMaterial4Destruction;
  612. FMaterialLibrary := nil;
  613. end;
  614. inherited;
  615. end;
  616. procedure TgxTexCombineShader.NotifyChange(Sender: TObject);
  617. begin
  618. FCombinerIsValid := True;
  619. FCommandCache := nil;
  620. inherited NotifyChange(Sender);
  621. end;
  622. procedure TgxTexCombineShader.NotifyLibMaterial3Destruction;
  623. begin
  624. FLibMaterial3Name := '';
  625. currentLibMaterial3 := nil;
  626. end;
  627. procedure TgxTexCombineShader.NotifyLibMaterial4Destruction;
  628. begin
  629. FLibMaterial4Name := '';
  630. currentLibMaterial4 := nil;
  631. end;
  632. procedure TgxTexCombineShader.SetMaterialLibrary(const val: TgxMaterialLibrary);
  633. begin
  634. FMaterialLibrary := val;
  635. SetLibMaterial3Name(LibMaterial3Name);
  636. SetLibMaterial4Name(LibMaterial4Name);
  637. end;
  638. procedure TgxTexCombineShader.SetLibMaterial3Name(const val: TgxLibMaterialName);
  639. var
  640. newLibMaterial: TgxLibMaterial;
  641. begin
  642. // locate new libmaterial
  643. if Assigned(FMaterialLibrary) then
  644. newLibMaterial := MaterialLibrary.Materials.GetLibMaterialByName(val)
  645. else
  646. newLibMaterial := nil;
  647. FLibMaterial3Name := val;
  648. // unregister if required
  649. if newLibMaterial <> currentLibMaterial3 then
  650. begin
  651. // unregister from old
  652. if Assigned(currentLibMaterial3) then
  653. currentLibMaterial3.UnregisterUser(Self);
  654. currentLibMaterial3 := newLibMaterial;
  655. // register with new
  656. if Assigned(currentLibMaterial3) then
  657. currentLibMaterial3.RegisterUser(Self);
  658. NotifyChange(Self);
  659. end;
  660. end;
  661. procedure TgxTexCombineShader.SetLibMaterial4Name(const val: TgxLibMaterialName);
  662. var
  663. newLibMaterial: TgxLibMaterial;
  664. begin
  665. // locate new libmaterial
  666. if Assigned(FMaterialLibrary) then
  667. newLibMaterial := MaterialLibrary.Materials.GetLibMaterialByName(val)
  668. else
  669. newLibMaterial := nil;
  670. FLibMaterial4Name := val;
  671. // unregister if required
  672. if newLibMaterial <> currentLibMaterial4 then
  673. begin
  674. // unregister from old
  675. if Assigned(currentLibMaterial4) then
  676. currentLibMaterial4.UnregisterUser(Self);
  677. currentLibMaterial4 := newLibMaterial;
  678. // register with new
  679. if Assigned(currentLibMaterial4) then
  680. currentLibMaterial4.RegisterUser(Self);
  681. NotifyChange(Self);
  682. end;
  683. end;
  684. procedure TgxTexCombineShader.DoInitialize(var rci: TgxRenderContextInfo; Sender: TObject);
  685. begin
  686. end;
  687. procedure TgxTexCombineShader.DoApply(var rci: TgxRenderContextInfo; Sender: TObject);
  688. var
  689. n, units: Integer;
  690. begin
  691. // if not GL_ARB_multitexture then Exit;
  692. FApplied3 := False;
  693. FApplied4 := False;
  694. if FCombinerIsValid and (FDesignTimeEnabled or (not (csDesigning in ComponentState))) then
  695. begin
  696. try
  697. if Assigned(currentLibMaterial3) or Assigned(currentLibMaterial4) then
  698. begin
  699. glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, @n);
  700. units := 0;
  701. if Assigned(currentLibMaterial3) and (n >= 3) then
  702. begin
  703. with currentLibMaterial3.Material.Texture do
  704. begin
  705. if Enabled then
  706. begin
  707. if currentLibMaterial3.TextureMatrixIsIdentity then
  708. ApplyAsTextureN(3, rci)
  709. else
  710. ApplyAsTextureN(3, rci, @currentLibMaterial3.TextureMatrix.X.X);
  711. // ApplyAsTextureN(3, rci, currentLibMaterial3);
  712. Inc(units, 4);
  713. FApplied3 := True;
  714. end;
  715. end;
  716. end;
  717. if Assigned(currentLibMaterial4) and (n >= 4) then
  718. begin
  719. with currentLibMaterial4.Material.Texture do
  720. begin
  721. if Enabled then
  722. begin
  723. if currentLibMaterial4.TextureMatrixIsIdentity then
  724. ApplyAsTextureN(4, rci)
  725. else
  726. ApplyAsTextureN(4, rci, @currentLibMaterial4.TextureMatrix.X.X);
  727. // ApplyAsTextureN(4, rci, currentLibMaterial4);
  728. Inc(units, 8);
  729. FApplied4 := True;
  730. end;
  731. end;
  732. end;
  733. if units > 0 then
  734. xglMapTexCoordToArbitraryAdd(units);
  735. end;
  736. if Length(FCommandCache) = 0 then
  737. FCommandCache := GetTextureCombiners(FCombiners);
  738. for n := 0 to High(FCommandCache) do
  739. begin
  740. rci.gxStates.ActiveTexture := FCommandCache[n].ActiveUnit;
  741. glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
  742. glTexEnvi(GL_TEXTURE_ENV, FCommandCache[n].Arg1, FCommandCache[n].Arg2);
  743. end;
  744. rci.gxStates.ActiveTexture := 0;
  745. except
  746. on E: Exception do
  747. begin
  748. FCombinerIsValid := False;
  749. InformationDlg(E.ClassName + ': ' + E.Message);
  750. end;
  751. end;
  752. end;
  753. end;
  754. function TgxTexCombineShader.DoUnApply(var rci: TgxRenderContextInfo): Boolean;
  755. begin
  756. if FApplied3 then
  757. with currentLibMaterial3.Material.Texture do
  758. UnApplyAsTextureN(3, rci, (not currentLibMaterial3.TextureMatrixIsIdentity));
  759. if FApplied4 then
  760. with currentLibMaterial4.Material.Texture do
  761. UnApplyAsTextureN(4, rci, (not currentLibMaterial4.TextureMatrixIsIdentity));
  762. Result := False;
  763. end;
  764. procedure TgxTexCombineShader.DoFinalize;
  765. begin
  766. end;
  767. procedure TgxTexCombineShader.SetCombiners(const val: TStringList);
  768. begin
  769. if val <> FCombiners then
  770. begin
  771. FCombiners.Assign(val);
  772. NotifyChange(Self);
  773. end;
  774. end;
  775. procedure TgxTexCombineShader.SetDesignTimeEnabled(const val: Boolean);
  776. begin
  777. if val <> FDesignTimeEnabled then
  778. begin
  779. FDesignTimeEnabled := val;
  780. NotifyChange(Self);
  781. end;
  782. end;
  783. //----------------------------------------------------------------------------
  784. initialization
  785. //----------------------------------------------------------------------------
  786. RegisterClasses([TgxShaderTextureSharing, TgxShaderTextureSharingMaterials,
  787. TgxShaderTextureSharingMaterial]);
  788. end.