GXSL.ShaderCombiner.pas 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. //
  2. // The graphics engine GLXEngine. The unit of GXScene for Delphi
  3. //
  4. unit GXSL.ShaderCombiner;
  5. (*
  6. Allows to combine shaders in different sequences.
  7. Note, that can't just take 2 random shaders and combine them, because
  8. shaders often override the objects material and vertex data with a total
  9. disregard to what existed before it. But in some cases, especially with
  10. multipass shaders, this unit does magic and allows to reuse and upgrade
  11. previously written shaders.
  12. *)
  13. interface
  14. {$I Stage.Defines.inc}
  15. uses
  16. System.Classes,
  17. GXS.Material,
  18. GXS.Scene,
  19. Stage.VectorGeometry,
  20. Stage.Strings,
  21. GXS.RenderContextInfo;
  22. type
  23. (* MP - multipass, SP-singlepass, AP - anypass (single or multi)
  24. One-Two or Two-One determines the order of how the shaders should be applied
  25. For example, sctTwoMPOneSP means that first one will be applied Shader Two,
  26. which can be a multipass shader, then Shader One is applied, which should be
  27. a singlepass shader.
  28. sctOneMPTwoSP and sctTwoMPOneSP modes are actualy quite Str@nge,
  29. because... well look at the code yourself
  30. TODO: Add more modes here, including sctOneAPTwoAP, which should be the
  31. default one.
  32. By the way, I admit - the names do look stupid, and if someone gives them
  33. proper names, I will be only glad. *)
  34. TgxShaderCombinerType = (sctOneSPTwoAP, sctTwoSPOneAP,
  35. sctOneMPTwoSP, sctTwoMPOneSP
  36. );
  37. TgxCustomShaderCombiner = class(TgxShader)
  38. private
  39. FCurrentPass: Integer;
  40. FCombinerType: TgxShaderCombinerType;
  41. FShaderOne: TgxShader;
  42. FShaderTwo: TgxShader;
  43. procedure SetShaderOne(const Value: TgxShader);
  44. procedure SetShaderTwo(const Value: TgxShader);
  45. protected
  46. procedure DoApply(var rci : TgxRenderContextInfo; Sender : TObject); override;
  47. function DoUnApply(var rci: TgxRenderContextInfo): Boolean; override;
  48. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  49. property CombinerType: TgxShaderCombinerType read FCombinerType write FCombinerType default sctOneSPTwoAP;
  50. property ShaderOne: TgxShader read FShaderOne write SetShaderOne;
  51. property ShaderTwo: TgxShader read FShaderTwo write SetShaderTwo;
  52. property CurrentPass : Integer read FCurrentPass stored False;
  53. public
  54. constructor Create(AOwner: TComponent); override;
  55. function ShaderSupported: Boolean; override;
  56. procedure Assign(Source: TPersistent); override;
  57. end;
  58. TgxShaderCombiner = class(TgxCustomShaderCombiner)
  59. published
  60. property CombinerType;
  61. property ShaderOne;
  62. property ShaderTwo;
  63. property ShaderStyle;
  64. end;
  65. //-------------------------------------------------
  66. implementation
  67. //-------------------------------------------------
  68. //-------------------------------------------------
  69. // TgxCustomShaderCombiner
  70. //-------------------------------------------------
  71. procedure TgxCustomShaderCombiner.Assign(Source: TPersistent);
  72. begin
  73. inherited;
  74. if Source is TgxCustomShaderCombiner then
  75. begin
  76. SetShaderOne(TgxCustomShaderCombiner(Source).FShaderOne);
  77. SetShaderTwo(TgxCustomShaderCombiner(Source).FShaderTwo);
  78. end;
  79. end;
  80. constructor TgxCustomShaderCombiner.Create(AOwner: TComponent);
  81. begin
  82. inherited;
  83. FCombinerType := sctOneSPTwoAP;
  84. end;
  85. procedure TgxCustomShaderCombiner.DoApply(var rci: TgxRenderContextInfo;
  86. Sender: TObject);
  87. begin
  88. if (csDesigning in ComponentState) then Exit;
  89. Assert((FShaderOne <> nil) and (FShaderTwo <> nil));
  90. FCurrentPass:=1;
  91. case FCombinerType of
  92. sctOneMPTwoSP:
  93. begin
  94. FShaderOne.Apply(rci, Self);
  95. FShaderTwo.Apply(rci, Self);
  96. end;
  97. sctTwoMPOneSP:
  98. begin
  99. FShaderTwo.Apply(rci, Self);
  100. FShaderOne.Apply(rci, Self);
  101. end;
  102. sctOneSPTwoAP:
  103. begin
  104. FShaderOne.Apply(rci, Self);
  105. end;
  106. sctTwoSPOneAP:
  107. begin
  108. FShaderTwo.Apply(rci, Self);
  109. end;
  110. else
  111. Assert(False, strErrorEx + strUnknownType);
  112. end;
  113. end;
  114. function TgxCustomShaderCombiner.DoUnApply(var rci: TgxRenderContextInfo): Boolean;
  115. begin
  116. case FCombinerType of
  117. sctOneMPTwoSP:
  118. begin
  119. if FShaderOne.UnApply(rci) then
  120. Result := True
  121. else
  122. Result := FShaderTwo.UnApply(rci);
  123. end;
  124. sctTwoMPOneSP:
  125. begin
  126. if FShaderTwo.UnApply(rci) then
  127. Result := True
  128. else
  129. Result := FShaderOne.UnApply(rci);
  130. end;
  131. sctOneSPTwoAP:
  132. begin
  133. if FCurrentPass = 1 then
  134. begin
  135. FShaderOne.UnApply(rci);
  136. FShaderTwo.Apply(rci, Self);
  137. Result := True;
  138. end
  139. else
  140. Result := FShaderTwo.UnApply(rci);
  141. end;
  142. sctTwoSPOneAP:
  143. begin
  144. if FCurrentPass = 1 then
  145. begin
  146. FShaderTwo.UnApply(rci);
  147. FShaderOne.Apply(rci, Self);
  148. Result := True;
  149. end
  150. else
  151. Result := FShaderOne.UnApply(rci);
  152. end;
  153. else
  154. begin
  155. Result := False;
  156. Assert(False, strErrorEx + strUnknownType);
  157. end;
  158. end;
  159. Inc(FCurrentPass);
  160. end;
  161. procedure TgxCustomShaderCombiner.Notification(AComponent: TComponent;
  162. Operation: TOperation);
  163. begin
  164. inherited;
  165. if Operation = opRemove then
  166. begin
  167. if AComponent = FShaderOne then
  168. FShaderOne := nil
  169. else if AComponent = FShaderTwo then
  170. FShaderTwo := nil;
  171. end;
  172. end;
  173. procedure TgxCustomShaderCombiner.SetShaderOne(const Value: TgxShader);
  174. begin
  175. if FShaderOne <> nil then
  176. FShaderOne.RemoveFreeNotification(Self);
  177. FShaderOne := Value;
  178. if FShaderOne <> nil then
  179. FShaderOne.FreeNotification(Self);
  180. end;
  181. procedure TgxCustomShaderCombiner.SetShaderTwo(const Value: TgxShader);
  182. begin
  183. if FShaderTwo <> nil then
  184. FShaderTwo.RemoveFreeNotification(Self);
  185. FShaderTwo := Value;
  186. if FShaderTwo <> nil then
  187. FShaderTwo.FreeNotification(Self);
  188. end;
  189. function TgxCustomShaderCombiner.ShaderSupported: Boolean;
  190. begin
  191. Result := (FShaderOne <> nil) and (FShaderTwo <> nil) and
  192. FShaderOne.ShaderSupported and FShaderTwo.ShaderSupported;
  193. end;
  194. initialization
  195. RegisterClasses([TgxCustomShaderCombiner, TgxShaderCombiner]);
  196. end.