GLSLx.BumpShaders.pas 60 KB

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