GLSL.DiffuseSpecularShader.pas 26 KB

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