2
0

GXSL.BumpShaders.pas 60 KB

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