2
0

GXSL.DiffuseSpecularShader.pas 26 KB

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