GLSL.BumpShaders.pas 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928
  1. //
  2. // The graphics engine GLScene https://github.com/glscene
  3. //
  4. unit GLSL.BumpShaders;
  5. (*
  6. A GLSL shader that applies bump mapping.
  7. This is a collection of GLSL Bump shaders, comes in these variaties
  8. (to know what these abriviations mean, see GLCustomShader.pas):
  9. - TGLSLBumpShader
  10. - TGLSLBumpShaderMT
  11. - TGLSLBumpShaderAM
  12. - TGLSLMLBumpShader
  13. - TGLSLMLBumpShaderMT
  14. Notes:
  15. 1) Alpha is a synthetic property, in real life your should set each
  16. color's Alpha individualy
  17. 2) TGLSLMLBumpShader takes all Light parameters directly
  18. from OpenGL (that includes TGLLightSource's)
  19. TODO:
  20. 1) Implement IGLShaderDescription in all shaders.
  21. *)
  22. interface
  23. uses
  24. Winapi.OpenGL,
  25. Winapi.OpenGLext,
  26. System.Classes,
  27. System.SysUtils,
  28. GLScene.OpenGLTokens,
  29. GLScene.VectorTypes,
  30. GLScene.VectorGeometry,
  31. GLS.Material,
  32. GLS.Graphics,
  33. GLScene.VectorLists,
  34. GLS.Color,
  35. GLS.RenderContextInfo,
  36. GLS.State,
  37. GLScene.TextureFormat,
  38. GLS.Texture,
  39. GLS.Scene,
  40. GLS.Context,
  41. GLS.Cadencer,
  42. GLScene.Strings,
  43. GLSL.Shader,
  44. GLSL.CustomShader,
  45. GLScene.Utils;
  46. type
  47. TBumpMethod = (bmDot3TexCombiner, bmBasicARBFP);
  48. TBumpSpace = (bsObject, bsTangentExternal, bsTangentQuaternion);
  49. TBumpOption = (boDiffuseTexture2, // Use secondary texture as diffuse
  50. boSpecularTexture3, // Use tertiary texture as specular
  51. boUseSecondaryTexCoords, // Pass through secondary texcoords
  52. boLightAttenuation, // Use light attenuation
  53. boParallaxMapping // Enable parallax offset mapping
  54. );
  55. TBumpOptions = set of TBumpOption;
  56. TSpecularMode = (smOff, smBlinn, smPhong);
  57. EGLSLBumpShaderException = class(EGLSLShaderException);
  58. // An abstract class.
  59. TGLBaseCustomGLSLBumpShader = class(TGLCustomGLSLShader, IGLMaterialLibrarySupported)
  60. private
  61. FBumpHeight: Single;
  62. FBumpSmoothness: Integer;
  63. FSpecularPower: Single;
  64. FSpecularSpread: Single;
  65. FLightPower: Single;
  66. FMaterialLibrary: TGLMaterialLibrary;
  67. FNormalTexture: TGLTexture;
  68. FSpecularTexture: TGLTexture;
  69. FNormalTextureName: TGLLibMaterialName;
  70. FSpecularTextureName: TGLLibMaterialName;
  71. function GetNormalTextureName: TGLLibMaterialName;
  72. function GetSpecularTextureName: TGLLibMaterialName;
  73. procedure SetNormalTextureName(const Value: TGLLibMaterialName);
  74. procedure SetSpecularTextureName(const Value: TGLLibMaterialName);
  75. procedure SetSpecularTexture(const Value: TGLTexture);
  76. procedure SetNormalTexture(const Value: TGLTexture);
  77. // Implementing IGLMaterialLibrarySupported.
  78. function GetMaterialLibrary: TGLAbstractMaterialLibrary;
  79. protected
  80. procedure DoApply(var rci : TGLRenderContextInfo; Sender : TObject); override;
  81. function DoUnApply(var rci: TGLRenderContextInfo): Boolean; override;
  82. procedure SetMaterialLibrary(const Value: TGLMaterialLibrary); virtual;
  83. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  84. public
  85. constructor Create(AOwner : TComponent); override;
  86. property BumpHeight: Single read FBumpHeight write FBumpHeight;
  87. property BumpSmoothness: Integer read FBumpSmoothness write FBumpSmoothness;
  88. property SpecularPower: Single read FSpecularPower write FSpecularPower;
  89. property SpecularSpread: Single read FSpecularSpread write FSpecularSpread;
  90. property LightPower: Single read FLightPower write FLightPower;
  91. property NormalTexture: TGLTexture read FNormalTexture write SetNormalTexture;
  92. property SpecularTexture: TGLTexture read FSpecularTexture write SetSpecularTexture;
  93. property NormalTextureName: TGLLibMaterialName read GetNormalTextureName write SetNormalTextureName;
  94. property SpecularTextureName: TGLLibMaterialName read GetSpecularTextureName write SetSpecularTextureName;
  95. property MaterialLibrary: TGLMaterialLibrary read FMaterialLibrary write SetMaterialLibrary;
  96. end;
  97. // An abstract class.
  98. TGLBaseCustomGLSLBumpShaderMT = class(TGLBaseCustomGLSLBumpShader)
  99. private
  100. FMainTexture: TGLTexture;
  101. FMainTextureName: TGLLibMaterialName;
  102. function GetMainTextureName: string;
  103. procedure SetMainTextureName(const Value: string);
  104. protected
  105. procedure SetMaterialLibrary(const Value: TGLMaterialLibrary); override;
  106. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  107. public
  108. property MainTexture: TGLTexture read FMainTexture write FMainTexture;
  109. property MainTextureName: TGLLibMaterialName read GetMainTextureName write SetMainTextureName;
  110. end;
  111. // One Light shaders.
  112. TGLCustomGLSLBumpShaderAM = class(TGLBaseCustomGLSLBumpShaderMT)
  113. private
  114. FAmbientColor: TGLColor;
  115. FDiffuseColor: TGLColor;
  116. FSpecularColor: TGLColor;
  117. function GetAlpha: Single;
  118. procedure SetAlpha(const Value: Single);
  119. protected
  120. procedure DoApply(var rci : TGLRenderContextInfo; Sender : TObject); override;
  121. procedure DoInitialize(var rci : TGLRenderContextInfo; Sender : TObject); override;
  122. public
  123. constructor Create(AOwner : TComponent); override;
  124. destructor Destroy; override;
  125. property AmbientColor: TGLColor read FAmbientColor;
  126. property DiffuseColor: TGLColor read FDiffuseColor;
  127. property SpecularColor: TGLColor read FSpecularColor;
  128. property Alpha: Single read GetAlpha write SetAlpha;
  129. end;
  130. TGLCustomGLSLBumpShaderMT = class(TGLBaseCustomGLSLBumpShaderMT)
  131. protected
  132. procedure DoApply(var rci : TGLRenderContextInfo; Sender : TObject); override;
  133. procedure DoInitialize(var rci : TGLRenderContextInfo; Sender : TObject); override;
  134. end;
  135. TGLCustomGLSLBumpShader = class(TGLBaseCustomGLSLBumpShader, IGLShaderDescription)
  136. private
  137. // Implementing IGLShaderDescription.
  138. procedure SetShaderTextures(const Textures: array of TGLTexture);
  139. procedure GetShaderTextures(var Textures: array of TGLTexture);
  140. procedure SetShaderColorParams(const AAmbientColor, ADiffuseColor, ASpecularcolor: TVector4f);
  141. procedure GetShaderColorParams(var AAmbientColor, ADiffuseColor, ASpecularcolor: TVector4f);
  142. procedure SetShaderMiscParameters(const ACadencer: TGLCadencer; const AMatLib: TGLMaterialLibrary; const ALightSources: TGLLightSourceSet);
  143. procedure GetShaderMiscParameters(var ACadencer: TGLCadencer; var AMatLib: TGLMaterialLibrary; var ALightSources: TGLLightSourceSet);
  144. function GetShaderAlpha: Single;
  145. procedure SetShaderAlpha(const Value: Single);
  146. function GetShaderDescription: string;
  147. protected
  148. procedure DoApply(var rci : TGLRenderContextInfo; Sender : TObject); override;
  149. procedure DoInitialize(var rci : TGLRenderContextInfo; Sender : TObject); override;
  150. end;
  151. // MultiLight shaders.
  152. TGLCustomGLSLMLBumpShader = class(TGLBaseCustomGLSLBumpShader, IGLShaderDescription)
  153. private
  154. FLightSources: TGLLightSourceSet;
  155. FLightCompensation: Single;
  156. procedure SetLightSources(const Value: TGLLightSourceSet);
  157. procedure SetLightCompensation(const Value: Single);
  158. // Implementing IGLShaderDescription.
  159. procedure SetShaderTextures(const Textures: array of TGLTexture);
  160. procedure GetShaderTextures(var Textures: array of TGLTexture);
  161. procedure SetShaderColorParams(const AAmbientColor, ADiffuseColor, ASpecularcolor: TVector4f);
  162. procedure GetShaderColorParams(var AAmbientColor, ADiffuseColor, ASpecularcolor: TVector4f);
  163. procedure SetShaderMiscParameters(const ACadencer: TGLCadencer; const AMatLib: TGLMaterialLibrary; const ALightSources: TGLLightSourceSet);
  164. procedure GetShaderMiscParameters(var ACadencer: TGLCadencer; var AMatLib: TGLMaterialLibrary; var ALightSources: TGLLightSourceSet);
  165. function GetShaderAlpha: Single;
  166. procedure SetShaderAlpha(const Value: Single);
  167. function GetShaderDescription: string;
  168. protected
  169. procedure DoApply(var rci : TGLRenderContextInfo; Sender : TObject); override;
  170. procedure DoInitialize(var rci : TGLRenderContextInfo; Sender : TObject); override;
  171. public
  172. constructor Create(AOwner : TComponent); override;
  173. property LightSources: TGLLightSourceSet read FLightSources write SetLightSources default [1];
  174. {Setting LightCompensation to a value less than 1 decreeses individual
  175. light intensity when using multiple lights }
  176. property LightCompensation: Single read FLightCompensation write SetLightCompensation;
  177. end;
  178. TGLCustomGLSLMLBumpShaderMT = class(TGLBaseCustomGLSLBumpShaderMT)
  179. private
  180. FLightSources: TGLLightSourceSet;
  181. FLightCompensation: Single;
  182. procedure SetLightSources(const Value: TGLLightSourceSet);
  183. procedure SetLightCompensation(const Value: Single);
  184. protected
  185. procedure DoApply(var rci : TGLRenderContextInfo; Sender : TObject); override;
  186. procedure DoInitialize(var rci : TGLRenderContextInfo; Sender : TObject); override;
  187. public
  188. constructor Create(AOwner : TComponent); override;
  189. property LightSources: TGLLightSourceSet read FLightSources write SetLightSources default [1];
  190. (* Setting LightCompensation to a value less than 1 decreeses individual
  191. light intensity when using multiple lights *)
  192. property LightCompensation: Single read FLightCompensation write SetLightCompensation;
  193. end;
  194. {************** Published **************}
  195. // One light shaders.
  196. TGLSLBumpShaderMT = class(TGLCustomGLSLBumpShaderMT)
  197. published
  198. property MainTextureName;
  199. property NormalTextureName;
  200. property SpecularTextureName;
  201. property MaterialLibrary;
  202. property BumpHeight;
  203. property BumpSmoothness;
  204. property SpecularPower;
  205. property SpecularSpread;
  206. property LightPower;
  207. end;
  208. TGLSLBumpShader = class(TGLCustomGLSLBumpShader)
  209. published
  210. property NormalTextureName;
  211. property SpecularTextureName;
  212. property MaterialLibrary;
  213. property BumpHeight;
  214. property BumpSmoothness;
  215. property SpecularPower;
  216. property SpecularSpread;
  217. property LightPower;
  218. end;
  219. TGLSLBumpShaderAM = class(TGLCustomGLSLBumpShaderAM)
  220. published
  221. property AmbientColor;
  222. property DiffuseColor;
  223. property SpecularColor;
  224. property Alpha stored False;
  225. property MainTextureName;
  226. property NormalTextureName;
  227. property SpecularTextureName;
  228. property MaterialLibrary;
  229. property BumpHeight;
  230. property BumpSmoothness;
  231. property SpecularPower;
  232. property SpecularSpread;
  233. property LightPower;
  234. end;
  235. // Multi light shaders.
  236. TGLSLMLBumpShader = class(TGLCustomGLSLMLBumpShader)
  237. published
  238. property NormalTextureName;
  239. property SpecularTextureName;
  240. property MaterialLibrary;
  241. property BumpHeight;
  242. property BumpSmoothness;
  243. property SpecularPower;
  244. property SpecularSpread;
  245. property LightPower;
  246. property LightSources;
  247. property LightCompensation;
  248. end;
  249. TGLSLMLBumpShaderMT = class(TGLCustomGLSLMLBumpShaderMT)
  250. published
  251. property MainTextureName;
  252. property NormalTextureName;
  253. property SpecularTextureName;
  254. property MaterialLibrary;
  255. property BumpHeight;
  256. property BumpSmoothness;
  257. property SpecularPower;
  258. property SpecularSpread;
  259. property LightPower;
  260. property LightSources;
  261. property LightCompensation;
  262. end;
  263. (*
  264. A shader that applies bump mapping.
  265. Notes:
  266. The normal map is expected to be the primary texture.
  267. The secondary texture is used for the diffuse texture,
  268. to enable set boDiffuseTexture2 in the BumpOptions property.
  269. The tertiary texture is used for the specular texture,
  270. to enable set boSpecularTexture3 in the BumpOptions property.
  271. The SpecularMode determines the specular highlight calculation
  272. (Blinn or Phong), smOff disables specular highlights in the
  273. shader.
  274. External tangent bump space expects tangent data under
  275. GL_TEXTURE1_ARB and binormal data under GL_TEXTURE2_ARB.
  276. The boUseSecondaryTexCoords bump option tells the shader to use
  277. the secondary texture coordinates for the diffuse and specular
  278. texture lookups.
  279. *)
  280. // A generic bump shader.
  281. TGLBumpShader = class(TGLShader)
  282. private
  283. FVertexProgramHandle: TGLARBVertexProgramHandle;
  284. FFragmentProgramHandle: TGLARBFragmentProgramHandle;
  285. FLightIDs: TGIntegerList;
  286. FLightsEnabled: Integer;
  287. FBumpMethod: TBumpMethod;
  288. FBumpSpace: TBumpSpace;
  289. FBumpOptions: TBumpOptions;
  290. FSpecularMode: TSpecularMode;
  291. FDesignTimeEnabled: Boolean;
  292. FAmbientPass: Boolean;
  293. FDiffusePass: Boolean;
  294. FVertexProgram: TStringList;
  295. FFragmentProgram: TStringList;
  296. FParallaxOffset: Single;
  297. function GenerateVertexProgram: string;
  298. function GenerateFragmentProgram: string;
  299. procedure DoLightPass(var rci: TGLRenderContextInfo; lightID: Cardinal);
  300. protected
  301. procedure SetBumpMethod(const Value: TBumpMethod);
  302. procedure SetBumpSpace(const Value: TBumpSpace);
  303. procedure SetBumpOptions(const Value: TBumpOptions);
  304. procedure SetSpecularMode(const Value: TSpecularMode);
  305. procedure SetDesignTimeEnabled(const Value: Boolean);
  306. procedure SetParallaxOffset(const Value: Single);
  307. procedure Loaded; override;
  308. procedure DeleteVertexPrograms;
  309. procedure DeleteFragmentPrograms;
  310. public
  311. constructor Create(AOwner: TComponent); override;
  312. destructor Destroy; override;
  313. procedure DoApply(var rci: TGLRenderContextInfo; Sender: TObject); override;
  314. function DoUnApply(var rci: TGLRenderContextInfo): Boolean; override;
  315. published
  316. property BumpMethod: TBumpMethod read FBumpMethod write SetBumpMethod;
  317. property BumpSpace: TBumpSpace read FBumpSpace write SetBumpSpace;
  318. property BumpOptions: TBumpOptions read FBumpOptions write SetBumpOptions;
  319. property SpecularMode: TSpecularMode read FSpecularMode write
  320. SetSpecularMode;
  321. property DesignTimeEnabled: Boolean read FDesignTimeEnabled write
  322. SetDesignTimeEnabled;
  323. property ParallaxOffset: Single read FParallaxOffset write
  324. SetParallaxOffset;
  325. end;
  326. //--------------------------------------------------------------
  327. implementation
  328. //--------------------------------------------------------------
  329. procedure GetVertexProgramCode(const Code: TStrings);
  330. begin
  331. with Code do
  332. begin
  333. Clear;
  334. Add('varying vec2 Texcoord; ');
  335. Add('varying vec3 ViewDirection; ');
  336. Add('varying vec3 LightDirection; ');
  337. Add(' ');
  338. Add('void main( void ) ');
  339. Add('{ ');
  340. Add(' gl_Position = ftransform(); ');
  341. Add(' Texcoord = gl_MultiTexCoord0.xy; ');
  342. Add(' ');
  343. Add(' vec3 fvViewDirection = (gl_ModelViewMatrix * gl_Vertex).xyz; ');
  344. Add(' vec3 fvLightDirection = gl_LightSource[0].position.xyz - fvViewDirection; ');
  345. Add(' ');
  346. Add(' vec3 fvNormal = gl_NormalMatrix * gl_Normal; ');
  347. Add(' vec3 fvBinormal = gl_NormalMatrix * gl_MultiTexCoord2.xyz; ');
  348. Add(' vec3 fvTangent = gl_NormalMatrix * gl_MultiTexCoord1.xyz; ');
  349. Add(' ');
  350. Add(' ViewDirection.x = dot( fvTangent, fvViewDirection ); ');
  351. Add(' ViewDirection.y = dot( fvBinormal, fvViewDirection ); ');
  352. Add(' ViewDirection.z = dot( fvNormal, fvViewDirection ); ');
  353. Add(' ');
  354. Add(' LightDirection.x = dot( fvTangent, fvLightDirection ); ');
  355. Add(' LightDirection.y = dot( fvBinormal, fvLightDirection ); ');
  356. Add(' LightDirection.z = dot( fvNormal, fvLightDirection ); ');
  357. Add(' ');
  358. Add(' LightDirection = normalize(LightDirection); ');
  359. Add(' ViewDirection = normalize(ViewDirection); ');
  360. Add('} ');
  361. end;
  362. end;
  363. procedure GetFragmentProgramCodeMP(const Code: TStrings; const UseSpecularMap: Boolean; const UseNormalMap: Boolean);
  364. begin
  365. with Code do
  366. begin
  367. Clear;
  368. Add('uniform vec4 fvAmbient; ');
  369. Add('uniform vec4 fvSpecular; ');
  370. Add('uniform vec4 fvDiffuse; ');
  371. Add(' ');
  372. Add('uniform float fLightPower; ');
  373. Add('uniform float fSpecularPower; ');
  374. Add('uniform float fSpecularSpread; ');
  375. if UseNormalMap then
  376. begin
  377. Add('uniform sampler2D bumpMap; ');
  378. Add('uniform float fBumpHeight; ');
  379. Add('uniform float fBumpSmoothness; ');
  380. end;
  381. Add(' ');
  382. Add('uniform sampler2D baseMap; ');
  383. if UseSpecularMap then
  384. Add('uniform sampler2D specMap; ');
  385. Add(' ');
  386. Add('varying vec2 Texcoord; ');
  387. Add('varying vec3 ViewDirection; ');
  388. Add('varying vec3 LightDirection; ');
  389. Add(' ');
  390. Add('void main( void ) ');
  391. Add('{ ');
  392. if UseNormalMap then
  393. Add(' vec3 fvNormal = normalize( ( texture2D( bumpMap, Texcoord ).xyz * fBumpSmoothness) - fBumpHeight * fBumpSmoothness); ')
  394. else
  395. Add(' vec3 fvNormal = vec3(0.0, 0.0, 1);');
  396. Add(' ');
  397. Add(' float fNDotL = dot( fvNormal, LightDirection ); ');
  398. Add(' vec3 fvReflection = normalize( ( (fSpecularSpread * fvNormal ) * fNDotL ) - LightDirection ); ');
  399. Add(' ');
  400. Add(' float fRDotV = max( dot( fvReflection, -ViewDirection ), 0.0 ); ');
  401. Add(' ');
  402. Add(' vec4 fvBaseColor = texture2D( baseMap, Texcoord ); ');
  403. if UseSpecularMap then
  404. Add(' vec4 fvSpecColor = texture2D( specMap, Texcoord ) * fvSpecular; ')
  405. else
  406. Add(' vec4 fvSpecColor = fvSpecular; ');
  407. Add(' ');
  408. Add(' vec4 fvTotalDiffuse = clamp(fvDiffuse * fNDotL, 0.0, 1.0); ');
  409. Add(' ');
  410. Add(' // (fvTotalDiffuse + 0.2) / 1.2 is used for removing artefacts on the non-lit side ');
  411. Add(' vec4 fvTotalSpecular = clamp((pow(fRDotV, fSpecularPower ) ) * (fvTotalDiffuse + 0.2) / 1.2 * fvSpecColor, 0.0, 1.0); ');
  412. Add(' ');
  413. Add(' gl_FragColor = fLightPower * (fvBaseColor * ( fvAmbient + fvTotalDiffuse ) + fvTotalSpecular); ');
  414. Add('} ');
  415. end;
  416. end;
  417. procedure GetFragmentProgramCode(const Code: TStrings; const UseSpecularMap: Boolean; const UseNormalMap: Boolean);
  418. begin
  419. with Code do
  420. begin
  421. Clear;
  422. Add('uniform float fLightPower; ');
  423. Add('uniform float fSpecularPower; ');
  424. Add('uniform float fSpecularSpread; ');
  425. if UseNormalMap then
  426. begin
  427. Add('uniform sampler2D bumpMap; ');
  428. Add('uniform float fBumpHeight; ');
  429. Add('uniform float fBumpSmoothness; ');
  430. end;
  431. Add(' ');
  432. Add('uniform sampler2D baseMap; ');
  433. if UseSpecularMap then
  434. Add('uniform sampler2D specMap; ');
  435. Add(' ');
  436. Add('varying vec2 Texcoord; ');
  437. Add('varying vec3 ViewDirection; ');
  438. Add('varying vec3 LightDirection; ');
  439. Add(' ');
  440. Add('void main( void ) ');
  441. Add('{ ');
  442. if UseNormalMap then
  443. Add(' vec3 fvNormal = normalize( ( texture2D( bumpMap, Texcoord ).xyz * fBumpSmoothness) - fBumpHeight * fBumpSmoothness); ')
  444. else
  445. Add(' vec3 fvNormal = vec3(0.0, 0.0, 1.0);');
  446. Add(' ');
  447. Add(' float fNDotL = dot( fvNormal, LightDirection ); ');
  448. Add(' vec3 fvReflection = normalize( ( (fSpecularSpread * fvNormal ) * fNDotL ) - LightDirection ); ');
  449. Add(' ');
  450. Add(' float fRDotV = max(dot( fvReflection, -ViewDirection ), 0.0); ');
  451. Add(' ');
  452. Add(' vec4 fvBaseColor = texture2D( baseMap, Texcoord ); ');
  453. if UseSpecularMap then
  454. Add(' vec4 fvSpecColor = texture2D( specMap, Texcoord ) * gl_LightSource[0].specular; ')
  455. else
  456. Add(' vec4 fvSpecColor = gl_LightSource[0].specular; ');
  457. Add(' ');
  458. Add(' vec4 fvTotalDiffuse = clamp(gl_LightSource[0].diffuse * fNDotL, 0.0, 1.0); ');
  459. Add(' ');
  460. Add(' // (fvTotalDiffuse + 0.2) / 1.2 is used for removing artefacts on the non-lit side ');
  461. Add(' vec4 fvTotalSpecular = clamp((pow(fRDotV, fSpecularPower ) ) * (fvTotalDiffuse + 0.2) / 1.2 * fvSpecColor, 0.0, 1.0); ');
  462. Add(' ');
  463. Add(' gl_FragColor = fLightPower * (fvBaseColor * ( gl_LightSource[0].ambient + fvTotalDiffuse ) + fvTotalSpecular); ');
  464. Add('} ');
  465. end;
  466. end;
  467. procedure GetMLVertexProgramCode(const Code: TStrings);
  468. begin
  469. with Code do
  470. begin
  471. Clear;
  472. Add('varying vec2 Texcoord; ');
  473. Add('varying vec3 ViewDirection; ');
  474. Add(' ');
  475. Add('varying vec3 fvViewDirection; ');
  476. Add('varying vec3 fvNormal; ');
  477. Add('varying vec3 fvBinormal; ');
  478. Add('varying vec3 fvTangent; ');
  479. Add(' ');
  480. Add('void main( void ) ');
  481. Add('{ ');
  482. Add(' gl_Position = ftransform(); ');
  483. Add(' Texcoord = gl_MultiTexCoord0.xy; ');
  484. Add(' ');
  485. Add(' fvViewDirection = (gl_ModelViewMatrix * gl_Vertex).xyz; ');
  486. Add(' ');
  487. Add(' fvNormal = gl_NormalMatrix * gl_Normal; ');
  488. Add(' fvBinormal = gl_NormalMatrix * gl_MultiTexCoord2.xyz; ');
  489. Add(' fvTangent = gl_NormalMatrix * gl_MultiTexCoord1.xyz; ');
  490. Add(' ');
  491. Add(' ViewDirection.x = dot( fvTangent, fvViewDirection ); ');
  492. Add(' ViewDirection.y = dot( fvBinormal, fvViewDirection ); ');
  493. Add(' ViewDirection.z = dot( fvNormal, fvViewDirection ); ');
  494. Add(' ');
  495. Add(' ViewDirection = normalize(ViewDirection); ');
  496. Add('} ');
  497. end;
  498. end;
  499. procedure GetMLFragmentProgramCodeBeg(const Code: TStrings; const UseSpecularMap: Boolean; const UseNormalMap: Boolean);
  500. begin
  501. with Code do
  502. begin
  503. Clear;
  504. Add('uniform float fLightPower; ');
  505. Add('uniform float fSpecularPower; ');
  506. Add('uniform float fSpecularSpread; ');
  507. if UseNormalMap then
  508. begin
  509. Add('uniform sampler2D bumpMap; ');
  510. Add('uniform float fBumpHeight; ');
  511. Add('uniform float fBumpSmoothness; ');
  512. end;
  513. Add(' ');
  514. Add('uniform sampler2D baseMap; ');
  515. if UseSpecularMap then
  516. Add('uniform sampler2D specMap; ');
  517. Add(' ');
  518. Add('varying vec2 Texcoord; ');
  519. Add('varying vec3 ViewDirection; ');
  520. Add(' ');
  521. Add('varying vec3 fvViewDirection; ');
  522. Add('varying vec3 fvNormal; ');
  523. Add('varying vec3 fvBinormal; ');
  524. Add('varying vec3 fvTangent; ');
  525. Add(' ');
  526. Add('void main( void ) ');
  527. Add('{ ');
  528. Add(' vec3 LightDirection;');
  529. Add(' vec3 fvLightDirection; ');
  530. Add(' ');
  531. if UseNormalMap then
  532. Add(' vec3 fvBumpNormal = normalize( ( texture2D( bumpMap, Texcoord ).xyz * fBumpSmoothness) - fBumpHeight * fBumpSmoothness); ')
  533. else
  534. Add(' vec3 fvBumpNormal = vec3(0.0, 0.0, 1);');
  535. Add(' ');
  536. Add(' float fNDotL ; ');
  537. Add(' vec3 fvReflection ; ');
  538. Add(' float fRDotV ; ');
  539. Add(' vec4 fvBaseColor = texture2D( baseMap, Texcoord ); ');
  540. if UseSpecularMap then
  541. Add(' vec4 fvSpecColor = texture2D( specMap, Texcoord ); ')
  542. else
  543. Add(' vec4 fvSpecColor = vec4(1.0, 1.0, 1.0, 1.0); ');
  544. Add(' vec4 fvNewDiffuse ; ');
  545. Add(' vec4 fvTotalDiffuse = vec4(0, 0, 0, 0); ');
  546. Add(' vec4 fvTotalAmbient = vec4(0, 0, 0, 0); ');
  547. Add(' vec4 fvTotalSpecular = vec4(0, 0, 0, 0); ');
  548. end;
  549. end;
  550. procedure GetMLFragmentProgramCodeMid(const Code: TStrings; const CurrentLight: Integer);
  551. begin
  552. with Code do
  553. begin
  554. Add(' fvLightDirection = gl_LightSource[' + IntToStr(CurrentLight) + '].position.xyz - fvViewDirection; ');
  555. Add(' ');
  556. Add(' LightDirection.x = dot( fvTangent, fvLightDirection ); ');
  557. Add(' LightDirection.y = dot( fvBinormal, fvLightDirection ); ');
  558. Add(' LightDirection.z = dot( fvNormal, fvLightDirection ); ');
  559. Add(' LightDirection = normalize(LightDirection); ');
  560. Add(' ');
  561. Add(' fNDotL = dot( fvBumpNormal, LightDirection ); ');
  562. Add(' fvReflection = normalize( ( (fSpecularSpread * fvBumpNormal ) * fNDotL ) - LightDirection ); ');
  563. Add(' fRDotV = max( dot( fvReflection, -ViewDirection ), 0.0 ); ');
  564. Add(' fvNewDiffuse = clamp(gl_LightSource[' + IntToStr(CurrentLight) + '].diffuse * fNDotL, 0.0, 1.0); ');
  565. Add(' fvTotalDiffuse = min(fvTotalDiffuse + fvNewDiffuse, 1.0); ');
  566. Add(' fvTotalSpecular = min(fvTotalSpecular + clamp((pow(fRDotV, fSpecularPower ) ) * (fvNewDiffuse + 0.2) / 1.2 * (fvSpecColor * gl_LightSource[' + IntToStr(CurrentLight) + '].specular), 0.0, 1.0), 1.0); ');
  567. Add(' fvTotalAmbient = fvTotalAmbient + gl_LightSource[' + IntToStr(CurrentLight) + '].ambient; ');
  568. end;
  569. end;
  570. procedure GetMLFragmentProgramCodeEnd(const Code: TStrings; const FLightCount: Integer; const FLightCompensation: Single);
  571. var
  572. Temp: AnsiString;
  573. begin
  574. with Code do
  575. begin
  576. Str((1 + (FLightCount - 1) * FLightCompensation) / FLightCount :1 :1, Temp);
  577. if (FLightCount = 1) or (FLightCompensation = 1) then
  578. Add(' gl_FragColor = fLightPower * (fvBaseColor * ( fvTotalAmbient + fvTotalDiffuse ) + fvTotalSpecular); ')
  579. else
  580. Add(' gl_FragColor = fLightPower * (fvBaseColor * ( fvTotalAmbient + fvTotalDiffuse ) + fvTotalSpecular) * ' + string(Temp) + '; ');
  581. Add('} ');
  582. end;
  583. end;
  584. { TGLBaseCustomGLSLBumpShader }
  585. constructor TGLBaseCustomGLSLBumpShader.Create(AOwner: TComponent);
  586. begin
  587. inherited;
  588. FSpecularPower := 6;
  589. FSpecularSpread := 1.5;
  590. FLightPower := 1;
  591. FBumpHeight := 0.5;
  592. FBumpSmoothness := 300;
  593. TStringList(VertexProgram.Code).OnChange := nil;
  594. TStringList(FragmentProgram.Code).OnChange := nil;
  595. VertexProgram.Enabled := True;
  596. FragmentProgram.Enabled := True;
  597. end;
  598. procedure TGLBaseCustomGLSLBumpShader.DoApply(
  599. var rci: TGLRenderContextInfo; Sender: TObject);
  600. begin
  601. // Don't inherit not to call the event.
  602. GetGLSLProg.UseProgramObject;
  603. Param['fSpecularPower'].AsVector1f := FSpecularPower;
  604. Param['fSpecularSpread'].AsVector1f := FSpecularSpread;
  605. Param['fLightPower'].AsVector1f := FLightPower;
  606. if FSpecularTexture <> nil then
  607. Param['specMap'].AsTexture2D[2] := FSpecularTexture;
  608. {$IFNDEF USE_OPTIMIZATIONS}
  609. if FNormalTexture <> nil then
  610. {$ENDIF}
  611. begin
  612. Param['bumpMap'].AsTexture2D[1] := FNormalTexture;
  613. Param['fBumpHeight'].AsVector1f := FBumpHeight;
  614. Param['fBumpSmoothness'].AsVector1f := FBumpSmoothness;
  615. end;
  616. end;
  617. function TGLBaseCustomGLSLBumpShader.DoUnApply(
  618. var rci: TGLRenderContextInfo): Boolean;
  619. begin
  620. //don't inherit not to call the event
  621. Result := False;
  622. GetGLSLProg.EndUseProgramObject;
  623. end;
  624. function TGLBaseCustomGLSLBumpShader.GetMaterialLibrary: TGLAbstractMaterialLibrary;
  625. begin
  626. Result := FMaterialLibrary;
  627. end;
  628. function TGLBaseCustomGLSLBumpShader.GetNormalTextureName: TGLLibMaterialName;
  629. begin
  630. Result := FMaterialLibrary.GetNameOfTexture(FNormalTexture);
  631. if Result = '' then Result := FNormalTextureName;
  632. end;
  633. function TGLBaseCustomGLSLBumpShader.GetSpecularTextureName: TGLLibMaterialName;
  634. begin
  635. Result := FMaterialLibrary.GetNameOfTexture(FSpecularTexture);
  636. if Result = '' then Result := FSpecularTextureName;
  637. end;
  638. procedure TGLBaseCustomGLSLBumpShader.Notification(
  639. AComponent: TComponent; Operation: TOperation);
  640. var
  641. Index: Integer;
  642. begin
  643. inherited;
  644. if Operation = opRemove then
  645. if AComponent = FMaterialLibrary then
  646. if FMaterialLibrary <> nil then
  647. begin
  648. // Need to nil the textures that were ownned by it.
  649. if FNormalTexture <> nil then
  650. begin
  651. Index := FMaterialLibrary.Materials.GetTextureIndex(FNormalTexture);
  652. if Index <> -1 then
  653. SetNormalTexture(nil);
  654. end;
  655. if FSpecularTexture <> nil then
  656. begin
  657. Index := FMaterialLibrary.Materials.GetTextureIndex(FSpecularTexture);
  658. if Index <> -1 then
  659. SetSpecularTexture(nil);
  660. end;
  661. FMaterialLibrary := nil;
  662. end;
  663. end;
  664. procedure TGLBaseCustomGLSLBumpShader.SetMaterialLibrary(
  665. const Value: TGLMaterialLibrary);
  666. begin
  667. if FMaterialLibrary <> nil then
  668. FMaterialLibrary.RemoveFreeNotification(Self);
  669. FMaterialLibrary := Value;
  670. if FMaterialLibrary <> nil then
  671. begin
  672. FMaterialLibrary.FreeNotification(Self);
  673. if FNormalTextureName <> '' then
  674. SetNormalTextureName(FNormalTextureName);
  675. if FSpecularTextureName <> '' then
  676. SetSpecularTextureName(FSpecularTextureName);
  677. end
  678. else
  679. begin
  680. FNormalTextureName := '';
  681. FSpecularTextureName := '';
  682. end;
  683. end;
  684. procedure TGLBaseCustomGLSLBumpShader.SetNormalTexture(
  685. const Value: TGLTexture);
  686. begin
  687. FNormalTexture := Value;
  688. FinalizeShader;
  689. end;
  690. procedure TGLBaseCustomGLSLBumpShader.SetNormalTextureName(
  691. const Value: TGLLibMaterialName);
  692. begin
  693. if FMaterialLibrary = nil then
  694. begin
  695. FNormalTextureName := Value;
  696. if not (csLoading in ComponentState) then
  697. raise EGLSLBumpShaderException.Create(strErrorEx + strMatLibNotDefined);
  698. end
  699. else
  700. begin
  701. SetNormalTexture(FMaterialLibrary.TextureByName(Value));
  702. FNormalTextureName := '';
  703. end;
  704. end;
  705. procedure TGLBaseCustomGLSLBumpShader.SetSpecularTexture(
  706. const Value: TGLTexture);
  707. begin
  708. FSpecularTexture := Value;
  709. FinalizeShader;
  710. end;
  711. procedure TGLBaseCustomGLSLBumpShader.SetSpecularTextureName(
  712. const Value: TGLLibMaterialName);
  713. begin
  714. if FMaterialLibrary = nil then
  715. begin
  716. FSpecularTextureName := Value;
  717. if not (csLoading in ComponentState) then
  718. raise EGLSLBumpShaderException.Create(strErrorEx + strMatLibNotDefined);
  719. end
  720. else
  721. begin
  722. SetSpecularTexture(FMaterialLibrary.TextureByName(Value));
  723. FSpecularTextureName := '';
  724. end;
  725. end;
  726. { TGLBaseCustomGLSLBumpShaderMT }
  727. function TGLBaseCustomGLSLBumpShaderMT.GetMainTextureName: TGLLibMaterialName;
  728. begin
  729. Result := FMaterialLibrary.GetNameOfTexture(FMainTexture);
  730. if Result = '' then Result := FMainTextureName;
  731. end;
  732. procedure TGLBaseCustomGLSLBumpShaderMT.Notification(
  733. AComponent: TComponent; Operation: TOperation);
  734. var
  735. Index: Integer;
  736. begin
  737. if Operation = opRemove then
  738. if AComponent = FMaterialLibrary then
  739. if FMaterialLibrary <> nil then
  740. begin
  741. //need to nil the textures that were ownned by it
  742. if FMainTexture <> nil then
  743. begin
  744. Index := FMaterialLibrary.Materials.GetTextureIndex(FMainTexture);
  745. if Index <> -1 then
  746. FMainTexture := nil;
  747. end;
  748. end;
  749. inherited;
  750. end;
  751. procedure TGLBaseCustomGLSLBumpShaderMT.SetMainTextureName(
  752. const Value: TGLLibMaterialName);
  753. begin
  754. if FMaterialLibrary = nil then
  755. begin
  756. FMainTextureName := Value;
  757. if not (csLoading in ComponentState) then
  758. raise EGLSLBumpShaderException.Create(strErrorEx + strMatLibNotDefined);
  759. end
  760. else
  761. begin
  762. FMainTexture := FMaterialLibrary.TextureByName(Value);
  763. FMainTextureName := '';
  764. end;
  765. end;
  766. procedure TGLBaseCustomGLSLBumpShaderMT.SetMaterialLibrary(
  767. const Value: TGLMaterialLibrary);
  768. begin
  769. inherited;
  770. if FMaterialLibrary <> nil then
  771. begin
  772. if FMainTextureName <> '' then
  773. SetMainTextureName(FMainTextureName);
  774. end
  775. else
  776. FMainTextureName := '';
  777. end;
  778. { TGLCustomGLSLBumpShaderAM }
  779. constructor TGLCustomGLSLBumpShaderAM.Create(AOwner: TComponent);
  780. begin
  781. inherited;
  782. FAmbientColor := TGLColor.Create(Self);
  783. FDiffuseColor := TGLColor.Create(Self);
  784. FSpecularColor := TGLColor.Create(Self);
  785. // Setup initial parameters.
  786. FAmbientColor.SetColor(0.15, 0.15, 0.15, 1);
  787. FDiffuseColor.SetColor(1, 1, 1, 1);
  788. FSpecularColor.SetColor(1, 1, 1, 1);
  789. end;
  790. destructor TGLCustomGLSLBumpShaderAM.Destroy;
  791. begin
  792. FAmbientColor.Destroy;
  793. FDiffuseColor.Destroy;
  794. FSpecularColor.Destroy;
  795. inherited;
  796. end;
  797. procedure TGLCustomGLSLBumpShaderAM.DoApply(var rci: TGLRenderContextInfo;
  798. Sender: TObject);
  799. begin
  800. inherited;
  801. Param['fvAmbient'].AsVector4f := FAmbientColor.Color;
  802. Param['fvDiffuse'].AsVector4f := FDiffuseColor.Color;
  803. Param['fvSpecular'].AsVector4f := FSpecularColor.Color;
  804. Param['baseMap'].AsTexture2D[0] := FMainTexture;
  805. end;
  806. procedure TGLCustomGLSLBumpShaderAM.DoInitialize(var rci : TGLRenderContextInfo; Sender : TObject);
  807. begin
  808. GetVertexProgramCode(VertexProgram.Code);
  809. GetFragmentProgramCodeMP(FragmentProgram.Code, FSpecularTexture <> nil, FNormalTexture <> nil);
  810. VertexProgram.Enabled := True;
  811. FragmentProgram.Enabled := True;
  812. inherited;
  813. end;
  814. function TGLCustomGLSLBumpShaderAM.GetAlpha: Single;
  815. begin
  816. Result := (FAmbientColor.Alpha + FDiffuseColor.Alpha + FSpecularColor.Alpha) / 3;
  817. end;
  818. procedure TGLCustomGLSLBumpShaderAM.SetAlpha(const Value: Single);
  819. begin
  820. FAmbientColor.Alpha := Value;
  821. FDiffuseColor.Alpha := Value;
  822. FSpecularColor.Alpha := Value;
  823. end;
  824. { TGLCustomGLSLMLBumpShaderMT }
  825. constructor TGLCustomGLSLMLBumpShaderMT.Create(AOwner: TComponent);
  826. begin
  827. inherited;
  828. FLightSources := [1];
  829. FLightCompensation := 1;
  830. end;
  831. procedure TGLCustomGLSLMLBumpShaderMT.DoApply(var rci: TGLRenderContextInfo;
  832. Sender: TObject);
  833. begin
  834. inherited;
  835. Param['baseMap'].AsTexture2D[0] := FMainTexture;
  836. end;
  837. procedure TGLCustomGLSLMLBumpShaderMT.DoInitialize(var rci : TGLRenderContextInfo; Sender : TObject);
  838. var
  839. I: Integer;
  840. lLightCount: Integer;
  841. begin
  842. GetMLVertexProgramCode(VertexProgram.Code);
  843. with FragmentProgram.Code do
  844. begin
  845. GetMLFragmentProgramCodeBeg(FragmentProgram.Code, FSpecularTexture <> nil, FNormalTexture <> nil);
  846. lLightCount := 0;
  847. // Repeat for all lights.
  848. for I := 0 to glsShaderMaxLightSources - 1 do
  849. if I + 1 in FLightSources then
  850. begin
  851. GetMLFragmentProgramCodeMid(FragmentProgram.Code, I);
  852. Inc(lLightCount);
  853. end;
  854. GetMLFragmentProgramCodeEnd(FragmentProgram.Code, lLightCount, FLightCompensation);
  855. end;
  856. VertexProgram.Enabled := True;
  857. FragmentProgram.Enabled := True;
  858. inherited;
  859. end;
  860. procedure TGLCustomGLSLMLBumpShaderMT.SetLightCompensation(
  861. const Value: Single);
  862. begin
  863. FLightCompensation := Value;
  864. FinalizeShader;
  865. end;
  866. procedure TGLCustomGLSLMLBumpShaderMT.SetLightSources(
  867. const Value: TGLLightSourceSet);
  868. begin
  869. Assert(Value <> [], strErrorEx + strShaderNeedsAtLeastOneLightSource);
  870. FLightSources := Value;
  871. FinalizeShader;
  872. end;
  873. { TGLCustomGLSLBumpShaderMT }
  874. procedure TGLCustomGLSLBumpShaderMT.DoApply(
  875. var rci: TGLRenderContextInfo; Sender: TObject);
  876. begin
  877. inherited;
  878. Param['baseMap'].AsTexture2D[0] := FMainTexture;
  879. end;
  880. procedure TGLCustomGLSLBumpShaderMT.DoInitialize(var rci : TGLRenderContextInfo; Sender : TObject);
  881. begin
  882. GetVertexProgramCode(VertexProgram.Code);
  883. GetFragmentProgramCode(FragmentProgram.Code, FSpecularTexture <> nil, FNormalTexture <> nil);
  884. inherited;
  885. end;
  886. { TGLCustomGLSLBumpShader }
  887. procedure TGLCustomGLSLBumpShader.DoApply(var rci: TGLRenderContextInfo;
  888. Sender: TObject);
  889. begin
  890. inherited;
  891. Param['baseMap'].AsVector1i := 0; // Use the current texture.
  892. end;
  893. procedure TGLCustomGLSLBumpShader.DoInitialize(var rci : TGLRenderContextInfo; Sender : TObject);
  894. begin
  895. GetVertexProgramCode(VertexProgram.Code);
  896. GetFragmentProgramCode(FragmentProgram.Code, FSpecularTexture <> nil, FNormalTexture <> nil);
  897. VertexProgram.Enabled := True;
  898. FragmentProgram.Enabled := True;
  899. inherited;
  900. end;
  901. function TGLCustomGLSLBumpShader.GetShaderAlpha: Single;
  902. begin
  903. //ignore
  904. Result := -1;
  905. end;
  906. procedure TGLCustomGLSLBumpShader.GetShaderColorParams(var AAmbientColor,
  907. ADiffuseColor, ASpecularcolor: TVector4f);
  908. begin
  909. //ignore
  910. AAmbientColor := NullHmgVector;
  911. ADiffuseColor := NullHmgVector;
  912. ASpecularcolor := NullHmgVector;
  913. end;
  914. procedure TGLCustomGLSLBumpShader.GetShaderTextures(
  915. var Textures: array of TGLTexture);
  916. begin
  917. Textures[0] := FNormalTexture;
  918. Textures[1] := FSpecularTexture;
  919. end;
  920. procedure TGLCustomGLSLBumpShader.GetShaderMiscParameters(var ACadencer: TGLCadencer;
  921. var AMatLib: TGLMaterialLibrary; var ALightSources: TGLLightSourceSet);
  922. begin
  923. ACadencer := nil;
  924. AMatLib := FMaterialLibrary;
  925. ALightSources := [0];
  926. end;
  927. procedure TGLCustomGLSLBumpShader.SetShaderAlpha(const Value: Single);
  928. begin
  929. //ignore
  930. end;
  931. procedure TGLCustomGLSLBumpShader.SetShaderColorParams(const AAmbientColor,
  932. ADiffuseColor, ASpecularcolor: TVector4f);
  933. begin
  934. //ignore
  935. end;
  936. procedure TGLCustomGLSLBumpShader.SetShaderMiscParameters(
  937. const ACadencer: TGLCadencer; const AMatLib: TGLMaterialLibrary;
  938. const ALightSources: TGLLightSourceSet);
  939. begin
  940. SetMaterialLibrary(AMatLib);
  941. end;
  942. procedure TGLCustomGLSLBumpShader.SetShaderTextures(
  943. const Textures: array of TGLTexture);
  944. begin
  945. SetNormalTexture(Textures[0]);
  946. SetSpecularTexture(Textures[1]);
  947. end;
  948. function TGLCustomGLSLBumpShader.GetShaderDescription: string;
  949. begin
  950. Result := 'ShaderTexture1 is NormalMap, ShaderTexture2 is SpecularMap'
  951. end;
  952. { TGLCustomGLSLMLBumpShader }
  953. constructor TGLCustomGLSLMLBumpShader.Create(AOwner: TComponent);
  954. begin
  955. inherited;
  956. FLightSources := [1];
  957. FLightCompensation := 1;
  958. end;
  959. procedure TGLCustomGLSLMLBumpShader.DoApply(var rci: TGLRenderContextInfo;
  960. Sender: TObject);
  961. begin
  962. inherited;
  963. Param['baseMap'].AsVector1i := 0; // Use the current texture.
  964. end;
  965. procedure TGLCustomGLSLMLBumpShader.DoInitialize(var rci : TGLRenderContextInfo; Sender : TObject);
  966. var
  967. I: Integer;
  968. lLightCount: Integer;
  969. begin
  970. GetMLVertexProgramCode(VertexProgram.Code);
  971. with FragmentProgram.Code do
  972. begin
  973. GetMLFragmentProgramCodeBeg(FragmentProgram.Code, FSpecularTexture <> nil, FNormalTexture <> nil);
  974. lLightCount := 0;
  975. // Repeat for all lights.
  976. for I := 0 to glsShaderMaxLightSources - 1 do
  977. if I + 1 in FLightSources then
  978. begin
  979. GetMLFragmentProgramCodeMid(FragmentProgram.Code, I);
  980. Inc(lLightCount);
  981. end;
  982. GetMLFragmentProgramCodeEnd(FragmentProgram.Code, lLightCount, FLightCompensation);
  983. end;
  984. VertexProgram.Enabled := True;
  985. FragmentProgram.Enabled := True;
  986. inherited;
  987. end;
  988. procedure TGLCustomGLSLMLBumpShader.SetLightCompensation(
  989. const Value: Single);
  990. begin
  991. FLightCompensation := Value;
  992. FinalizeShader;
  993. end;
  994. procedure TGLCustomGLSLMLBumpShader.SetLightSources(
  995. const Value: TGLLightSourceSet);
  996. begin
  997. Assert(Value <> [], strErrorEx + strShaderNeedsAtLeastOneLightSource);
  998. FLightSources := Value;
  999. FinalizeShader;
  1000. end;
  1001. function TGLCustomGLSLMLBumpShader.GetShaderAlpha: Single;
  1002. begin
  1003. //ignore
  1004. Result := -1;
  1005. end;
  1006. procedure TGLCustomGLSLMLBumpShader.GetShaderColorParams(var AAmbientColor,
  1007. ADiffuseColor, ASpecularcolor: TVector4f);
  1008. begin
  1009. //ignore
  1010. AAmbientColor := NullHmgVector;
  1011. ADiffuseColor := NullHmgVector;
  1012. ASpecularcolor := NullHmgVector;
  1013. end;
  1014. function TGLCustomGLSLMLBumpShader.GetShaderDescription: string;
  1015. begin
  1016. Result := 'ShaderTexture1 is NormalMap, ShaderTexture2 is SpecularMap';
  1017. end;
  1018. procedure TGLCustomGLSLMLBumpShader.GetShaderMiscParameters(
  1019. var ACadencer: TGLCadencer; var AMatLib: TGLMaterialLibrary;
  1020. var ALightSources: TGLLightSourceSet);
  1021. begin
  1022. ACadencer := nil;
  1023. AMatLib := FMaterialLibrary;
  1024. ALightSources := FLightSources;
  1025. end;
  1026. procedure TGLCustomGLSLMLBumpShader.GetShaderTextures(
  1027. var Textures: array of TGLTexture);
  1028. begin
  1029. Textures[0] := FNormalTexture;
  1030. Textures[1] := FSpecularTexture;
  1031. end;
  1032. procedure TGLCustomGLSLMLBumpShader.SetShaderAlpha(const Value: Single);
  1033. begin
  1034. //ignore
  1035. end;
  1036. procedure TGLCustomGLSLMLBumpShader.SetShaderColorParams(const AAmbientColor,
  1037. ADiffuseColor, ASpecularcolor: TVector4f);
  1038. begin
  1039. //ignore
  1040. end;
  1041. procedure TGLCustomGLSLMLBumpShader.SetShaderMiscParameters(
  1042. const ACadencer: TGLCadencer; const AMatLib: TGLMaterialLibrary;
  1043. const ALightSources: TGLLightSourceSet);
  1044. begin
  1045. SetMaterialLibrary(AMatLib);
  1046. SetLightSources(ALightSources);
  1047. end;
  1048. procedure TGLCustomGLSLMLBumpShader.SetShaderTextures(
  1049. const Textures: array of TGLTexture);
  1050. begin
  1051. SetNormalTexture(Textures[0]);
  1052. SetSpecularTexture(Textures[1]);
  1053. end;
  1054. // ------------------
  1055. // ------------------ TGLBumpShader ------------------
  1056. // ------------------
  1057. constructor TGLBumpShader.Create(AOwner: TComponent);
  1058. begin
  1059. inherited;
  1060. FLightIDs := TGIntegerList.Create;
  1061. FBumpMethod := bmDot3TexCombiner;
  1062. FBumpSpace := bsObject;
  1063. FBumpOptions := [];
  1064. FSpecularMode := smOff;
  1065. ShaderStyle := ssLowLevel;
  1066. FParallaxOffset := 0.04;
  1067. FVertexProgram := TStringList.Create;
  1068. FFragmentProgram := TStringList.Create;
  1069. end;
  1070. destructor TGLBumpShader.Destroy;
  1071. begin
  1072. DeleteVertexPrograms;
  1073. DeleteFragmentPrograms;
  1074. FLightIDs.Free;
  1075. FVertexProgram.Free;
  1076. FFragmentProgram.Free;
  1077. inherited;
  1078. end;
  1079. procedure TGLBumpShader.Loaded;
  1080. begin
  1081. inherited;
  1082. end;
  1083. function TGLBumpShader.GenerateVertexProgram: string;
  1084. var
  1085. VP: TStringList;
  1086. DoTangent, DoSpecular, DoParallaxOffset: Boolean;
  1087. texcoord: Integer;
  1088. begin
  1089. DoSpecular := (BumpMethod = bmBasicARBFP) and not (SpecularMode = smOff);
  1090. DoTangent := (BumpSpace = bsTangentExternal) or (BumpSpace =
  1091. bsTangentQuaternion);
  1092. DoParallaxOffset := (BumpMethod = bmBasicARBFP) and (boParallaxMapping in
  1093. BumpOptions) and DoTangent;
  1094. VP := TStringList.Create;
  1095. VP.Add('!!ARBvp1.0');
  1096. VP.Add('OPTION ARB_position_invariant;');
  1097. VP.Add('PARAM mv[4] = { state.matrix.modelview };');
  1098. VP.Add('PARAM mvinv[4] = { state.matrix.modelview.inverse };');
  1099. VP.Add('PARAM mvit[4] = { state.matrix.modelview.invtrans };');
  1100. VP.Add('PARAM tex[4] = { state.matrix.texture[0] };');
  1101. if boUseSecondaryTexCoords in BumpOptions then
  1102. VP.Add('PARAM tex2[4] = { state.matrix.texture[1] };');
  1103. VP.Add('PARAM lightPos = program.local[0];');
  1104. VP.Add('PARAM lightAtten = program.local[1];');
  1105. if BumpSpace = bsTangentExternal then
  1106. begin
  1107. VP.Add('ATTRIB tangent = vertex.texcoord[1];');
  1108. VP.Add('ATTRIB binormal = vertex.texcoord[2];');
  1109. VP.Add('ATTRIB normal = vertex.normal;');
  1110. end;
  1111. VP.Add('TEMP temp, temp2, light, eye, atten;');
  1112. if (boLightAttenuation in BumpOptions) then
  1113. begin
  1114. VP.Add(' DP4 temp.x, mv[0], vertex.position;');
  1115. VP.Add(' DP4 temp.y, mv[1], vertex.position;');
  1116. VP.Add(' DP4 temp.z, mv[2], vertex.position;');
  1117. VP.Add(' ADD light, lightPos, -temp;');
  1118. VP.Add(' DP3 atten.y, light, light;');
  1119. VP.Add(' RSQ atten.y, atten.y;');
  1120. if BumpMethod = bmDot3TexCombiner then
  1121. begin
  1122. VP.Add(' RCP atten.y, atten.y;');
  1123. VP.Add(' MUL atten.z, atten.y, atten.y;');
  1124. VP.Add(' MAD atten.x, lightAtten.y, atten.y, lightAtten.x;');
  1125. VP.Add(' MAD atten.x, lightAtten.z, atten.z, atten.x;');
  1126. VP.Add(' RCP atten.x, atten.x;');
  1127. end
  1128. else if BumpMethod = bmBasicARBFP then
  1129. begin
  1130. // Store the distance in atten.x for ARBFP,
  1131. // fragment program will calculate attenutation
  1132. VP.Add(' RCP atten.x, atten.y;');
  1133. end;
  1134. VP.Add(' DP3 temp.x, mvinv[0], light;');
  1135. VP.Add(' DP3 temp.y, mvinv[1], light;');
  1136. VP.Add(' DP3 temp.z, mvinv[2], light;');
  1137. VP.Add(' MOV light, temp;');
  1138. end
  1139. else
  1140. begin
  1141. VP.Add(' DP4 light.x, mvinv[0], lightPos;');
  1142. VP.Add(' DP4 light.y, mvinv[1], lightPos;');
  1143. VP.Add(' DP4 light.z, mvinv[2], lightPos;');
  1144. VP.Add(' ADD light, light, -vertex.position;');
  1145. end;
  1146. if DoSpecular or DoParallaxOffset then
  1147. VP.Add(' ADD eye, mvit[3], -vertex.position;');
  1148. if DoTangent then
  1149. begin
  1150. if BumpSpace = bsTangentExternal then
  1151. begin
  1152. VP.Add(' DP3 temp.x, light, tangent;');
  1153. VP.Add(' DP3 temp.y, light, binormal;');
  1154. VP.Add(' DP3 temp.z, light, normal;');
  1155. VP.Add(' MOV light, temp;');
  1156. if DoSpecular or DoParallaxOffset then
  1157. begin
  1158. VP.Add(' DP3 temp.x, eye, tangent;');
  1159. VP.Add(' DP3 temp.y, eye, binormal;');
  1160. VP.Add(' DP3 temp.z, eye, normal;');
  1161. VP.Add(' MOV eye, temp;');
  1162. end;
  1163. end
  1164. else if BumpSpace = bsTangentQuaternion then
  1165. begin
  1166. VP.Add(' DP3 temp.x, light, light;');
  1167. VP.Add(' RSQ temp.x, temp.x;');
  1168. VP.Add(' MUL light, temp.x, light;');
  1169. VP.Add(' MOV temp2.x, vertex.normal.y;');
  1170. VP.Add(' ADD temp2.y, 0.0, -vertex.normal.x;');
  1171. VP.Add(' MOV temp2.z, 0.0;');
  1172. VP.Add(' DP3 temp.x, temp2, light;');
  1173. VP.Add(' MUL temp.x, temp2.y, light.z;');
  1174. VP.Add(' MAD temp.y, vertex.normal.z, light.x, temp.x;');
  1175. VP.Add(' MUL temp.x, vertex.normal.y, light.z;');
  1176. VP.Add(' MAD temp.z, vertex.normal.z, light.y, -temp.x;');
  1177. VP.Add(' MUL temp.x, vertex.normal.y, light.y;');
  1178. VP.Add(' MAD temp.x, vertex.normal.z, light.z, temp.x;');
  1179. VP.Add(' MAD temp.w, -temp2.y, light.x, temp.x;');
  1180. VP.Add(' MOV light, temp.yzwy;');
  1181. if DoSpecular or DoParallaxOffset then
  1182. begin
  1183. VP.Add(' DP3 temp.x, temp2, eye;');
  1184. VP.Add(' MUL temp.x, temp2.y, eye.z;');
  1185. VP.Add(' MAD temp.y, vertex.normal.z, eye.x, temp.x;');
  1186. VP.Add(' MUL temp.x, vertex.normal.y, eye.z;');
  1187. VP.Add(' MAD temp.z, vertex.normal.z, eye.y, -temp.x;');
  1188. VP.Add(' MUL temp.x, vertex.normal.y, eye.y;');
  1189. VP.Add(' MAD temp.x, vertex.normal.z, eye.z, temp.x;');
  1190. VP.Add(' MAD temp.w, -temp2.y, eye.x, temp.x;');
  1191. VP.Add(' MOV eye, temp.yzwy;');
  1192. end;
  1193. end;
  1194. end;
  1195. if BumpMethod = bmDot3TexCombiner then
  1196. begin
  1197. if BumpSpace <> bsTangentQuaternion then
  1198. begin
  1199. VP.Add(' DP3 temp.x, light, light;');
  1200. VP.Add(' RSQ temp, temp.x;');
  1201. VP.Add(' MUL light, temp.x, light;');
  1202. end;
  1203. if boLightAttenuation in BumpOptions then
  1204. VP.Add(' MUL light, atten.x, light;');
  1205. VP.Add(' MAD result.color, light, 0.5, 0.5;');
  1206. VP.Add(' MOV result.color.w, 1.0;');
  1207. end
  1208. else if BumpMethod = bmBasicARBFP then
  1209. begin
  1210. if boLightAttenuation in BumpOptions then
  1211. VP.Add(' MOV light.w, atten.x;')
  1212. else
  1213. VP.Add(' MOV light.w, 0.0;');
  1214. if DoSpecular or DoParallaxOffset then
  1215. VP.Add(' MOV eye.w, 0.0;');
  1216. end;
  1217. texcoord := 0;
  1218. VP.Add(' DP4 temp.x, vertex.texcoord[0], tex[0];');
  1219. VP.Add(' DP4 temp.y, vertex.texcoord[0], tex[1];');
  1220. VP.Add(' DP4 temp.z, vertex.texcoord[0], tex[2];');
  1221. VP.Add(' DP4 temp.w, vertex.texcoord[0], tex[3];');
  1222. VP.Add(' MOV result.texcoord[' + IntToStr(texcoord) + '], temp;');
  1223. Inc(texcoord);
  1224. if boUseSecondaryTexCoords in BumpOptions then
  1225. begin
  1226. VP.Add(' DP4 temp.x, vertex.texcoord[1], tex2[0];');
  1227. VP.Add(' DP4 temp.y, vertex.texcoord[1], tex2[1];');
  1228. VP.Add(' DP4 temp.z, vertex.texcoord[1], tex2[2];');
  1229. VP.Add(' DP4 temp.w, vertex.texcoord[1], tex2[3];');
  1230. VP.Add(' MOV result.texcoord[' + IntToStr(texcoord) + '], temp;');
  1231. Inc(texcoord);
  1232. end;
  1233. if BumpMethod = bmDot3TexCombiner then
  1234. begin
  1235. if (boDiffuseTexture2 in BumpOptions)
  1236. and not (boUseSecondaryTexCoords in BumpOptions) then
  1237. VP.Add(' MOV result.texcoord[' + IntToStr(texcoord) + '], temp;');
  1238. end
  1239. else
  1240. begin
  1241. VP.Add(' MOV result.texcoord[' + IntToStr(texcoord) + '], light;');
  1242. Inc(texcoord);
  1243. if DoSpecular then
  1244. VP.Add(' MOV result.texcoord[' + IntToStr(texcoord) + '], eye;');
  1245. end;
  1246. VP.Add('END');
  1247. FVertexProgram.Assign(VP);
  1248. Result := VP.Text;
  1249. VP.Free;
  1250. end;
  1251. function TGLBumpShader.GenerateFragmentProgram: string;
  1252. var
  1253. FP: TStringList;
  1254. DoSpecular,
  1255. DoTangent,
  1256. DoParallaxOffset: Boolean;
  1257. texcoord,
  1258. normalTexCoords,
  1259. diffTexCoords,
  1260. specTexCoords,
  1261. lightTexCoords,
  1262. eyeTexCoords: Integer;
  1263. begin
  1264. DoSpecular := not (SpecularMode = smOff);
  1265. DoTangent := (BumpSpace = bsTangentExternal) or (BumpSpace =
  1266. bsTangentQuaternion);
  1267. DoParallaxOffset := (boParallaxMapping in BumpOptions) and DoTangent;
  1268. texcoord := 0;
  1269. normalTexCoords := texcoord;
  1270. if boUseSecondaryTexCoords in BumpOptions then
  1271. Inc(texcoord);
  1272. diffTexCoords := texcoord;
  1273. specTexCoords := texcoord;
  1274. Inc(texcoord);
  1275. lightTexCoords := texcoord;
  1276. Inc(texcoord);
  1277. eyeTexCoords := texcoord;
  1278. FP := TStringList.Create;
  1279. FP.Add('!!ARBfp1.0');
  1280. FP.Add('PARAM lightDiffuse = program.local[0];');
  1281. FP.Add('PARAM lightSpecular = program.local[1];');
  1282. FP.Add('PARAM lightAtten = program.local[2];');
  1283. FP.Add('PARAM materialDiffuse = state.material.diffuse;');
  1284. FP.Add('PARAM materialSpecular = state.material.specular;');
  1285. FP.Add('PARAM shininess = state.material.shininess;');
  1286. FP.Add('TEMP temp, tex, light, eye, normal, col, diff, spec;');
  1287. FP.Add('TEMP textureColor, reflect, atten, offset, texcoord;');
  1288. if DoSpecular or DoParallaxOffset then
  1289. begin
  1290. // Get the eye vector
  1291. FP.Add(' DP3 eye, fragment.texcoord[' + IntToStr(eyeTexCoords) +
  1292. '], fragment.texcoord[' + IntToStr(eyeTexCoords) + '];');
  1293. FP.Add(' RSQ eye, eye.x;');
  1294. FP.Add(' MUL eye, fragment.texcoord[' + IntToStr(eyeTexCoords) +
  1295. '], eye.x;');
  1296. end;
  1297. if DoParallaxOffset then
  1298. begin
  1299. // Get the parallax offset
  1300. FP.Add(' TEX textureColor, fragment.texcoord[' + IntToStr(normalTexCoords)
  1301. + '], texture[0], 2D;');
  1302. FP.Add(Format(' MAD offset.x, textureColor.a, %f, %f;', [FParallaxOffset,
  1303. -0.5 * FParallaxOffset]));
  1304. FP.Add(' MUL offset, eye, offset.x;');
  1305. FP.Add(' ADD texcoord, fragment.texcoord[' + IntToStr(normalTexCoords) +
  1306. '], offset;');
  1307. end
  1308. else
  1309. FP.Add(' MOV texcoord, fragment.texcoord[' + IntToStr(normalTexCoords) +
  1310. '];');
  1311. // Get the normalized normal vector
  1312. FP.Add(' TEX textureColor, texcoord, texture[0], 2D;');
  1313. FP.Add(' ADD normal, textureColor, -0.5;');
  1314. FP.Add(' DP3 temp, normal, normal;');
  1315. FP.Add(' RSQ temp, temp.x;');
  1316. FP.Add(' MUL normal, normal, temp.x;');
  1317. // Get the normalized light vector
  1318. FP.Add(' MOV light, fragment.texcoord[' + IntToStr(lightTexCoords) + '];');
  1319. if boLightAttenuation in BumpOptions then
  1320. FP.Add(' MOV atten.x, light.w;');
  1321. FP.Add(' DP3 light, light, light;');
  1322. FP.Add(' RSQ light, light.x;');
  1323. FP.Add(' MUL light, fragment.texcoord[' + IntToStr(lightTexCoords) +
  1324. '], light.x;');
  1325. // Calculate the diffuse color
  1326. FP.Add(' DP3 diff, normal, light;');
  1327. FP.Add(' MUL diff, diff, lightDiffuse;');
  1328. FP.Add(' MUL diff, diff, materialDiffuse;');
  1329. if boDiffuseTexture2 in BumpOptions then
  1330. begin
  1331. if DoParallaxOffset then
  1332. begin
  1333. FP.Add(' ADD temp, fragment.texcoord[' + IntToStr(diffTexCoords) +
  1334. '], offset;');
  1335. FP.Add(' TEX textureColor, temp, texture[1], 2D;');
  1336. end
  1337. else
  1338. FP.Add(' TEX textureColor, fragment.texcoord[' + IntToStr(diffTexCoords)
  1339. + '], texture[1], 2D;');
  1340. FP.Add(' MUL diff, diff, textureColor;');
  1341. end;
  1342. if DoSpecular then
  1343. begin
  1344. case SpecularMode of
  1345. smBlinn:
  1346. begin
  1347. FP.Add(' ADD eye, eye, light;');
  1348. FP.Add(' DP3 temp, eye, eye;');
  1349. FP.Add(' RSQ temp, temp.x;');
  1350. FP.Add(' MUL eye, eye, temp.x;');
  1351. FP.Add(' DP3_SAT spec, normal, eye;');
  1352. end;
  1353. smPhong:
  1354. begin
  1355. FP.Add(' DP3 reflect, normal, light;');
  1356. FP.Add(' MUL reflect, reflect.x, normal;');
  1357. FP.Add(' MUL reflect, 2.0, reflect;');
  1358. FP.Add(' ADD reflect, reflect, -light;');
  1359. FP.Add(' DP3_SAT spec, reflect, eye;');
  1360. end;
  1361. else
  1362. Assert(False, 'Invalid specular mode!');
  1363. end;
  1364. FP.Add(' POW spec, spec.x, shininess.x;');
  1365. FP.Add(' MUL spec, spec, materialSpecular;');
  1366. FP.Add(' MUL spec, spec, lightSpecular;');
  1367. if boSpecularTexture3 in BumpOptions then
  1368. begin
  1369. if DoParallaxOffset then
  1370. begin
  1371. FP.Add(' ADD temp, fragment.texcoord[' + IntToStr(specTexCoords) +
  1372. '], offset;');
  1373. FP.Add(' TEX textureColor, temp, texture[2], 2D;');
  1374. end
  1375. else
  1376. FP.Add(' TEX textureColor, fragment.texcoord[' +
  1377. IntToStr(specTexCoords) + '], texture[2], 2D;');
  1378. FP.Add(' MUL spec, spec, textureColor;');
  1379. end;
  1380. end;
  1381. // Output
  1382. if DoSpecular then
  1383. FP.Add(' ADD temp, diff, spec;')
  1384. else
  1385. FP.Add(' MOV temp, diff;');
  1386. if boLightAttenuation in BumpOptions then
  1387. begin
  1388. FP.Add(' MUL atten.y, atten.x, atten.x;');
  1389. FP.Add(' MAD atten.x, lightAtten.y, atten.x, lightAtten.x;');
  1390. FP.Add(' MAD atten.x, lightAtten.z, atten.y, atten.x;');
  1391. FP.Add(' RCP atten.x, atten.x;');
  1392. FP.Add(' MUL temp, temp, atten.x;');
  1393. end;
  1394. FP.Add(' MOV_SAT result.color, temp;');
  1395. FP.Add(' MOV result.color.w, 1.0;');
  1396. FP.Add('END');
  1397. FFragmentProgram.Assign(FP);
  1398. Result := FP.Text;
  1399. FP.Free;
  1400. end;
  1401. // DoLightPass
  1402. //
  1403. procedure TGLBumpShader.DoLightPass(var rci: TGLRenderContextInfo;
  1404. lightID: Cardinal);
  1405. var
  1406. dummyHandle, tempHandle: Integer;
  1407. lightPos, lightAtten,
  1408. materialDiffuse, lightDiffuse, lightSpecular: TGLVector;
  1409. begin
  1410. FVertexProgramHandle.Enable;
  1411. FVertexProgramHandle.Bind;
  1412. // Set the light position to program.local[0]
  1413. gl.GetLightfv(GL_LIGHT0 + FLightIDs[0], GL_POSITION, @lightPos.X);
  1414. gl.ProgramLocalParameter4fv(GL_VERTEX_PROGRAM_ARB, 0, @lightPos.X);
  1415. // Set the light attenutation to program.local[1]
  1416. lightAtten.X := rci.GLStates.LightConstantAtten[FLightIDs[0]];
  1417. lightAtten.Y := rci.GLStates.LightLinearAtten[FLightIDs[0]];
  1418. lightAtten.Z := rci.GLStates.LightQuadraticAtten[FLightIDs[0]];
  1419. gl.ProgramLocalParameter4fv(GL_VERTEX_PROGRAM_ARB, 1, @lightAtten.X);
  1420. case FBumpMethod of
  1421. bmDot3TexCombiner:
  1422. begin
  1423. rci.GLStates.ActiveTexture := 0;
  1424. dummyHandle := rci.GLStates.TextureBinding[0, ttTexture2D];
  1425. gl.TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
  1426. gl.TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_DOT3_RGB_ARB);
  1427. gl.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE0_ARB);
  1428. gl.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
  1429. rci.GLStates.ActiveTexture := 1;
  1430. rci.GLStates.ActiveTextureEnabled[ttTexture2D] := True;
  1431. tempHandle := rci.GLStates.TextureBinding[1, ttTexture2D];
  1432. if tempHandle = 0 then
  1433. rci.GLStates.TextureBinding[1, ttTexture2D] := dummyHandle;
  1434. lightDiffuse := rci.GLStates.LightDiffuse[FLightIDs[0]];
  1435. gl.GetMaterialfv(GL_FRONT, GL_DIFFUSE, @materialDiffuse);
  1436. lightDiffuse.X := lightDiffuse.X * materialDiffuse.X;
  1437. lightDiffuse.Y := lightDiffuse.Y * materialDiffuse.Y;
  1438. lightDiffuse.Z := lightDiffuse.Z * materialDiffuse.Z;
  1439. lightDiffuse.W := lightDiffuse.W * materialDiffuse.W;
  1440. gl.TexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, @lightDiffuse);
  1441. gl.TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
  1442. gl.TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
  1443. gl.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
  1444. gl.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT_COLOR_EXT);
  1445. with rci.GLStates do
  1446. begin
  1447. ActiveTexture := 2;
  1448. ActiveTextureEnabled[ttTexture2D] := False;
  1449. ActiveTexture := 0;
  1450. end;
  1451. end;
  1452. bmBasicARBFP:
  1453. begin
  1454. FFragmentProgramHandle.Enable;
  1455. FFragmentProgramHandle.Bind;
  1456. lightDiffuse := rci.GLStates.LightDiffuse[FLightIDs[0]];
  1457. lightSpecular := rci.GLStates.LightSpecular[FLightIDs[0]];
  1458. lightAtten.X := rci.GLStates.LightConstantAtten[FLightIDs[0]];
  1459. gl.ProgramLocalParameter4fv(GL_FRAGMENT_PROGRAM_ARB, 0,
  1460. @lightDiffuse.X);
  1461. gl.ProgramLocalParameter4fv(GL_FRAGMENT_PROGRAM_ARB, 1,
  1462. @lightSpecular.X);
  1463. gl.ProgramLocalParameter4fv(GL_FRAGMENT_PROGRAM_ARB, 2,
  1464. @lightAtten.X);
  1465. end;
  1466. else
  1467. Assert(False, 'Invalid bump method!');
  1468. end;
  1469. end;
  1470. procedure TGLBumpShader.DoApply(var rci: TGLRenderContextInfo; Sender: TObject);
  1471. var
  1472. maxTextures, i: Integer;
  1473. ambient, LMaterialAmbient: TGLColorVector;
  1474. success: Boolean;
  1475. begin
  1476. if (csDesigning in ComponentState) and not DesignTimeEnabled then
  1477. exit;
  1478. if not Enabled then
  1479. exit;
  1480. gl.GetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, @maxTextures);
  1481. success := False;
  1482. try
  1483. if not gl.ARB_multitexture then
  1484. raise Exception.Create('This shader requires GL_ARB_multitexture.');
  1485. if (maxTextures < 3)
  1486. and ((BumpMethod <> bmDot3TexCombiner) or (BumpSpace = bsTangentExternal)) then
  1487. raise
  1488. Exception.Create('The current shader settings require 3 or more texture units.');
  1489. if (maxTextures < 4)
  1490. and (BumpMethod <> bmDot3TexCombiner)
  1491. and (boUseSecondaryTexCoords in BumpOptions)
  1492. and (SpecularMode <> smOff) then
  1493. raise
  1494. Exception.Create('The current shader settings require 4 or more texture units.');
  1495. if not Assigned(FVertexProgramHandle) then
  1496. begin
  1497. FVertexProgramHandle := TGLARBVertexProgramHandle.CreateAndAllocate;
  1498. FVertexProgramHandle.LoadARBProgram(GenerateVertexProgram);
  1499. end;
  1500. if not Assigned(FFragmentProgramHandle) then
  1501. if FBumpMethod = bmBasicARBFP then
  1502. begin
  1503. FFragmentProgramHandle := TGLARBFragmentProgramHandle.CreateAndAllocate;
  1504. FFragmentProgramHandle.LoadARBProgram(GenerateFragmentProgram);
  1505. end;
  1506. success := True;
  1507. finally
  1508. if not success then
  1509. begin
  1510. Enabled := False;
  1511. DesignTimeEnabled := False;
  1512. end;
  1513. end;
  1514. FLightIDs.Clear;
  1515. rci.GLStates.ActiveTexture := 0;
  1516. if rci.GLStates.ActiveTextureEnabled[ttTexture2D] then
  1517. for i := 0 to rci.GLStates.MaxLights - 1 do
  1518. begin
  1519. if rci.GLStates.LightEnabling[i] then
  1520. FLightIDs.Add(i);
  1521. end;
  1522. FLightsEnabled := FLightIDs.Count;
  1523. FAmbientPass := False;
  1524. FDiffusePass := False;
  1525. if FLightIDs.Count > 0 then
  1526. begin
  1527. rci.GLStates.DepthFunc := cfLEqual;
  1528. rci.GLStates.Disable(stBlend);
  1529. DoLightPass(rci, FLightIDs[0]);
  1530. FLightIDs.Delete(0);
  1531. end
  1532. else
  1533. with rci.GLStates do
  1534. begin
  1535. Disable(stLighting);
  1536. ActiveTexture := 0;
  1537. ActiveTextureEnabled[ttTexture2D] := False;
  1538. ActiveTexture := 1;
  1539. ActiveTextureEnabled[ttTexture2D] := False;
  1540. ActiveTexture := 2;
  1541. ActiveTextureEnabled[ttTexture2D] := False;
  1542. ActiveTexture := 0;
  1543. gl.GetFloatv(GL_LIGHT_MODEL_AMBIENT, @ambient);
  1544. gl.GetMaterialfv(GL_FRONT, GL_AMBIENT, @LMaterialAmbient);
  1545. ambient.X := ambient.X * LMaterialAmbient.X;
  1546. ambient.Y := ambient.Y * LMaterialAmbient.Y;
  1547. ambient.Z := ambient.Z * LMaterialAmbient.Z;
  1548. gl.Color3fv(@ambient);
  1549. FAmbientPass := True;
  1550. end;
  1551. end;
  1552. function TGLBumpShader.DoUnApply(var rci: TGLRenderContextInfo): Boolean;
  1553. var
  1554. ambient, LMaterialAmbient: TGLVector;
  1555. begin
  1556. Result := False;
  1557. if (csDesigning in ComponentState) and not DesignTimeEnabled then
  1558. exit;
  1559. if not Enabled then
  1560. exit;
  1561. if FLightIDs.Count > 0 then
  1562. with rci.GLStates do
  1563. begin
  1564. DepthFunc := cfLEqual;
  1565. Enable(stBlend);
  1566. SetBlendFunc(bfOne, bfOne);
  1567. DoLightPass(rci, FLightIDs[0]);
  1568. FLightIDs.Delete(0);
  1569. Result := True;
  1570. Exit;
  1571. end
  1572. else if not FDiffusePass and (FLightsEnabled <> 0)
  1573. and (boDiffuseTexture2 in BumpOptions)
  1574. and (BumpMethod = bmDot3TexCombiner) then
  1575. with rci.GLStates do
  1576. begin
  1577. Enable(stBlend);
  1578. SetBlendFunc(bfDstColor, bfZero);
  1579. ActiveTexture := 0;
  1580. ActiveTextureEnabled[ttTexture2D] := False;
  1581. ActiveTexture := 1;
  1582. ActiveTextureEnabled[ttTexture2D] := True;
  1583. gl.TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  1584. ActiveTexture := 2;
  1585. ActiveTextureEnabled[ttTexture2D] := False;
  1586. ActiveTexture := 0;
  1587. FDiffusePass := True;
  1588. Result := True;
  1589. Exit;
  1590. end
  1591. else if not FAmbientPass then
  1592. with rci.GLStates do
  1593. begin
  1594. FVertexProgramHandle.Disable;
  1595. if BumpMethod = bmBasicARBFP then
  1596. FFragmentProgramHandle.Disable;
  1597. Disable(stLighting);
  1598. ActiveTexture := 0;
  1599. ActiveTextureEnabled[ttTexture2D] := False;
  1600. ActiveTexture := 1;
  1601. ActiveTextureEnabled[ttTexture2D] := False;
  1602. ActiveTexture := 2;
  1603. ActiveTextureEnabled[ttTexture2D] := False;
  1604. ActiveTexture := 0;
  1605. DepthFunc := cfLEqual;
  1606. Enable(stBlend);
  1607. SetBlendFunc(bfOne, bfOne);
  1608. gl.GetFloatv(GL_LIGHT_MODEL_AMBIENT, @ambient);
  1609. gl.GetMaterialfv(GL_FRONT, GL_AMBIENT, @LMaterialAmbient);
  1610. ambient.X := ambient.X * LMaterialAmbient.X;
  1611. ambient.Y := ambient.Y * LMaterialAmbient.Y;
  1612. ambient.Z := ambient.Z * LMaterialAmbient.Z;
  1613. gl.Color3fv(@ambient);
  1614. FAmbientPass := True;
  1615. Result := True;
  1616. Exit;
  1617. end;
  1618. FVertexProgramHandle.Disable;
  1619. if BumpMethod = bmBasicARBFP then
  1620. FFragmentProgramHandle.Disable;
  1621. end;
  1622. procedure TGLBumpShader.DeleteVertexPrograms;
  1623. begin
  1624. FVertexProgramHandle.Free;
  1625. FVertexProgramHandle := nil;
  1626. FVertexProgram.Clear;
  1627. end;
  1628. procedure TGLBumpShader.DeleteFragmentPrograms;
  1629. begin
  1630. FFragmentProgramHandle.Free;
  1631. FFragmentProgramHandle := nil;
  1632. FFragmentProgram.Clear;
  1633. end;
  1634. procedure TGLBumpShader.SetBumpMethod(const Value: TBumpMethod);
  1635. begin
  1636. if Value <> FBumpMethod then
  1637. begin
  1638. FBumpMethod := Value;
  1639. DeleteVertexPrograms;
  1640. DeleteFragmentPrograms;
  1641. NotifyChange(Self);
  1642. end;
  1643. end;
  1644. procedure TGLBumpShader.SetBumpSpace(const Value: TBumpSpace);
  1645. begin
  1646. if Value <> FBumpSpace then
  1647. begin
  1648. FBumpSpace := Value;
  1649. DeleteVertexPrograms;
  1650. DeleteFragmentPrograms;
  1651. NotifyChange(Self);
  1652. end;
  1653. end;
  1654. procedure TGLBumpShader.SetBumpOptions(const Value: TBumpOptions);
  1655. begin
  1656. if Value <> FBumpOptions then
  1657. begin
  1658. FBumpOptions := Value;
  1659. DeleteVertexPrograms;
  1660. DeleteFragmentPrograms;
  1661. NotifyChange(Self);
  1662. end;
  1663. end;
  1664. procedure TGLBumpShader.SetSpecularMode(const Value: TSpecularMode);
  1665. begin
  1666. if Value <> FSpecularMode then
  1667. begin
  1668. FSpecularMode := Value;
  1669. DeleteVertexPrograms;
  1670. DeleteFragmentPrograms;
  1671. NotifyChange(Self);
  1672. end;
  1673. end;
  1674. procedure TGLBumpShader.SetDesignTimeEnabled(const Value: Boolean);
  1675. begin
  1676. if Value <> FDesignTimeEnabled then
  1677. begin
  1678. FDesignTimeEnabled := Value;
  1679. NotifyChange(Self);
  1680. end;
  1681. end;
  1682. procedure TGLBumpShader.SetParallaxOffset(const Value: Single);
  1683. begin
  1684. if Value <> FParallaxOffset then
  1685. begin
  1686. FParallaxOffset := Value;
  1687. DeleteVertexPrograms;
  1688. DeleteFragmentPrograms;
  1689. NotifyChange(Self);
  1690. end;
  1691. end;
  1692. //-----------------------------------------------
  1693. initialization
  1694. //-----------------------------------------------
  1695. RegisterClasses([TGLSLBumpShaderMT, TGLSLBumpShader, TGLSLBumpShaderAM,
  1696. TGLSLMLBumpShader, TGLSLMLBumpShaderMT]);
  1697. end.