2
0

GLSL.TextureShaders.pas 27 KB

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