GLSL.ShaderVertexDisplacement.pas 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. //
  2. // This unit is part of the GLScene Engine, http://glscene.org
  3. //
  4. (*
  5. VertexDisplacement shader : Basic Vertex Displacement with Perlin Noise
  6. You can Improved it :
  7. The vertex displacement can be done by reading a 2D or 3D texture.
  8. It can be done along the normal or the tangent.
  9. It can be scaled, twisted, modulated, inverted...
  10. Converted from : https://www.clicktorelease.com/blog/vertex-displacement-noise-3d-webgl-glsl-three-js
  11. At this time only one light source is supported
  12. *)
  13. unit GLSL.ShaderVertexDisplacement;
  14. interface
  15. {$I GLScene.inc}
  16. uses
  17. Winapi.OpenGLext,
  18. System.Classes,
  19. OpenGLTokens,
  20. GLScene,
  21. GLBaseClasses,
  22. GLState,
  23. GLContext,
  24. GLRenderContextInfo,
  25. GLVectorGeometry,
  26. GLCoordinates,
  27. GLTextureFormat,
  28. GLColor,
  29. GLTexture,
  30. GLMaterial,
  31. GLSL.Shader,
  32. GLS.ShaderCustom;
  33. type
  34. (* Custom class for GLSLVertexDisplacementShader.
  35. VertexDisplacement Shader : Spherical Environment Mapping *)
  36. TGLCustomGLSLVertexDisplacementShader = class(TGLCustomGLSLShader)
  37. private
  38. FAmbientColor: TGLColor;
  39. // FDiffuseColor: TGLColor;
  40. FSpecularColor: TGLColor;
  41. FAmbientFactor : Single;
  42. FDiffuseFactor : Single;
  43. FSpecularFactor : Single;
  44. FMaterialLibrary: TGLAbstractMaterialLibrary;
  45. FMainTexture: TGLTexture;
  46. FMainTexName : TGLLibMaterialName;
  47. FElapsedTime : Single;
  48. FNoise : Single;
  49. FDisplacementScale : Single;
  50. FNoiseScale : Single;
  51. FTurbulenceFactor : Single;
  52. FNoisePeriod : Single;
  53. FTimeFactor : Single;
  54. function GetMaterialLibrary: TGLAbstractMaterialLibrary;
  55. procedure SetMainTexTexture(const Value: TGLTexture);
  56. function GetMainTexName: TGLLibMaterialName;
  57. procedure SetMainTexName(const Value: TGLLibMaterialName);
  58. //procedure SetDiffuseColor(AValue: TGLColor);
  59. procedure SetAmbientColor(AValue: TGLColor);
  60. procedure SetSpecularColor(AValue: TGLColor);
  61. protected
  62. procedure DoApply(var rci : TGLRenderContextInfo; Sender : TObject); override;
  63. function DoUnApply(var rci: TGLRenderContextInfo): Boolean; override;
  64. procedure SetMaterialLibrary(const Value: TGLAbstractMaterialLibrary); virtual;
  65. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  66. public
  67. constructor Create(AOwner : TComponent); override;
  68. destructor Destroy; override;
  69. // property DiffuseColor : TGLColor read FDiffuseColor Write setDiffuseColor;
  70. property SpecularColor : TGLColor Read FSpecularColor Write setSpecularColor;
  71. property AmbientColor : TGLColor Read FAmbientColor Write setAmbientColor;
  72. property AmbientFactor : Single Read FAmbientFactor Write FAmbientFactor;
  73. property DiffuseFactor : Single Read FDiffuseFactor Write FDiffuseFactor;
  74. property SpecularFactor : Single Read FSpecularFactor Write FSpecularFactor;
  75. property MaterialLibrary: TGLAbstractMaterialLibrary read getMaterialLibrary write SetMaterialLibrary;
  76. property MainTexture: TGLTexture read FMainTexture write SetMainTexTexture;
  77. property MainTextureName: TGLLibMaterialName read GetMainTexName write SetMainTexName;
  78. property ElapsedTime: Single read FElapsedTime write FElapsedTime;
  79. property NoiseFactor : Single read FNoise write FNoise;
  80. property NoiseScale : Single read FNoiseScale write FNoiseScale;
  81. property TurbulenceFactor : Single read FTurbulenceFactor write FTurbulenceFactor;
  82. property NoisePeriod : Single read FNoisePeriod write FNoisePeriod;
  83. property DisplacementScale : Single read FDisplacementScale write FDisplacementScale;
  84. property TimeFactor : Single read FTimeFactor write FTimeFactor;
  85. end;
  86. TGLSLVertexDisplacementShader = class(TGLCustomGLSLVertexDisplacementShader)
  87. published
  88. property AmbientColor;
  89. // property DiffuseColor;
  90. property SpecularColor;
  91. property AmbientFactor;
  92. property DiffuseFactor;
  93. property SpecularFactor;
  94. property MaterialLibrary;
  95. property MainTexture;
  96. property MainTextureName;
  97. property ElapsedTime;
  98. property NoiseFactor;
  99. property NoiseScale;
  100. property TurbulenceFactor;
  101. property NoisePeriod;
  102. property DisplacementScale;
  103. property TimeFactor;
  104. end;
  105. //=========================================================
  106. implementation
  107. //=========================================================
  108. constructor TGLCustomGLSLVertexDisplacementShader.Create(AOwner: TComponent);
  109. begin
  110. inherited;
  111. with VertexProgram.Code do
  112. begin
  113. clear;
  114. Add('uniform float time; ');
  115. Add('uniform float NoiseFactor; ');
  116. Add('uniform float TurbulenceFactor; ');
  117. Add('uniform float NoiseScale; ');
  118. Add('uniform float NoisePeriod; ');
  119. Add('uniform float DisplacementScale; ');
  120. Add('uniform float TimeFactor; ');
  121. Add('varying vec3 viewVec; ');
  122. Add('varying vec3 normal; ');
  123. Add('varying vec3 lightVec; ');
  124. Add('varying vec2 vTexCoord; ');
  125. Add('varying float noise; ');
  126. //
  127. // GLSL textureless classic 3D noise "cnoise",
  128. // with an RSL-style periodic variant "pnoise".
  129. // Author: Stefan Gustavson ([email protected])
  130. // Version: 2011-10-11
  131. //
  132. // Many thanks to Ian McEwan of Ashima Arts for the
  133. // ideas for permutation and gradient selection.
  134. //
  135. // Copyright (c) 2011 Stefan Gustavson. All rights reserved.
  136. // Distributed under the MIT license. See LICENSE file.
  137. // https://github.com/ashima/webgl-noise
  138. //
  139. Add('vec3 mod289(vec3 x) ');
  140. Add('{ ');
  141. Add(' return x - floor(x * (1.0 / 289.0)) * 289.0; ');
  142. Add('} ');
  143. Add('vec4 mod289(vec4 x) ');
  144. Add('{ ');
  145. Add(' return x - floor(x * (1.0 / 289.0)) * 289.0; ');
  146. Add('} ');
  147. Add('vec4 permute(vec4 x) ');
  148. Add('{ ');
  149. Add(' return mod289(((x*34.0)+1.0)*x); ');
  150. Add('} ');
  151. Add('vec4 taylorInvSqrt(vec4 r) ');
  152. Add('{ ');
  153. Add(' return 1.79284291400159 - 0.85373472095314 * r; ');
  154. Add('} ');
  155. Add('vec3 fade(vec3 t) { ');
  156. Add(' return t*t*t*(t*(t*6.0-15.0)+10.0); ');
  157. Add('} ');
  158. // Classic Perlin noise, periodic variant
  159. Add('float pnoise(vec3 P, vec3 rep) ');
  160. Add('{ ');
  161. Add(' vec3 Pi0 = mod(floor(P), rep); // Integer part, modulo period ');
  162. Add(' vec3 Pi1 = mod(Pi0 + vec3(1.0), rep); // Integer part + 1, mod period ');
  163. Add(' Pi0 = mod289(Pi0); ');
  164. Add(' Pi1 = mod289(Pi1); ');
  165. Add(' vec3 Pf0 = fract(P); // Fractional part for interpolation ');
  166. Add(' vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0 ');
  167. Add(' vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x); ');
  168. Add(' vec4 iy = vec4(Pi0.yy, Pi1.yy); ');
  169. Add(' vec4 iz0 = Pi0.zzzz; ');
  170. Add(' vec4 iz1 = Pi1.zzzz; ');
  171. Add(' vec4 ixy = permute(permute(ix) + iy); ');
  172. Add(' vec4 ixy0 = permute(ixy + iz0); ');
  173. Add(' vec4 ixy1 = permute(ixy + iz1); ');
  174. Add(' vec4 gx0 = ixy0 * (1.0 / 7.0); ');
  175. Add(' vec4 gy0 = fract(floor(gx0) * (1.0 / 7.0)) - 0.5; ');
  176. Add(' gx0 = fract(gx0); ');
  177. Add(' vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0); ');
  178. Add(' vec4 sz0 = step(gz0, vec4(0.0)); ');
  179. Add(' gx0 -= sz0 * (step(0.0, gx0) - 0.5); ');
  180. Add(' gy0 -= sz0 * (step(0.0, gy0) - 0.5); ');
  181. Add(' vec4 gx1 = ixy1 * (1.0 / 7.0); ');
  182. Add(' vec4 gy1 = fract(floor(gx1) * (1.0 / 7.0)) - 0.5; ');
  183. Add(' gx1 = fract(gx1); ');
  184. Add(' vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1); ');
  185. Add(' vec4 sz1 = step(gz1, vec4(0.0)); ');
  186. Add(' gx1 -= sz1 * (step(0.0, gx1) - 0.5); ');
  187. Add(' gy1 -= sz1 * (step(0.0, gy1) - 0.5); ');
  188. Add(' vec3 g000 = vec3(gx0.x,gy0.x,gz0.x); ');
  189. Add(' vec3 g100 = vec3(gx0.y,gy0.y,gz0.y); ');
  190. Add(' vec3 g010 = vec3(gx0.z,gy0.z,gz0.z); ');
  191. Add(' vec3 g110 = vec3(gx0.w,gy0.w,gz0.w); ');
  192. Add(' vec3 g001 = vec3(gx1.x,gy1.x,gz1.x); ');
  193. Add(' vec3 g101 = vec3(gx1.y,gy1.y,gz1.y); ');
  194. Add(' vec3 g011 = vec3(gx1.z,gy1.z,gz1.z); ');
  195. Add(' vec3 g111 = vec3(gx1.w,gy1.w,gz1.w); ');
  196. Add(' vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))); ');
  197. Add(' g000 *= norm0.x; ');
  198. Add(' g010 *= norm0.y; ');
  199. Add(' g100 *= norm0.z; ');
  200. Add(' g110 *= norm0.w; ');
  201. Add(' vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))); ');
  202. Add(' g001 *= norm1.x; ');
  203. Add(' g011 *= norm1.y; ');
  204. Add(' g101 *= norm1.z; ');
  205. Add(' g111 *= norm1.w; ');
  206. Add(' float n000 = dot(g000, Pf0); ');
  207. Add(' float n100 = dot(g100, vec3(Pf1.x, Pf0.yz)); ');
  208. Add(' float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z)); ');
  209. Add(' float n110 = dot(g110, vec3(Pf1.xy, Pf0.z)); ');
  210. Add(' float n001 = dot(g001, vec3(Pf0.xy, Pf1.z)); ');
  211. Add(' float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z)); ');
  212. Add(' float n011 = dot(g011, vec3(Pf0.x, Pf1.yz)); ');
  213. Add(' float n111 = dot(g111, Pf1); ');
  214. Add(' vec3 fade_xyz = fade(Pf0); ');
  215. Add(' vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z); ');
  216. Add(' vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y); ');
  217. Add(' float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); ');
  218. Add(' return 2.2 * n_xyz; ');
  219. Add('} ');
  220. Add('float turbulence( vec3 p ) { ');
  221. Add(' float w = 100.0; ');
  222. Add(' float t = -.5; ');
  223. Add(' for (float f = 1.0 ; f <= 10.0 ; f++ ){ ');
  224. Add(' float power = pow( 2.0, f ); ');
  225. Add(' t += abs( pnoise( vec3( power * p ), vec3( 10.0, 10.0, 10.0 ) ) / power ); ');
  226. Add(' } ');
  227. Add(' return t; ');
  228. Add('} ');
  229. Add('void main() { '); //96
  230. Add(' mat4 mWorld = gl_ModelViewMatrix; ');
  231. Add(' vec3 Normal = gl_NormalMatrix * gl_Normal; //gl_Normal; ');
  232. Add(' vec4 Position = gl_Vertex; ');
  233. Add(' vec4 vert = gl_ModelViewMatrix * gl_Vertex; ');
  234. Add(' vec4 lightPos = gl_LightSource[0].position;');
  235. Add(' vTexCoord = gl_MultiTexCoord0; ');
  236. Add(' vec3 vNormal = normalize( Normal * mat3(mWorld )); ');
  237. Add(' time = TimeFactor*time; ');
  238. // add time to the noise parameters so it's animated
  239. Add(' noise = NoiseFactor* -0.10* turbulence( TurbulenceFactor * vNormal+time ); ');
  240. // get a 3d noise using the position, low frequency
  241. Add(' float b = (NoisePeriod*time)*pnoise( vec3((NoiseScale *time)* (Position.xyz + vec3(time ))), vec3(100) ); ');
  242. // compose both noises
  243. Add(' float displacement =( noise + b); ');
  244. Add(' vec4 newPosition =vec4((Position.xyz + DisplacementScale*(vec3(vNormal * displacement))),1.0); ');
  245. Add(' normal = vNormal; ');
  246. Add(' lightVec = vec3(lightPos - vert); ');
  247. Add(' viewVec = -vec3(vert); ');
  248. Add(' gl_Position = gl_ModelViewProjectionMatrix * newPosition; ');
  249. Add('} ');
  250. end;
  251. with FragmentProgram.Code do
  252. begin
  253. clear;
  254. Add('uniform vec4 AmbientColor; ');
  255. Add('uniform vec4 SpecularColor; ');
  256. Add('uniform float DiffuseIntensity; ');
  257. Add('uniform float AmbientIntensity; ');
  258. Add('uniform float SpecularIntensity; ');
  259. Add('uniform sampler2D MainTexture; ');
  260. Add('varying vec3 viewVec; ');
  261. Add('varying vec3 normal; ');
  262. Add('varying vec3 lightVec; ');
  263. Add('varying float noise; ');
  264. Add('float random( vec3 scale, float seed ){ ');
  265. Add(' return fract( sin( dot( gl_FragCoord.xyz + seed, scale ) ) * 43758.5453 + seed ) ; ');
  266. Add('} ');
  267. Add('void main() { ');
  268. // get a random offset
  269. Add(' float r = 0.01 * random( vec3( 12.9898, 78.233, 151.7182 ), 0.0 ); ');
  270. // lookup vertically in the texture, using noise and offset
  271. // to get the right RGB colour
  272. Add(' vec2 tPos = vec2( 0, 1.0 - 1.3 * noise + r ); ');
  273. Add(' vec4 DiffuseColor; ');
  274. Add(' DiffuseColor = texture2D( MainTexture, tPos ); ');
  275. // Simple Lighting
  276. Add(' vec3 L = normalize(lightVec); ');
  277. Add(' vec3 V = normalize(viewVec); ');
  278. Add(' vec3 halfAngle = normalize(L + V); ');
  279. Add(' float NdotL = dot(L, normal); ');
  280. Add(' float NdotH = clamp(dot(halfAngle, normal), 0.0, 1.0); ');
  281. Add(' // "Half-Lambert" technique for more pleasing diffuse term ');
  282. Add(' float diffuse = DiffuseColor*(0.5 * NdotL + 0.5); ');
  283. Add(' float specular = pow(NdotH, 64.0); ');
  284. Add(' vec4 FinalColour = AmbientColor*AmbientIntensity + ');
  285. Add(' DiffuseColor*diffuse*DiffuseIntensity + ');
  286. Add(' SpecularColor*specular*SpecularIntensity; ');
  287. Add(' gl_FragColor = FinalColour; ; ');
  288. // Add(' gl_FragColor = vec4(DiffuseColor,1.0); ');
  289. Add('} ');
  290. end;
  291. FAmbientColor := TGLColor.Create(Self);
  292. //FDiffuseColor := TGLColor.Create(Self);
  293. FSpecularColor := TGLColor.Create(Self);
  294. //setup initial parameters
  295. FAmbientColor.SetColor(0.15, 0.15, 0.15, 1.0);
  296. //FDiffuseColor.SetColor(1, 1, 1, 1);
  297. FSpecularColor.SetColor(1.0, 1.0, 1.0, 1.0);
  298. FAmbientFactor := 0.8;
  299. FDiffuseFactor :=0.9;
  300. FSpecularFactor :=0.8;
  301. FElapsedTime := 1.0;
  302. FNoise := 10.0;
  303. FDisplacementScale:=1.0;
  304. FNoiseScale:=0.05;
  305. FTurbulenceFactor:=0.5;
  306. FNoisePeriod := 5.0;
  307. FTimeFactor := 0.05;
  308. end;
  309. destructor TGLCustomGLSLVertexDisplacementShader.Destroy;
  310. begin
  311. FAmbientColor.Destroy;
  312. // FDiffuseColor.Destroy;
  313. FSpecularColor.Destroy;
  314. inherited;
  315. end;
  316. procedure TGLCustomGLSLVertexDisplacementShader.DoApply(var rci: TGLRenderContextInfo; Sender: TObject);
  317. begin
  318. GetGLSLProg.UseProgramObject;
  319. // Param['DiffuseColor'].AsVector4f := FDiffuseColor.Color;
  320. param['AmbientColor'].AsVector4f := FAmbientColor.Color;
  321. param['SpecularColor'].AsVector4f := FSpecularColor.Color;
  322. param['AmbientIntensity'].AsVector1f := FAmbientFactor;
  323. param['DiffuseIntensity'].AsVector1f := FDiffuseFactor;
  324. param['SpecularIntensity'].AsVector1f := FSpecularFactor;
  325. Param['time'].AsVector1f := FElapsedTime;
  326. Param['NoiseFactor'].AsVector1f := FNoise;
  327. Param['NoiseScale'].AsVector1f := FNoiseScale;
  328. Param['TurbulenceFactor'].AsVector1f := FTurbulenceFactor;
  329. Param['NoisePeriod'].AsVector1f := FNoisePeriod;
  330. Param['DisplacementScale'].AsVector1f := FDisplacementScale;
  331. Param['TimeFactor'].AsVector1f := FTimeFactor;
  332. Param['MainTexture'].AsTexture2D[0] := FMainTexture;
  333. end;
  334. function TGLCustomGLSLVertexDisplacementShader.DoUnApply(var rci: TGLRenderContextInfo): Boolean;
  335. begin
  336. gl.ActiveTexture(GL_TEXTURE0_ARB);
  337. GetGLSLProg.EndUseProgramObject;
  338. Result := False;
  339. end;
  340. function TGLCustomGLSLVertexDisplacementShader.GetMaterialLibrary: TGLAbstractMaterialLibrary;
  341. begin
  342. Result := FMaterialLibrary;
  343. end;
  344. procedure TGLCustomGLSLVertexDisplacementShader.SetMaterialLibrary(const Value: TGLAbstractMaterialLibrary);
  345. begin
  346. if FMaterialLibrary <> nil then FMaterialLibrary.RemoveFreeNotification(Self);
  347. FMaterialLibrary := Value;
  348. if (FMaterialLibrary <> nil)
  349. and (FMaterialLibrary is TGLAbstractMaterialLibrary) then
  350. FMaterialLibrary.FreeNotification(Self);
  351. end;
  352. procedure TGLCustomGLSLVertexDisplacementShader.SetMainTexTexture(const Value: TGLTexture);
  353. begin
  354. if FMainTexture = Value then Exit;
  355. FMainTexture := Value;
  356. NotifyChange(Self)
  357. end;
  358. function TGLCustomGLSLVertexDisplacementShader.GetMainTexName: TGLLibMaterialName;
  359. begin
  360. Result := TGLMaterialLibrary(FMaterialLibrary).GetNameOfTexture(FMainTexture);
  361. if Result = '' then Result := FMainTexName;
  362. end;
  363. procedure TGLCustomGLSLVertexDisplacementShader.SetMainTexName(const Value: TGLLibMaterialName);
  364. begin
  365. // Assert(not(assigned(FMaterialLibrary)),'You must set Material Library Before');
  366. if FMainTexName = Value then Exit;
  367. FMainTexName := Value;
  368. FMainTexture := TGLMaterialLibrary(FMaterialLibrary).TextureByName(FMainTexName);
  369. NotifyChange(Self);
  370. end;
  371. //procedure TGLCustomGLSLVertexDisplacementShader.SetDiffuseColor(AValue: TGLColor);
  372. //begin
  373. // FDiffuseColor.DirectColor := AValue.Color;
  374. //end;
  375. procedure TGLCustomGLSLVertexDisplacementShader.SetAmbientColor(AValue: TGLColor);
  376. begin
  377. FAmbientColor.DirectColor := AValue.Color;
  378. end;
  379. procedure TGLCustomGLSLVertexDisplacementShader.SetSpecularColor(AValue: TGLColor);
  380. begin
  381. FSpecularColor.DirectColor := AValue.Color;
  382. end;
  383. procedure TGLCustomGLSLVertexDisplacementShader.Notification(AComponent: TComponent; Operation: TOperation);
  384. var
  385. Index: Integer;
  386. begin
  387. inherited;
  388. if Operation = opRemove then
  389. if AComponent = FMaterialLibrary then
  390. if FMaterialLibrary <> nil then
  391. begin
  392. if FMainTexture <> nil then
  393. begin
  394. Index := TGLMaterialLibrary(FMaterialLibrary).Materials.GetTextureIndex(FMainTexture);
  395. if Index <> -1 then
  396. SetMainTexTexture(nil);
  397. end;
  398. FMaterialLibrary := nil;
  399. end;
  400. end;
  401. end.