GLS.ShaderTexCombine.pas 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. //
  2. // This unit is part of the GLScene Engine, http://glscene.org
  3. //
  4. unit GLS.ShaderTexCombine;
  5. (* A shader that allows texture combiner setup. *)
  6. interface
  7. {$I GLScene.inc}
  8. uses
  9. Winapi.OpenGL,
  10. Winapi.OpenGLext,
  11. System.Classes,
  12. System.SysUtils,
  13. GLTexture,
  14. GLMaterial,
  15. GLRenderContextInfo,
  16. GLTextureCombiners,
  17. OpenGLTokens,
  18. GLState,
  19. XOpenGL,
  20. GLContext,
  21. GLS.Utils;
  22. type
  23. // A shader that can setup the texture combiner.
  24. TGLTexCombineShader = class(TGLShader)
  25. private
  26. FCombiners: TStringList;
  27. FCommandCache: TCombinerCache;
  28. FCombinerIsValid: Boolean; // to avoid reparsing invalid stuff
  29. FDesignTimeEnabled: Boolean;
  30. FMaterialLibrary: TGLMaterialLibrary;
  31. FLibMaterial3Name: TGLLibMaterialName;
  32. currentLibMaterial3: TGLLibMaterial;
  33. FLibMaterial4Name: TGLLibMaterialName;
  34. currentLibMaterial4: TGLLibMaterial;
  35. FApplied3, FApplied4: Boolean;
  36. protected
  37. procedure SetCombiners(const val: TStringList);
  38. procedure SetDesignTimeEnabled(const val: Boolean);
  39. procedure SetMaterialLibrary(const val: TGLMaterialLibrary);
  40. procedure SetLibMaterial3Name(const val: TGLLibMaterialName);
  41. procedure SetLibMaterial4Name(const val: TGLLibMaterialName);
  42. procedure NotifyLibMaterial3Destruction;
  43. procedure NotifyLibMaterial4Destruction;
  44. procedure DoInitialize(var rci: TGLRenderContextInfo; Sender: TObject); override;
  45. procedure DoApply(var rci: TGLRenderContextInfo; Sender: TObject); override;
  46. function DoUnApply(var rci: TGLRenderContextInfo): Boolean; override;
  47. procedure DoFinalize; override;
  48. public
  49. constructor Create(AOwner: TComponent); override;
  50. destructor Destroy; override;
  51. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  52. procedure NotifyChange(Sender: TObject); override;
  53. published
  54. property Combiners: TStringList read FCombiners write SetCombiners;
  55. property DesignTimeEnabled: Boolean read FDesignTimeEnabled write SetDesignTimeEnabled;
  56. property MaterialLibrary: TGLMaterialLibrary read FMaterialLibrary write SetMaterialLibrary;
  57. property LibMaterial3Name: TGLLibMaterialName read FLibMaterial3Name write SetLibMaterial3Name;
  58. property LibMaterial4Name: TGLLibMaterialName read FLibMaterial4Name write SetLibMaterial4Name;
  59. end;
  60. // ------------------------------------------------------------------
  61. implementation
  62. // ------------------------------------------------------------------
  63. // ------------------
  64. // ------------------ TGLTexCombineShader ------------------
  65. // ------------------
  66. constructor TGLTexCombineShader.Create(AOwner: TComponent);
  67. begin
  68. inherited;
  69. ShaderStyle := ssLowLevel;
  70. FCombiners := TStringList.Create;
  71. TStringList(FCombiners).OnChange := NotifyChange;
  72. FCombinerIsValid := True;
  73. FCommandCache := nil;
  74. end;
  75. destructor TGLTexCombineShader.Destroy;
  76. begin
  77. if Assigned(currentLibMaterial3) then
  78. currentLibMaterial3.UnregisterUser(Self);
  79. if Assigned(currentLibMaterial4) then
  80. currentLibMaterial4.UnregisterUser(Self);
  81. inherited;
  82. FCombiners.Free;
  83. end;
  84. procedure TGLTexCombineShader.Notification(AComponent: TComponent; Operation: TOperation);
  85. begin
  86. if (FMaterialLibrary = AComponent) and (Operation = opRemove) then
  87. begin
  88. NotifyLibMaterial3Destruction;
  89. NotifyLibMaterial4Destruction;
  90. FMaterialLibrary := nil;
  91. end;
  92. inherited;
  93. end;
  94. procedure TGLTexCombineShader.NotifyChange(Sender: TObject);
  95. begin
  96. FCombinerIsValid := True;
  97. FCommandCache := nil;
  98. inherited NotifyChange(Sender);
  99. end;
  100. procedure TGLTexCombineShader.NotifyLibMaterial3Destruction;
  101. begin
  102. FLibMaterial3Name := '';
  103. currentLibMaterial3 := nil;
  104. end;
  105. procedure TGLTexCombineShader.NotifyLibMaterial4Destruction;
  106. begin
  107. FLibMaterial4Name := '';
  108. currentLibMaterial4 := nil;
  109. end;
  110. procedure TGLTexCombineShader.SetMaterialLibrary(const val: TGLMaterialLibrary);
  111. begin
  112. FMaterialLibrary := val;
  113. SetLibMaterial3Name(LibMaterial3Name);
  114. SetLibMaterial4Name(LibMaterial4Name);
  115. end;
  116. procedure TGLTexCombineShader.SetLibMaterial3Name(const val: TGLLibMaterialName);
  117. var
  118. newLibMaterial: TGLLibMaterial;
  119. begin
  120. // locate new libmaterial
  121. if Assigned(FMaterialLibrary) then
  122. newLibMaterial := MaterialLibrary.Materials.GetLibMaterialByName(val)
  123. else
  124. newLibMaterial := nil;
  125. FLibMaterial3Name := val;
  126. // unregister if required
  127. if newLibMaterial <> currentLibMaterial3 then
  128. begin
  129. // unregister from old
  130. if Assigned(currentLibMaterial3) then
  131. currentLibMaterial3.UnregisterUser(Self);
  132. currentLibMaterial3 := newLibMaterial;
  133. // register with new
  134. if Assigned(currentLibMaterial3) then
  135. currentLibMaterial3.RegisterUser(Self);
  136. NotifyChange(Self);
  137. end;
  138. end;
  139. procedure TGLTexCombineShader.SetLibMaterial4Name(const val: TGLLibMaterialName);
  140. var
  141. newLibMaterial: TGLLibMaterial;
  142. begin
  143. // locate new libmaterial
  144. if Assigned(FMaterialLibrary) then
  145. newLibMaterial := MaterialLibrary.Materials.GetLibMaterialByName(val)
  146. else
  147. newLibMaterial := nil;
  148. FLibMaterial4Name := val;
  149. // unregister if required
  150. if newLibMaterial <> currentLibMaterial4 then
  151. begin
  152. // unregister from old
  153. if Assigned(currentLibMaterial4) then
  154. currentLibMaterial4.UnregisterUser(Self);
  155. currentLibMaterial4 := newLibMaterial;
  156. // register with new
  157. if Assigned(currentLibMaterial4) then
  158. currentLibMaterial4.RegisterUser(Self);
  159. NotifyChange(Self);
  160. end;
  161. end;
  162. procedure TGLTexCombineShader.DoInitialize(var rci: TGLRenderContextInfo; Sender: TObject);
  163. begin
  164. end;
  165. procedure TGLTexCombineShader.DoApply(var rci: TGLRenderContextInfo; Sender: TObject);
  166. var
  167. n, units: Integer;
  168. begin
  169. if not GL.ARB_multitexture then
  170. Exit;
  171. FApplied3 := False;
  172. FApplied4 := False;
  173. if FCombinerIsValid and (FDesignTimeEnabled or (not (csDesigning in ComponentState))) then
  174. begin
  175. try
  176. if Assigned(currentLibMaterial3) or Assigned(currentLibMaterial4) then
  177. begin
  178. gl.GetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, @n);
  179. units := 0;
  180. if Assigned(currentLibMaterial3) and (n >= 3) then
  181. begin
  182. with currentLibMaterial3.Material.Texture do
  183. begin
  184. if Enabled then
  185. begin
  186. if currentLibMaterial3.TextureMatrixIsIdentity then
  187. ApplyAsTextureN(3, rci)
  188. else
  189. ApplyAsTextureN(3, rci, @currentLibMaterial3.TextureMatrix.V[0].X);
  190. // ApplyAsTextureN(3, rci, currentLibMaterial3);
  191. Inc(units, 4);
  192. FApplied3 := True;
  193. end;
  194. end;
  195. end;
  196. if Assigned(currentLibMaterial4) and (n >= 4) then
  197. begin
  198. with currentLibMaterial4.Material.Texture do
  199. begin
  200. if Enabled then
  201. begin
  202. if currentLibMaterial4.TextureMatrixIsIdentity then
  203. ApplyAsTextureN(4, rci)
  204. else
  205. ApplyAsTextureN(4, rci, @currentLibMaterial4.TextureMatrix.V[0].X);
  206. // ApplyAsTextureN(4, rci, currentLibMaterial4);
  207. Inc(units, 8);
  208. FApplied4 := True;
  209. end;
  210. end;
  211. end;
  212. if units > 0 then
  213. xgl.MapTexCoordToArbitraryAdd(units);
  214. end;
  215. if Length(FCommandCache) = 0 then
  216. FCommandCache := GetTextureCombiners(FCombiners);
  217. for n := 0 to High(FCommandCache) do
  218. begin
  219. rci.GLStates.ActiveTexture := FCommandCache[n].ActiveUnit;
  220. gl.TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
  221. gl.TexEnvi(GL_TEXTURE_ENV, FCommandCache[n].Arg1, FCommandCache[n].Arg2);
  222. end;
  223. rci.GLStates.ActiveTexture := 0;
  224. except
  225. on E: Exception do
  226. begin
  227. FCombinerIsValid := False;
  228. InformationDlg(E.ClassName + ': ' + E.Message);
  229. end;
  230. end;
  231. end;
  232. end;
  233. function TGLTexCombineShader.DoUnApply(var rci: TGLRenderContextInfo): Boolean;
  234. begin
  235. if FApplied3 then
  236. with currentLibMaterial3.Material.Texture do
  237. UnApplyAsTextureN(3, rci, (not currentLibMaterial3.TextureMatrixIsIdentity));
  238. if FApplied4 then
  239. with currentLibMaterial4.Material.Texture do
  240. UnApplyAsTextureN(4, rci, (not currentLibMaterial4.TextureMatrixIsIdentity));
  241. Result := False;
  242. end;
  243. procedure TGLTexCombineShader.DoFinalize;
  244. begin
  245. end;
  246. procedure TGLTexCombineShader.SetCombiners(const val: TStringList);
  247. begin
  248. if val <> FCombiners then
  249. begin
  250. FCombiners.Assign(val);
  251. NotifyChange(Self);
  252. end;
  253. end;
  254. procedure TGLTexCombineShader.SetDesignTimeEnabled(const val: Boolean);
  255. begin
  256. if val <> FDesignTimeEnabled then
  257. begin
  258. FDesignTimeEnabled := val;
  259. NotifyChange(Self);
  260. end;
  261. end;
  262. end.