GLSL.TextureShaders.pas 27 KB

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