GXS.CgBombShader.pas 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. //
  2. // The graphics engine GXScene
  3. //
  4. unit GXS.CgBombShader;
  5. (* Just a good looking shader *)
  6. interface
  7. uses
  8. System.Classes,
  9. System.SysUtils,
  10. GXS.Texture,
  11. GXS.Cadencer,
  12. GXS.Context,
  13. Stage.Strings,
  14. GXS.Material,
  15. GXS.RenderContextInfo,
  16. Stage.TextureFormat,
  17. GXS.State,
  18. Cg.GL,
  19. GXS.CgShader;
  20. type
  21. ECGxBombShaderException = class(ECGxShaderException);
  22. TCGxBombShaderTextureSource = (stsPrimaryTexture, stsSecondadyTexture,
  23. stsThirdTexture, stsUserSelectedTexture);
  24. // Just a good-looking shader.
  25. TCGxCustomBombShader = class(TCGxCadencableCustomShader, IgxMaterialLibrarySupported)
  26. private
  27. FMaterialLibrary: TgxAbstractMaterialLibrary;
  28. FGradientTexture: TgxTexture;
  29. FMainTexture: TgxTexture;
  30. FMainTextureName: TgxLibMaterialName;
  31. FGradientTextureName: TgxLibMaterialName;
  32. FSharpness: Single;
  33. FColorRange: Single;
  34. FSpeed: Single;
  35. FDisplacement: Single;
  36. FAlpha: Single;
  37. FTurbDensity: Single;
  38. FColorSharpness: Single;
  39. FGradientTextureShare: Single;
  40. FMainTextureShare: Single;
  41. {$IFNDEF USE_OPTIMIZATIONS}
  42. FMainTextureSource: TCGxBombShaderTextureSource;
  43. {$ENDIF}
  44. procedure SetGradientTexture(const Value: TgxTexture);
  45. procedure SetMainTexture(const Value: TgxTexture);
  46. function GetMainTextureName: TgxLibMaterialName;
  47. procedure SetMainTextureName(const Value: TgxLibMaterialName);
  48. function GetGradientTextureName: TgxLibMaterialName;
  49. procedure SetGradientTextureName(const Value: TgxLibMaterialName);
  50. function StoreColorRange: Boolean;
  51. function StoreColorSharpness: Boolean;
  52. function StoreDisplacement: Boolean;
  53. function StoreGradientTextureShare: Boolean;
  54. function StoreSharpness: Boolean;
  55. function StoreSpeed: Boolean;
  56. function StoreTurbDensity: Boolean;
  57. function StoreMainTextureShare: Boolean;
  58. // Implementing IGLMaterialLibrarySupported.
  59. function GetMaterialLibrary: TgxAbstractMaterialLibrary;
  60. protected
  61. procedure DoInitialize(var rci : TgxRenderContextInfo; Sender : TObject); override;
  62. procedure DoApply(var rci: TgxRenderContextInfo; Sender: TObject); override;
  63. procedure OnApplyVP(CgProgram: TCGxProgram; Sender: TObject); virtual;
  64. procedure OnApplyFP(CgProgram: TCGxProgram; Sender: TObject); virtual;
  65. procedure OnUnApplyFP(CgProgram: TCGxProgram); virtual;
  66. procedure SetMaterialLibrary(const Value: TgxAbstractMaterialLibrary); virtual;
  67. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  68. public
  69. constructor Create(AOwner: TComponent); override;
  70. property MainTexture: TgxTexture read FMainTexture write SetMainTexture;
  71. property MainTextureName: TgxLibMaterialName read GetMainTextureName write SetMainTextureName;
  72. property GradientTexture: TgxTexture read FGradientTexture write SetGradientTexture;
  73. property GradientTextureName: TgxLibMaterialName read GetGradientTextureName write SetGradientTextureName;
  74. property GradientTextureShare: Single read FGradientTextureShare write FGradientTextureShare stored StoreGradientTextureShare;
  75. property MainTextureShare: Single read FMainTextureShare write FMainTextureShare stored StoreMainTextureShare;
  76. property Alpha: Single read FAlpha write FAlpha;
  77. property Displacement: Single read FDisplacement write FDisplacement stored StoreDisplacement;
  78. property Sharpness: Single read FSharpness write FSharpness stored StoreSharpness;
  79. property ColorSharpness: Single read FColorSharpness write FColorSharpness stored StoreColorSharpness;
  80. property Speed: Single read FSpeed write FSpeed stored StoreSpeed;
  81. property TurbDensity: Single read FTurbDensity write FTurbDensity stored StoreTurbDensity;
  82. property ColorRange: Single read FColorRange write FColorRange stored StoreColorRange;
  83. {$IFNDEF USE_OPTIMIZATIONS}
  84. property MainTextureSource: TCGxBombShaderTextureSource read FMainTextureSource write FMainTextureSource;
  85. {$ENDIF}
  86. property MaterialLibrary: TgxAbstractMaterialLibrary read FMaterialLibrary write SetMaterialLibrary;
  87. end;
  88. TCGxBombShader = class(TCGxCustomBombShader)
  89. protected
  90. procedure DoInitialize(var rci : TgxRenderContextInfo; Sender : TObject); override;
  91. procedure DoApply(var rci: TgxRenderContextInfo; Sender: TObject); override;
  92. procedure OnApplyVP(CgProgram: TCGxProgram; Sender: TObject); override;
  93. procedure OnApplyFP(CgProgram: TCGxProgram; Sender: TObject); override;
  94. procedure OnUnApplyFP(CgProgram: TCGxProgram); override;
  95. published
  96. property MainTextureShare;
  97. property MainTextureName;
  98. property GradientTextureShare;
  99. property GradientTextureName;
  100. property Alpha;
  101. property Cadencer;
  102. property Displacement;
  103. property Sharpness;
  104. property ColorSharpness;
  105. property Speed;
  106. property TurbDensity;
  107. property ColorRange;
  108. property MaterialLibrary;
  109. property DesignEnable;
  110. end;
  111. //=============================================================
  112. implementation
  113. //=============================================================
  114. const
  115. EPS = 0.001;
  116. //--------------------------------
  117. // TCGxCustomBombShader
  118. //--------------------------------
  119. constructor TCGxCustomBombShader.Create(AOwner: TComponent);
  120. begin
  121. inherited;
  122. VertexProgram.OnApply := OnApplyVP;
  123. VertexProgram.ManualNotification := True;
  124. FragmentProgram.OnApply := OnApplyFP;
  125. FragmentProgram.OnUnApply := OnUnApplyFP;
  126. FragmentProgram.ManualNotification := True;
  127. FAlpha := 0.7;
  128. FDisplacement := 0.3;
  129. FSharpness := 3;
  130. FColorSharpness := 1;
  131. FSpeed := 0.3;
  132. FTurbDensity := 1;
  133. FColorRange := 0.24;
  134. FGradientTextureShare := 0.7;
  135. FMainTextureShare := 0.7;
  136. {$IFNDEF USE_OPTIMIZATIONS}
  137. FMainTextureSource := stsUserSelectedTexture;
  138. {$ENDIF}
  139. end;
  140. procedure TCGxCustomBombShader.DoApply(var rci: TgxRenderContextInfo; Sender: TObject);
  141. begin
  142. VertexProgram.Apply(rci, Sender);
  143. FragmentProgram.Apply(rci, Sender);
  144. {$IFDEF USE_OPTIMIZATIONS}
  145. if FMainTexture <> nil then
  146. FragmentProgram.ParamByName('MainTextureSampler').SetAsTexture2D(FMainTexture.Handle);
  147. {$ELSE}
  148. case FMainTextureSource of
  149. stsPrimaryTexture: FragmentProgram.ParamByName('MainTextureSampler').SetAsTexture2D(rci.gxStates.TextureBinding[0, ttTexture2D]);
  150. stsSecondadyTexture: FragmentProgram.ParamByName('MainTextureSampler').SetAsTexture2D(rci.gxStates.TextureBinding[1, ttTexture2D]);
  151. stsThirdTexture: FragmentProgram.ParamByName('MainTextureSampler').SetAsTexture2D(rci.gxStates.TextureBinding[2, ttTexture2D]);
  152. stsUserSelectedTexture:
  153. begin
  154. if FMainTexture <> nil then
  155. FragmentProgram.ParamByName('MainTextureSampler').SetAsTexture2D(FMainTexture.Handle);
  156. end;
  157. end;
  158. {$ENDIF}
  159. end;
  160. procedure TCGxCustomBombShader.DoInitialize(var rci : TgxRenderContextInfo; Sender : TObject);
  161. begin
  162. if FGradientTexture = nil then
  163. try
  164. FGradientTexture := TgxMaterialLibrary(FMaterialLibrary).TextureByName(FGradientTextureName);
  165. except
  166. Enabled := False;
  167. raise;
  168. end;
  169. if FMainTexture = nil then
  170. try
  171. FMainTexture := TgxMaterialLibrary(FMaterialLibrary).TextureByName(FMainTextureName);
  172. except end;
  173. with VertexProgram.Code do
  174. begin
  175. Clear;
  176. Add(' ');
  177. Add('//in ');
  178. Add('struct appData ');
  179. Add('{ ');
  180. Add(' float4 Position : POSITION; ');
  181. Add(' float4 Normal : NORMAL; ');
  182. Add(' float4 TexCoord0 : TEXCOORD0; ');
  183. Add('}; ');
  184. Add(' ');
  185. Add('// out ');
  186. Add('struct vertexOutData ');
  187. Add('{ ');
  188. Add(' float4 HPosition : POSITION; ');
  189. Add(' float4 Color0 : COLOR0; ');
  190. Add(' float4 TexCoord0 : TEXCOORD0; ');
  191. Add('}; ');
  192. Add(' ');
  193. Add(' ');
  194. Add(' ');
  195. Add('vertexOutData main( ');
  196. Add(' appData IN, ');
  197. Add(' uniform float4x4 WorldViewProj, ');
  198. Add(' const float4x4 NoiseMatrix, ');
  199. Add(' uniform float Timer, ');
  200. Add(' uniform float Displacement, ');
  201. Add(' uniform float Sharpness, ');
  202. Add(' uniform float ColorSharpness , ');
  203. Add(' uniform float Speed, ');
  204. Add(' uniform float TurbDensity, ');
  205. Add(' uniform float ColorRange ');
  206. Add(' ) ');
  207. Add('{ ');
  208. Add(' vertexOutData OUT; ');
  209. Add(' OUT.TexCoord0 = IN.TexCoord0; ');
  210. Add(' float4 noisePos = TurbDensity * mul(IN.Position + (Speed * Timer), NoiseMatrix); ');
  211. Add(' float i = sin(noisePos.x + noisePos.y + noisePos.z + tan(noisePos.x + noisePos.y + noisePos.z)/100000 ); ');
  212. Add(' float cr = 0.5 + ColorRange * i; ');
  213. Add(' cr = pow(cr,ColorSharpness); ');
  214. Add(' OUT.Color0 = float4((cr).xxx, 1.0f); ');
  215. Add(' // Displacement along normal ');
  216. Add(' float ni = pow(abs(i), Sharpness); ');
  217. Add(' float4 Nn = float4(normalize(IN.Position).xyz,0); ');
  218. Add(' float4 NewPos = IN.Position - (Nn * (ni - 0.5) * Displacement) * 10; ');
  219. Add(' OUT.HPosition = mul(WorldViewProj, NewPos); ');
  220. Add(' return OUT; ');
  221. Add('} ');
  222. end;
  223. with FragmentProgram.Code do
  224. begin
  225. Clear;
  226. Add('struct vertexOutData ');
  227. Add('{ ');
  228. Add(' float4 Color0 : COLOR0; ');
  229. Add(' float4 TexCoord0 : TEXCOORD0; ');
  230. Add('}; ');
  231. Add(' ');
  232. Add('float4 main( ');
  233. Add(' vertexOutData IN, ');
  234. Add(' uniform sampler2D GradeSampler, ');
  235. Add(' uniform float GradientTextureShare, ');
  236. if FMainTexture <> nil then
  237. begin
  238. Add(' uniform sampler2D MainTextureSampler, ');
  239. Add(' uniform float MainTextureShare, ');
  240. end;
  241. Add(' uniform float Alpha ');
  242. Add(' ): COLOR ');
  243. Add('{ ');
  244. Add(' float4 GradeColor = tex2D(GradeSampler, float2(IN.Color0.x, IN.Color0.y)); ');
  245. if FMainTexture <> nil then
  246. Add(' float4 TextureColor = tex2D(MainTextureSampler, IN.TexCoord0.xy); ');
  247. Add(' ');
  248. if FMainTexture <> nil then
  249. Add(' TextureColor = TextureColor * MainTextureShare + GradeColor * GradientTextureShare; ')
  250. else
  251. Add(' float4 TextureColor = GradeColor * GradientTextureShare; ');
  252. Add(' TextureColor.w = Alpha; ');
  253. Add(' return TextureColor;');
  254. Add('} ');
  255. end;
  256. inherited DoInitialize(rci, Sender);
  257. // May be there was an error and shader disabled itself.
  258. if Enabled then
  259. begin
  260. Assert(FGradientTexture <> nil);
  261. VertexProgram.ParamByName('NoiseMatrix').SetAsStateMatrix(CG_GL_TEXTURE_MATRIX, CG_GL_MATRIX_IDENTITY);
  262. FragmentProgram.ParamByName('GradeSampler').SetAsTexture2D(FGradientTexture.Handle);
  263. end;
  264. end;
  265. function TCGxCustomBombShader.GetGradientTextureName: TgxLibMaterialName;
  266. begin
  267. Result := TgxMaterialLibrary(FMaterialLibrary).GetNameOfTexture(FGradientTexture);
  268. if Result = '' then Result := FGradientTextureName;
  269. end;
  270. function TCGxCustomBombShader.GetMainTextureName: TgxLibMaterialName;
  271. begin
  272. Result := TgxMaterialLibrary(FMaterialLibrary).GetNameOfTexture(FMainTexture);
  273. if Result = '' then Result := FMainTextureName;
  274. end;
  275. function TCGxCustomBombShader.GetMaterialLibrary: TgxAbstractMaterialLibrary;
  276. begin
  277. Result := FMaterialLibrary;
  278. end;
  279. procedure TCGxCustomBombShader.Notification(AComponent: TComponent;
  280. Operation: TOperation);
  281. var
  282. Index: Integer;
  283. begin
  284. inherited;
  285. if Operation = opRemove then
  286. if AComponent = FMaterialLibrary then
  287. if FMaterialLibrary <> nil then
  288. begin
  289. // Need to nil the textures that were owned by it
  290. if FMainTexture <> nil then
  291. begin
  292. Index := TgxMaterialLibrary(FMaterialLibrary).Materials.GetTextureIndex(FMainTexture);
  293. if Index <> -1 then
  294. SetMainTexture(nil);
  295. end;
  296. if FGradientTexture <> nil then
  297. begin
  298. Index := TgxMaterialLibrary(FMaterialLibrary).Materials.GetTextureIndex(FGradientTexture);
  299. if Index <> -1 then
  300. SetGradientTexture(nil);
  301. end;
  302. FMaterialLibrary := nil;
  303. end;
  304. end;
  305. procedure TCGxCustomBombShader.OnApplyFP(CgProgram: TCGxProgram; Sender: TObject);
  306. begin
  307. CgProgram.ParamByName('Alpha').SetAsScalar(FAlpha);
  308. CgProgram.ParamByName('GradientTextureShare').SetAsScalar(FGradientTextureShare);
  309. CgProgram.ParamByName('GradeSampler').EnableTexture;
  310. if FMainTexture <> nil then
  311. begin
  312. CgProgram.ParamByName('MainTextureShare').SetAsScalar(FMainTextureShare);
  313. CgProgram.ParamByName('MainTextureSampler').EnableTexture;
  314. end;
  315. end;
  316. procedure TCGxCustomBombShader.OnApplyVP(CgProgram: TCGxProgram; Sender: TObject);
  317. begin
  318. CgProgram.ParamByName('WorldViewProj').SetAsStateMatrix(CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);
  319. CgProgram.ParamByName('Timer').SetAsScalar(Cadencer.CurrentTime);
  320. CgProgram.ParamByName('Displacement').SetAsScalar(FDisplacement);
  321. CgProgram.ParamByName('Sharpness').SetAsScalar(FSharpness);
  322. CgProgram.ParamByName('ColorSharpness').SetAsScalar(FColorSharpness);
  323. CgProgram.ParamByName('Speed').SetAsScalar(FSpeed);
  324. CgProgram.ParamByName('TurbDensity').SetAsScalar(FTurbDensity);
  325. CgProgram.ParamByName('ColorRange').SetAsScalar(FColorRange);
  326. end;
  327. procedure TCGxCustomBombShader.OnUnApplyFP(CgProgram: TCGxProgram);
  328. begin
  329. CgProgram.ParamByName('GradeSampler').DisableTexture;
  330. if FMainTexture <> nil then
  331. CgProgram.ParamByName('MainTextureSampler').DisableTexture;
  332. end;
  333. procedure TCGxCustomBombShader.SetGradientTexture(const Value: TgxTexture);
  334. begin
  335. if FGradientTexture = Value then Exit;
  336. FGradientTexture := Value;
  337. NotifyChange(Self);
  338. end;
  339. procedure TCGxCustomBombShader.SetGradientTextureName(
  340. const Value: TgxLibMaterialName);
  341. begin
  342. FGradientTextureName := Value;
  343. if ShaderInitialized then
  344. NotifyChange(Self);
  345. end;
  346. procedure TCGxCustomBombShader.SetMainTexture(
  347. const Value: TgxTexture);
  348. begin
  349. if FMainTexture = Value then Exit;
  350. FMainTexture := Value;
  351. NotifyChange(Self);
  352. end;
  353. procedure TCGxCustomBombShader.SetMainTextureName(
  354. const Value: TgxLibMaterialName);
  355. begin
  356. FMainTextureName := Value;
  357. if ShaderInitialized then
  358. NotifyChange(Self);
  359. end;
  360. procedure TCGxCustomBombShader.SetMaterialLibrary(
  361. const Value: TgxAbstractMaterialLibrary);
  362. begin
  363. if FMaterialLibrary <> nil then FMaterialLibrary.RemoveFreeNotification(Self);
  364. FMaterialLibrary := Value;
  365. if (FMaterialLibrary <> nil)
  366. and (FMaterialLibrary is TgxAbstractMaterialLibrary) then
  367. FMaterialLibrary.FreeNotification(Self);
  368. end;
  369. function TCGxCustomBombShader.StoreColorRange: Boolean;
  370. begin
  371. Result := Abs(FColorRange - 0.24) > EPS;
  372. end;
  373. function TCGxCustomBombShader.StoreColorSharpness: Boolean;
  374. begin
  375. Result := Abs(FColorSharpness - 1) > EPS;
  376. end;
  377. function TCGxCustomBombShader.StoreDisplacement: Boolean;
  378. begin
  379. Result := Abs(FDisplacement - 0.3) > EPS;
  380. end;
  381. function TCGxCustomBombShader.StoreGradientTextureShare: Boolean;
  382. begin
  383. Result := Abs(FGradientTextureShare - 0.7) > EPS;
  384. end;
  385. function TCGxCustomBombShader.StoreMainTextureShare: Boolean;
  386. begin
  387. Result := Abs(FMainTextureShare - 0.7) > EPS;
  388. end;
  389. function TCGxCustomBombShader.StoreSharpness: Boolean;
  390. begin
  391. Result := Abs(FSharpness - 3) > EPS;
  392. end;
  393. function TCGxCustomBombShader.StoreSpeed: Boolean;
  394. begin
  395. Result := Abs(FSpeed - 0.3) > EPS;
  396. end;
  397. function TCGxCustomBombShader.StoreTurbDensity: Boolean;
  398. begin
  399. Result := Abs(FTurbDensity - 1) > EPS;
  400. end;
  401. //--------------------------------
  402. // TCGxBombShader
  403. //--------------------------------
  404. procedure TCGxBombShader.DoApply(var rci: TgxRenderContextInfo;
  405. Sender: TObject);
  406. begin
  407. {$IFNDEF USE_OPTIMIZATIONS}
  408. if (not (csDesigning in ComponentState)) or DesignEnable then
  409. inherited;
  410. {$ENDIF}
  411. end;
  412. procedure TCGxBombShader.DoInitialize(var rci : TgxRenderContextInfo; Sender : TObject);
  413. begin
  414. {$IFNDEF USE_OPTIMIZATIONS}
  415. if (not (csDesigning in ComponentState)) or DesignEnable then
  416. inherited;
  417. {$ENDIF}
  418. end;
  419. procedure TCGxBombShader.OnApplyFP(CgProgram: TCGxProgram;
  420. Sender: TObject);
  421. begin
  422. {$IFNDEF USE_OPTIMIZATIONS}
  423. if (not (csDesigning in ComponentState)) or DesignEnable then
  424. inherited;
  425. {$ENDIF}
  426. end;
  427. procedure TCGxBombShader.OnApplyVP(CgProgram: TCGxProgram;
  428. Sender: TObject);
  429. begin
  430. {$IFNDEF USE_OPTIMIZATIONS}
  431. if (not (csDesigning in ComponentState)) or DesignEnable then
  432. inherited;
  433. {$ENDIF}
  434. end;
  435. procedure TCGxBombShader.OnUnApplyFP(CgProgram: TCGxProgram);
  436. begin
  437. {$IFNDEF USE_OPTIMIZATIONS}
  438. if (not (csDesigning in ComponentState)) or DesignEnable then
  439. inherited;
  440. {$ENDIF}
  441. end;
  442. initialization
  443. RegisterClasses([TCGxCustomBombShader, TCGxBombShader]);
  444. end.