GXSL.DiffuseSpecularShader.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820
  1. //
  2. // The graphics engine GXScene https://github.com/glscene
  3. //
  4. unit GXSL.DiffuseSpecularShader;
  5. (*
  6. This is a collection of GLSL Diffuse Specular shaders, comes in these variaties
  7. (to know what these suffixes and prefixes mean see GXS.CustomShader.pas):
  8. - TgxSLDiffuseSpecularShader
  9. - TgxSLDiffuseSpecularShaderMT
  10. - TgxSLMLDiffuseSpecularShader
  11. - TgxSLMLDiffuseSpecularShaderMT
  12. Notes:
  13. 1) TgxSLDiffuseSpecularShader takes all Material parameters directly
  14. from OpenGL (that includes TgxMaterial's)
  15. 2) TgxSLDiffuseSpecularShader takes all Light parameters directly
  16. from OpenGL (that includes TgxLightSource's)
  17. *)
  18. interface
  19. {$I GLScene.Defines.inc}
  20. uses
  21. System.Classes,
  22. System.SysUtils,
  23. GXS.Texture,
  24. GXS.Scene,
  25. GLScene.VectorGeometry,
  26. GLScene.Strings,
  27. GXSL.CustomShader,
  28. GXSL.Shader,
  29. GXS.Color,
  30. GXS.RenderContextInfo,
  31. GXS.Material;
  32. type
  33. EgxslDiffuseSpecularShaderException = class(EgxslShaderException);
  34. // Abstract class.
  35. TgxBaseCustomGLSLDiffuseSpecular = class(TgxslCustomShader)
  36. private
  37. FLightPower: Single;
  38. FRealisticSpecular: Boolean;
  39. FFogSupport: TgxShaderFogSupport;
  40. procedure SetRealisticSpecular(const Value: Boolean);
  41. procedure SetFogSupport(const Value: TgxShaderFogSupport);
  42. protected
  43. procedure DoApply(var rci : TgxRenderContextInfo; Sender : TObject); override;
  44. function DoUnApply(var rci: TgxRenderContextInfo): Boolean; override;
  45. public
  46. constructor Create(AOwner : TComponent); override;
  47. property LightPower: Single read FLightPower write FLightPower;
  48. property RealisticSpecular: Boolean read FRealisticSpecular write SetRealisticSpecular;
  49. // User can disable fog support and save some FPS if he doesn't need it.
  50. property FogSupport: TgxShaderFogSupport read FFogSupport write SetFogSupport default sfsAuto;
  51. end;
  52. // Abstract class.
  53. TgxBaseGLSLDiffuseSpecularShaderMT = class(TgxBaseCustomGLSLDiffuseSpecular, IgxMaterialLibrarySupported)
  54. private
  55. FMaterialLibrary: TgxMaterialLibrary;
  56. FMainTexture: TgxTexture;
  57. FMainTextureName: TgxLibMaterialName;
  58. function GetMainTextureName: TgxLibMaterialName;
  59. procedure SetMainTextureName(const Value: TgxLibMaterialName);
  60. // Implementing IGLMaterialLibrarySupported.
  61. function GetMaterialLibrary: TgxAbstractMaterialLibrary;
  62. protected
  63. procedure SetMaterialLibrary(const Value: TgxMaterialLibrary); virtual;
  64. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  65. procedure DoApply(var rci : TgxRenderContextInfo; Sender : TObject); override;
  66. public
  67. property MainTexture: TgxTexture read FMainTexture write FMainTexture;
  68. property MainTextureName: TgxLibMaterialName read GetMainTextureName write SetMainTextureName;
  69. property MaterialLibrary: TgxMaterialLibrary read FMaterialLibrary write SetMaterialLibrary;
  70. end;
  71. {******** Single Light ************}
  72. TgxCustomGLSLDiffuseSpecularShader = class(TgxBaseCustomGLSLDiffuseSpecular)
  73. protected
  74. procedure DoInitialize(var rci: TgxRenderContextInfo; Sender: TObject); override;
  75. procedure DoApply(var rci : TgxRenderContextInfo; Sender : TObject); override;
  76. end;
  77. TgxCustomGLSLDiffuseSpecularShaderMT = class(TgxBaseGLSLDiffuseSpecularShaderMT)
  78. protected
  79. procedure DoInitialize(var rci: TgxRenderContextInfo; Sender: TObject); override;
  80. end;
  81. //******* Multi Light *********
  82. TLightRecord = record
  83. Enabled: Boolean;
  84. Style: TgxLightStyle;
  85. end;
  86. // Note: probably LightCount should be replaced by LightSources, like in GLSLBumpShader.pas
  87. TgxCustomGLSLMLDiffuseSpecularShader = class(TgxBaseCustomGLSLDiffuseSpecular)
  88. private
  89. FLightTrace: array[0..7] of TLightRecord;
  90. protected
  91. procedure DoInitialize(var rci: TgxRenderContextInfo; Sender: TObject); override;
  92. procedure DoApply(var rci: TgxRenderContextInfo; Sender: TObject); override;
  93. public
  94. constructor Create(AOwner : TComponent); override;
  95. end;
  96. TgxCustomGLSLMLDiffuseSpecularShaderMT = class(TgxBaseGLSLDiffuseSpecularShaderMT)
  97. private
  98. FLightTrace: array[0..7] of TLightRecord;
  99. protected
  100. procedure DoInitialize(var rci: TgxRenderContextInfo; Sender: TObject); override;
  101. procedure DoApply(var rci: TgxRenderContextInfo; Sender: TObject); override;
  102. public
  103. constructor Create(AOwner : TComponent); override;
  104. end;
  105. {******** Published Stuff ************}
  106. TgxSLDiffuseSpecularShaderMT = class(TgxCustomGLSLDiffuseSpecularShaderMT)
  107. published
  108. property MainTextureName;
  109. property LightPower;
  110. property FogSupport;
  111. end;
  112. TgxSLDiffuseSpecularShader = class(TgxCustomGLSLDiffuseSpecularShader)
  113. published
  114. property LightPower;
  115. property FogSupport;
  116. end;
  117. TgxSLMLDiffuseSpecularShaderMT = class(TgxCustomGLSLMLDiffuseSpecularShaderMT)
  118. published
  119. property MainTextureName;
  120. property LightPower;
  121. property FogSupport;
  122. end;
  123. TgxSLMLDiffuseSpecularShader = class(TgxCustomGLSLMLDiffuseSpecularShader)
  124. published
  125. property LightPower;
  126. property FogSupport;
  127. end;
  128. //---------------------------------------------------------------------------
  129. implementation
  130. //---------------------------------------------------------------------------
  131. procedure GetVertexProgramCode(const Code: TStrings;
  132. AFogSupport: Boolean; var rci: TgxRenderContextInfo);
  133. begin
  134. with Code do
  135. begin
  136. Clear;
  137. Add('varying vec3 Normal; ');
  138. Add('varying vec4 Position; ');
  139. if AFogSupport then
  140. begin
  141. Add('varying float fogFactor; ');
  142. end;
  143. Add(' ');
  144. Add(' ');
  145. Add('void main(void) ');
  146. Add('{ ');
  147. Add(' gl_Position = ftransform(); ');
  148. Add(' gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; ');
  149. Add(' Normal = normalize(gl_NormalMatrix * gl_Normal); ');
  150. Add(' Position = gl_ModelViewMatrix * gl_Vertex; ');
  151. if AFogSupport then
  152. begin
  153. Add(' const float LOG2 = 1.442695; ');
  154. Add(' gl_FogFragCoord = length(Position.xyz); ');
  155. case TgxSceneBuffer(rci.buffer).FogEnvironment.FogMode of
  156. fmLinear:
  157. Add(' fogFactor = (gl_Fog.end - gl_FogFragCoord) * gl_Fog.scale; ');
  158. fmExp, // Yep, I don't know about this type, so I use fmExp2.
  159. fmExp2:
  160. begin
  161. Add(' fogFactor = exp2( -gl_Fog.density * ');
  162. Add(' gl_Fog.density * ');
  163. Add(' gl_FogFragCoord * ');
  164. Add(' gl_FogFragCoord * ');
  165. Add(' LOG2 ); ');
  166. end;
  167. else
  168. Assert(False, strUnknownType);
  169. end;
  170. Add(' fogFactor = clamp(fogFactor, 0.0, 1.0); ');
  171. end;
  172. Add('} ');
  173. end;
  174. end;
  175. procedure AddLightSub(const Code: TStrings);
  176. begin
  177. with Code do
  178. begin
  179. Add('void pointLight(in int i, in vec3 normal, in vec3 eye, in vec3 ecPosition3)');
  180. Add('{');
  181. Add(' float nDotVP; // normal . light direction');
  182. Add(' float nDotHV; // normal . light half vector');
  183. Add(' float pf; // power factor');
  184. Add(' float attenuation; // computed attenuation factor');
  185. Add(' float d; // distance from surface to light source');
  186. Add(' vec3 VP; // direction from surface to light position');
  187. Add(' vec3 halfVector; // direction of maximum highlights');
  188. Add(' ');
  189. Add(' // Compute vector from surface to light position');
  190. Add(' VP = vec3 (gl_LightSource[i].position) - ecPosition3;');
  191. Add(' ');
  192. Add(' // Compute distance between surface and light position');
  193. Add(' d = length(VP);');
  194. Add(' ');
  195. Add(' // Normalize the vector from surface to light position');
  196. Add(' VP = normalize(VP);');
  197. Add(' ');
  198. Add(' // Compute attenuation');
  199. Add(' attenuation = 1.0 / (gl_LightSource[i].constantAttenuation +');
  200. Add(' gl_LightSource[i].linearAttenuation * d +');
  201. Add(' gl_LightSource[i].quadraticAttenuation * d * d);');
  202. Add(' ');
  203. Add(' halfVector = normalize(VP + eye);');
  204. Add(' ');
  205. Add(' nDotVP = max(0.0, dot(normal, VP));');
  206. Add(' nDotHV = max(0.0, dot(normal, halfVector));');
  207. Add(' ');
  208. Add(' if (nDotVP == 0.0)');
  209. Add(' {');
  210. Add(' pf = 0.0;');
  211. Add(' }');
  212. Add(' else');
  213. Add(' {');
  214. Add(' pf = pow(nDotHV, gl_FrontMaterial.shininess);');
  215. Add(' ');
  216. Add(' }');
  217. Add(' Ambient += gl_LightSource[i].ambient * attenuation;');
  218. Add(' Diffuse += gl_LightSource[i].diffuse * nDotVP * attenuation;');
  219. Add(' Specular += gl_LightSource[i].specular * pf * attenuation;');
  220. Add('}');
  221. Add(' ');
  222. Add('void directionalLight(in int i, in vec3 normal)');
  223. Add('{');
  224. Add(' float nDotVP; // normal . light direction');
  225. Add(' float nDotHV; // normal . light half vector');
  226. Add(' float pf; // power factor');
  227. Add(' ');
  228. Add(' nDotVP = max(0.0, dot(normal, normalize(vec3 (gl_LightSource[i].position))));');
  229. Add(' nDotHV = max(0.0, dot(normal, vec3 (gl_LightSource[i].halfVector)));');
  230. Add(' ');
  231. Add(' if (nDotVP == 0.0)');
  232. Add(' {');
  233. Add(' pf = 0.0;');
  234. Add(' }');
  235. Add(' else');
  236. Add(' {');
  237. Add(' pf = pow(nDotHV, gl_FrontMaterial.shininess);');
  238. Add(' ');
  239. Add(' }');
  240. Add(' Ambient += gl_LightSource[i].ambient;');
  241. Add(' Diffuse += gl_LightSource[i].diffuse * nDotVP;');
  242. Add(' Specular += gl_LightSource[i].specular * pf;');
  243. Add('}');
  244. Add('void spotLight(in int i, in vec3 normal, in vec3 eye, in vec3 ecPosition3)');
  245. Add('{');
  246. Add(' float nDotVP; // normal . light direction');
  247. Add(' float nDotHV; // normal . light half vector');
  248. Add(' float pf; // power factor');
  249. Add(' float spotDot; // cosine of angle between spotlight');
  250. Add(' float spotAttenuation; // spotlight attenuation factor');
  251. Add(' float attenuation; // computed attenuation factor');
  252. Add(' float d; // distance from surface to light source');
  253. Add(' vec3 VP; // direction from surface to light position');
  254. Add(' vec3 halfVector; // direction of maximum highlights');
  255. Add(' ');
  256. Add(' // Compute vector from surface to light position');
  257. Add(' VP = vec3 (gl_LightSource[i].position) - ecPosition3;');
  258. Add(' ');
  259. Add(' // Compute distance between surface and light position');
  260. Add(' d = length(VP);');
  261. Add(' ');
  262. Add(' // Normalize the vector from surface to light position');
  263. Add(' VP = normalize(VP);');
  264. Add(' ');
  265. Add(' // Compute attenuation');
  266. Add(' attenuation = 1.0 / (gl_LightSource[i].constantAttenuation +');
  267. Add(' gl_LightSource[i].linearAttenuation * d +');
  268. Add(' gl_LightSource[i].quadraticAttenuation * d * d);');
  269. Add(' ');
  270. Add(' // See if point on surface is inside cone of illumination');
  271. Add(' spotDot = dot(-VP, normalize(gl_LightSource[i].spotDirection));');
  272. Add(' ');
  273. Add(' if (spotDot < gl_LightSource[i].spotCosCutoff)');
  274. Add(' {');
  275. Add(' spotAttenuation = 0.0; // light adds no contribution');
  276. Add(' }');
  277. Add(' else');
  278. Add(' {');
  279. Add(' spotAttenuation = pow(spotDot, gl_LightSource[i].spotExponent);');
  280. Add(' ');
  281. Add(' }');
  282. Add(' // Combine the spotlight and distance attenuation.');
  283. Add(' attenuation *= spotAttenuation;');
  284. Add(' ');
  285. Add(' halfVector = normalize(VP + eye);');
  286. Add(' ');
  287. Add(' nDotVP = max(0.0, dot(normal, VP));');
  288. Add(' nDotHV = max(0.0, dot(normal, halfVector));');
  289. Add(' ');
  290. Add(' if (nDotVP == 0.0)');
  291. Add(' {');
  292. Add(' pf = 0.0;');
  293. Add(' }');
  294. Add(' else');
  295. Add(' {');
  296. Add(' pf = pow(nDotHV, gl_FrontMaterial.shininess);');
  297. Add(' ');
  298. Add(' }');
  299. Add(' Ambient += gl_LightSource[i].ambient * attenuation;');
  300. Add(' Diffuse += gl_LightSource[i].diffuse * nDotVP * attenuation;');
  301. Add(' Specular += gl_LightSource[i].specular * pf * attenuation;');
  302. Add(' ');
  303. Add('}');
  304. Add('void infiniteSpotLight(in int i, in vec3 normal)');
  305. Add('{');
  306. Add(' float nDotVP; // normal . light direction');
  307. Add(' float nDotHV; // normal . light half vector');
  308. Add(' float pf; // power factor');
  309. Add(' float spotAttenuation;');
  310. Add(' vec3 Ppli;');
  311. Add(' vec3 Sdli;');
  312. Add(' ');
  313. Add(' nDotVP = max(0.0, dot(normal, normalize(vec3 (gl_LightSource[i].position))));');
  314. Add(' nDotHV = max(0.0, dot(normal, vec3 (gl_LightSource[i].halfVector)));');
  315. Add(' ');
  316. Add(' Ppli = -normalize(vec3(gl_LightSource[i].position));');
  317. Add(' Sdli = normalize(vec3(gl_LightSource[i].spotDirection));');
  318. Add(' ');
  319. Add(' spotAttenuation = pow(dot(Ppli, Sdli), gl_LightSource[i].spotExponent);');
  320. Add(' if (nDotVP == 0.0)');
  321. Add(' {');
  322. Add(' pf = 0.0;');
  323. Add(' }');
  324. Add(' else');
  325. Add(' {');
  326. Add(' pf = pow(nDotHV, gl_FrontMaterial.shininess);');
  327. Add(' ');
  328. Add(' }');
  329. Add(' Ambient += gl_LightSource[i].ambient * spotAttenuation;');
  330. Add(' Diffuse += gl_LightSource[i].diffuse * nDotVP * spotAttenuation;');
  331. Add(' Specular += gl_LightSource[i].specular * pf * spotAttenuation;');
  332. Add('}');
  333. end;
  334. end;
  335. procedure GetMLFragmentProgramCodeMid(const Code: TStrings;
  336. const CurrentLight: Integer; AStyle: TgxLightStyle);
  337. begin
  338. with Code do
  339. begin
  340. case AStyle of
  341. lsOmni: Add(Format(' pointLight(%d, N, eye, Pos); ', [CurrentLight]));
  342. lsSpot: Add(Format(' spotLight(%d, N, eye, Pos); ', [CurrentLight]));
  343. lsParallel: Add(Format(' directionalLight(%d, N); ', [CurrentLight]));
  344. lsParallelSpot: Add(Format(' infiniteSpotLight(%d, N); ', [CurrentLight]));
  345. end;
  346. end;
  347. end;
  348. procedure GetFragmentProgramCode(const Code: TStrings;
  349. const ARealisticSpecular: Boolean; const AFogSupport: Boolean;
  350. aRci: TgxRenderContextInfo);
  351. var
  352. scene: TgxScene;
  353. begin
  354. with Code do
  355. begin
  356. Clear;
  357. Add('uniform float LightIntensity; ');
  358. Add('uniform sampler2D MainTexture; ');
  359. Add(' ');
  360. Add('varying vec3 Normal; ');
  361. Add('varying vec4 Position; ');
  362. if AFogSupport then
  363. begin
  364. Add('varying float fogFactor; ');
  365. end;
  366. Add('vec4 Ambient;');
  367. Add('vec4 Diffuse;');
  368. Add('vec4 Specular;');
  369. AddLightSub(Code);
  370. Add('void main(void) ');
  371. Add('{ ');
  372. Add(' vec4 TextureContrib = texture2D(MainTexture, gl_TexCoord[0].xy); ');
  373. Add(' vec3 eye = vec3(0.0, 0.0, 1.0); ');
  374. Add(' Diffuse = vec4(0.0); ');
  375. Add(' Specular = vec4(0.0); ');
  376. Add(' Ambient = vec4(0.0); ');
  377. Add(' vec3 Pos = Position.xyz; ');
  378. Add(' vec3 N = normalize(Normal); ');
  379. scene := TgxScene(ARci.scene);
  380. if (scene.Lights.Count > 0) then
  381. GetMLFragmentProgramCodeMid(Code, 0,
  382. TgxLightSource(scene.Lights[0]).LightStyle);
  383. if ARealisticSpecular then
  384. Add(' gl_FragColor = LightIntensity * (TextureContrib * (gl_FrontLightModelProduct.sceneColor + Ambient * gl_FrontMaterial.ambient + Diffuse * gl_FrontMaterial.diffuse) + Specular * gl_FrontMaterial.specular); ')
  385. else
  386. Add(' gl_FragColor = LightIntensity * TextureContrib * (gl_FrontLightModelProduct.sceneColor + Ambient * gl_FrontMaterial.ambient + Diffuse * gl_FrontMaterial.diffuse + Specular * gl_FrontMaterial.specular); ');
  387. if AFogSupport then
  388. Add(' gl_FragColor = mix(gl_Fog.color, gl_FragColor, fogFactor);');
  389. Add(' gl_FragColor.a = TextureContrib.a; ');
  390. Add('} ');
  391. end;
  392. end;
  393. procedure GetMLFragmentProgramCodeBeg(const Code: TStrings;
  394. const AFogSupport: Boolean);
  395. begin
  396. with Code do
  397. begin
  398. Clear;
  399. Add('uniform sampler2D MainTexture;');
  400. Add('uniform float LightIntensity; ');
  401. Add('uniform float SpecPower; ');
  402. Add('varying vec3 Normal;');
  403. Add('varying vec4 Position;');
  404. if AFogSupport then
  405. begin
  406. Add('varying float fogFactor;');
  407. end;
  408. Add('vec4 Ambient;');
  409. Add('vec4 Diffuse;');
  410. Add('vec4 Specular;');
  411. AddLightSub(Code);
  412. Add('void main(void) ');
  413. Add('{ ');
  414. Add(' vec4 TextureContrib = texture2D(MainTexture, gl_TexCoord[0].st); ');
  415. Add(' vec3 eye = vec3(0.0, 0.0, 1.0); ');
  416. Add(' Diffuse = vec4(0.0); ');
  417. Add(' Specular = vec4(0.0); ');
  418. Add(' Ambient = vec4(0.0); ');
  419. Add(' vec3 Pos = Position.xyz; ');
  420. Add(' vec3 N = normalize(Normal); ');
  421. end;
  422. end;
  423. procedure GetMLFragmentProgramCodeEnd(const Code: TStrings;
  424. const ARealisticSpecular: Boolean;
  425. AFogSupport: Boolean);
  426. begin
  427. with Code do
  428. begin
  429. if ARealisticSpecular then
  430. Add(' gl_FragColor = LightIntensity * (TextureContrib * (gl_FrontLightModelProduct.sceneColor + Ambient * gl_FrontMaterial.ambient + Diffuse * gl_FrontMaterial.diffuse) + Specular * gl_FrontMaterial.specular); ')
  431. else
  432. Add(' gl_FragColor = LightIntensity * TextureContrib * (gl_FrontLightModelProduct.sceneColor + Ambient * gl_FrontMaterial.ambient + Diffuse * gl_FrontMaterial.diffuse + Specular * gl_FrontMaterial.specular); ');
  433. if AFogSupport then
  434. Add(' gl_FragColor = mix(gl_Fog.color, gl_FragColor, fogFactor);');
  435. Add(' gl_FragColor.a = TextureContrib.a; ');
  436. Add('} ');
  437. end;
  438. end;
  439. { TgxBaseCustomGLSLDiffuseSpecular }
  440. constructor TgxBaseCustomGLSLDiffuseSpecular.Create(
  441. AOwner: TComponent);
  442. begin
  443. inherited;
  444. FLightPower := 1;
  445. FFogSupport := sfsAuto;
  446. TStringList(VertexProgram.Code).OnChange := nil;
  447. TStringList(FragmentProgram.Code).OnChange := nil;
  448. VertexProgram.Enabled := true;
  449. FragmentProgram.Enabled := true;
  450. end;
  451. procedure TgxBaseCustomGLSLDiffuseSpecular.DoApply(
  452. var rci: TgxRenderContextInfo; Sender: TObject);
  453. begin
  454. GetGXSLProg.UseProgramObject;
  455. Param['LightIntensity'].AsVector1f := FLightPower;
  456. end;
  457. function TgxBaseCustomGLSLDiffuseSpecular.DoUnApply(
  458. var rci: TgxRenderContextInfo): Boolean;
  459. begin
  460. Result := False;
  461. GetGXSLProg.EndUseProgramObject;
  462. end;
  463. procedure TgxBaseCustomGLSLDiffuseSpecular.SetFogSupport(
  464. const Value: TgxShaderFogSupport);
  465. begin
  466. if FFogSupport <> Value then
  467. begin
  468. FFogSupport := Value;
  469. Self.FinalizeShader;
  470. end;
  471. end;
  472. procedure TgxBaseCustomGLSLDiffuseSpecular.SetRealisticSpecular(
  473. const Value: Boolean);
  474. begin
  475. if FRealisticSpecular <> Value then
  476. begin
  477. FRealisticSpecular := Value;
  478. Self.FinalizeShader;
  479. end;
  480. end;
  481. { TgxBaseGLSLDiffuseSpecularShaderMT }
  482. procedure TgxBaseGLSLDiffuseSpecularShaderMT.DoApply(
  483. var rci: TgxRenderContextInfo; Sender: TObject);
  484. begin
  485. inherited;
  486. Param['MainTexture'].AsTexture2D[0] := FMainTexture;
  487. end;
  488. function TgxBaseGLSLDiffuseSpecularShaderMT.GetMainTextureName: TgxLibMaterialName;
  489. begin
  490. Result := FMaterialLibrary.GetNameOfTexture(FMainTexture);
  491. end;
  492. function TgxBaseGLSLDiffuseSpecularShaderMT.GetMaterialLibrary: TgxAbstractMaterialLibrary;
  493. begin
  494. Result := FMaterialLibrary;
  495. end;
  496. procedure TgxBaseGLSLDiffuseSpecularShaderMT.Notification(
  497. AComponent: TComponent; Operation: TOperation);
  498. var
  499. Index: Integer;
  500. begin
  501. inherited;
  502. if Operation = opRemove then
  503. if AComponent = FMaterialLibrary then
  504. if FMaterialLibrary <> nil then
  505. begin
  506. //need to nil the textures that were ownned by it
  507. if FMainTexture <> nil then
  508. begin
  509. Index := FMaterialLibrary.Materials.GetTextureIndex(FMainTexture);
  510. if Index <> -1 then
  511. FMainTexture := nil;
  512. end;
  513. FMaterialLibrary := nil;
  514. end;
  515. end;
  516. procedure TgxBaseGLSLDiffuseSpecularShaderMT.SetMainTextureName(
  517. const Value: TgxLibMaterialName);
  518. begin
  519. if FMaterialLibrary = nil then
  520. begin
  521. FMainTextureName := Value;
  522. if not (csLoading in ComponentState) then
  523. raise EgxslDiffuseSpecularShaderException.Create(strErrorEx + strMatLibNotDefined);
  524. end
  525. else
  526. begin
  527. FMainTexture := FMaterialLibrary.TextureByName(Value);
  528. FMainTextureName := '';
  529. end;
  530. end;
  531. procedure TgxBaseGLSLDiffuseSpecularShaderMT.SetMaterialLibrary(
  532. const Value: TgxMaterialLibrary);
  533. begin
  534. if FMaterialLibrary <> nil then
  535. FMaterialLibrary.RemoveFreeNotification(Self);
  536. FMaterialLibrary := Value;
  537. if FMaterialLibrary <> nil then
  538. begin
  539. FMaterialLibrary.FreeNotification(Self);
  540. if FMainTextureName <> '' then
  541. SetMainTextureName(FMainTextureName);
  542. end
  543. else
  544. FMainTextureName := '';
  545. end;
  546. { TgxCustomGLSLDiffuseSpecularShaderMT }
  547. procedure TgxCustomGLSLDiffuseSpecularShaderMT.DoInitialize(var rci: TgxRenderContextInfo; Sender: TObject);
  548. begin
  549. GetVertexProgramCode(VertexProgram.Code, IsFogEnabled(FFogSupport, rci), rci);
  550. GetFragmentProgramCode(FragmentProgram.Code, FRealisticSpecular, IsFogEnabled(FFogSupport, rci), rci);
  551. VertexProgram.Enabled := True;
  552. FragmentProgram.Enabled := True;
  553. inherited;
  554. end;
  555. { TgxCustomGLSLDiffuseSpecularShader }
  556. procedure TgxCustomGLSLDiffuseSpecularShader.DoApply(
  557. var rci: TgxRenderContextInfo; Sender: TObject);
  558. begin
  559. inherited;
  560. Param['MainTexture'].AsVector1i := 0; // Use the current texture.
  561. end;
  562. procedure TgxCustomGLSLDiffuseSpecularShader.DoInitialize(var rci: TgxRenderContextInfo; Sender: TObject);
  563. begin
  564. GetVertexProgramCode(VertexProgram.Code, IsFogEnabled(FFogSupport, rci), rci);
  565. GetFragmentProgramCode(FragmentProgram.Code, FRealisticSpecular, IsFogEnabled(FFogSupport, rci), rci);
  566. VertexProgram.Enabled := True;
  567. FragmentProgram.Enabled := True;
  568. inherited;
  569. end;
  570. { TgxCustomGLSLMLDiffuseSpecularShader }
  571. constructor TgxCustomGLSLMLDiffuseSpecularShader.Create(
  572. AOwner: TComponent);
  573. begin
  574. inherited;
  575. end;
  576. procedure TgxCustomGLSLMLDiffuseSpecularShader.DoApply(var rci: TgxRenderContextInfo; Sender: TObject);
  577. var
  578. I: Integer;
  579. scene: TgxScene;
  580. needRecompile: Boolean;
  581. begin
  582. scene := TgxScene(rci.scene);
  583. needRecompile := False;
  584. for I := 0 to scene.Lights.Count - 1 do
  585. begin
  586. if Assigned(scene.Lights[I]) then
  587. begin
  588. if FLightTrace[I].Enabled <> TgxLightSource(scene.Lights[I]).Shining then
  589. begin
  590. needRecompile := True;
  591. break;
  592. end;
  593. if FLightTrace[I].Style <> TgxLightSource(scene.Lights[I]).LightStyle then
  594. begin
  595. needRecompile := True;
  596. break;
  597. end;
  598. end
  599. else
  600. if FLightTrace[I].Enabled then
  601. begin
  602. needRecompile := True;
  603. break;
  604. end;
  605. end;
  606. if needRecompile then
  607. begin
  608. FinalizeShader;
  609. InitializeShader(rci, Sender);
  610. end;
  611. inherited;
  612. Param['MainTexture'].AsVector1i := 0; // Use the current texture.
  613. end;
  614. procedure TgxCustomGLSLMLDiffuseSpecularShader.DoInitialize(var rci: TgxRenderContextInfo; Sender: TObject);
  615. var
  616. I: Integer;
  617. scene: TgxScene;
  618. begin
  619. GetVertexProgramCode(VertexProgram.Code, IsFogEnabled(FFogSupport, rci), rci);
  620. with FragmentProgram.Code do
  621. begin
  622. GetMLFragmentProgramCodeBeg(FragmentProgram.Code, IsFogEnabled(FFogSupport, rci));
  623. // Repeat for all lights.
  624. scene := TgxScene(rci.scene);
  625. for I := 0 to scene.Lights.Count - 1 do
  626. begin
  627. if Assigned(scene.Lights[I]) then
  628. begin
  629. FLightTrace[I].Enabled := TgxLightSource(scene.Lights[I]).Shining;
  630. FLightTrace[I].Style := TgxLightSource(scene.Lights[I]).LightStyle;
  631. if FLightTrace[I].Enabled then
  632. GetMLFragmentProgramCodeMid(FragmentProgram.Code, I, FLightTrace[I].Style);
  633. end
  634. else
  635. FLightTrace[I].Enabled := False;
  636. end;
  637. GetMLFragmentProgramCodeEnd(FragmentProgram.Code,
  638. FRealisticSpecular, IsFogEnabled(FFogSupport, rci));
  639. end;
  640. VertexProgram.Enabled := True;
  641. FragmentProgram.Enabled := True;
  642. inherited DoInitialize(rci, Sender);
  643. end;
  644. { TgxCustomGLSLMLDiffuseSpecularShaderMT }
  645. constructor TgxCustomGLSLMLDiffuseSpecularShaderMT.Create(
  646. AOwner: TComponent);
  647. begin
  648. inherited;
  649. end;
  650. procedure TgxCustomGLSLMLDiffuseSpecularShaderMT.DoApply(
  651. var rci: TgxRenderContextInfo; Sender: TObject);
  652. var
  653. I: Integer;
  654. scene: TgxScene;
  655. needRecompile: Boolean;
  656. begin
  657. scene := TgxScene(rci.scene);
  658. needRecompile := False;
  659. for I := 0 to scene.Lights.Count - 1 do
  660. begin
  661. if Assigned(scene.Lights[I]) then
  662. begin
  663. if FLightTrace[I].Enabled <> TgxLightSource(scene.Lights[I]).Shining then
  664. begin
  665. needRecompile := True;
  666. break;
  667. end;
  668. if FLightTrace[I].Style <> TgxLightSource(scene.Lights[I]).LightStyle then
  669. begin
  670. needRecompile := True;
  671. break;
  672. end;
  673. end
  674. else
  675. if FLightTrace[I].Enabled then
  676. begin
  677. needRecompile := True;
  678. break;
  679. end;
  680. end;
  681. if needRecompile then
  682. begin
  683. FinalizeShader;
  684. InitializeShader(rci, Sender);
  685. end;
  686. inherited;
  687. end;
  688. procedure TgxCustomGLSLMLDiffuseSpecularShaderMT.DoInitialize(var rci: TgxRenderContextInfo; Sender: TObject);
  689. var
  690. I: Integer;
  691. scene: TgxScene;
  692. begin
  693. GetVertexProgramCode(VertexProgram.Code, IsFogEnabled(FFogSupport, rci), rci);
  694. with FragmentProgram.Code do
  695. begin
  696. GetMLFragmentProgramCodeBeg(FragmentProgram.Code, IsFogEnabled(FFogSupport, rci));
  697. // Repeat for all lights.
  698. scene := TgxScene(rci.scene);
  699. for I := 0 to scene.Lights.Count - 1 do
  700. begin
  701. if Assigned(scene.Lights[I]) then
  702. begin
  703. FLightTrace[I].Enabled := TgxLightSource(scene.Lights[I]).Shining;
  704. FLightTrace[I].Style := TgxLightSource(scene.Lights[I]).LightStyle;
  705. if FLightTrace[I].Enabled then
  706. GetMLFragmentProgramCodeMid(FragmentProgram.Code, I, FLightTrace[I].Style);
  707. end
  708. else
  709. FLightTrace[I].Enabled := False;
  710. end;
  711. GetMLFragmentProgramCodeEnd(FragmentProgram.Code,
  712. FRealisticSpecular, IsFogEnabled(FFogSupport, rci));
  713. end;
  714. VertexProgram.Enabled := True;
  715. FragmentProgram.Enabled := True;
  716. inherited;
  717. end;
  718. initialization
  719. RegisterClasses([
  720. TgxCustomGLSLDiffuseSpecularShader,
  721. TgxCustomGLSLDiffuseSpecularShaderMT,
  722. TgxCustomGLSLMLDiffuseSpecularShader,
  723. TgxCustomGLSLMLDiffuseSpecularShaderMT,
  724. TgxSLDiffuseSpecularShader,
  725. TgxSLDiffuseSpecularShaderMT,
  726. TgxSLMLDiffuseSpecularShader,
  727. TgxSLMLDiffuseSpecularShaderMT
  728. ]);
  729. end.