Cg.BombShader.pas 16 KB

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