FmShaderMemo.pas 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033
  1. //
  2. // The multimedia graphics platform GLScene https://github.com/glscene
  3. //
  4. unit FmShaderMemo;
  5. (*
  6. Shader code editor.
  7. // TODO: need to decide how to load templates from external file
  8. // and update it without package recompilation
  9. *)
  10. interface
  11. {$I GLScene.inc}
  12. uses
  13. Winapi.Windows,
  14. Winapi.Messages,
  15. System.SysUtils,
  16. System.Variants,
  17. System.Classes,
  18. System.Win.Registry,
  19. VCL.Controls,
  20. VCL.Forms,
  21. VCL.ComCtrls,
  22. VCL.ImgList,
  23. VCL.Dialogs,
  24. VCL.Menus,
  25. VCL.ActnList,
  26. VCL.ToolWin,
  27. VCL.ExtCtrls,
  28. VCL.StdCtrls,
  29. VCL.Graphics,
  30. GLS.Memo;
  31. type
  32. TShaderMemoForm = class(TForm)
  33. ImageList: TImageList;
  34. ToolBar: TToolBar;
  35. TBOpen: TToolButton;
  36. TBSave: TToolButton;
  37. TBStayOnTop: TToolButton;
  38. TBHelp: TToolButton;
  39. ToolButton2: TToolButton;
  40. TBCopy: TToolButton;
  41. TBPaste: TToolButton;
  42. TBCut: TToolButton;
  43. ToolButton10: TToolButton;
  44. TBTemplate: TToolButton;
  45. TBUndo: TToolButton;
  46. TBRedo: TToolButton;
  47. ToolButton4: TToolButton;
  48. GLSLMemo: TGLSSynHiMemo;
  49. OpenDialog: TOpenDialog;
  50. SaveDialog: TSaveDialog;
  51. TemplateMenu: TPopupMenu;
  52. GLSL120: TMenuItem;
  53. GLSL330: TMenuItem;
  54. GLSL400: TMenuItem;
  55. N1: TMenuItem;
  56. N2: TMenuItem;
  57. CompilatorLog: TMemo;
  58. TBIncIndent: TToolButton;
  59. TBDecIndent: TToolButton;
  60. TBComment: TToolButton;
  61. TBUncoment: TToolButton;
  62. ToolButton1: TToolButton;
  63. Panel1: TPanel;
  64. CancelButton: TButton;
  65. OKButton: TButton;
  66. CheckButton: TButton;
  67. procedure FormCreate(Sender: TObject);
  68. procedure FormDestroy(Sender: TObject);
  69. procedure GLSLMemoGutterClick(Sender: TObject; LineNo: Integer);
  70. procedure GLSLMemoGutterDraw(Sender: TObject; ACanvas: TCanvas; LineNo: Integer; rct: TRect);
  71. procedure TBOpenClick(Sender: TObject);
  72. procedure TBSaveClick(Sender: TObject);
  73. procedure TBStayOnTopClick(Sender: TObject);
  74. procedure TBUndoClick(Sender: TObject);
  75. procedure GLSLMemoUndoChange(Sender: TObject; CanUndo, CanRedo: Boolean);
  76. procedure TBRedoClick(Sender: TObject);
  77. procedure TBCopyClick(Sender: TObject);
  78. procedure TBPasteClick(Sender: TObject);
  79. procedure TBCutClick(Sender: TObject);
  80. procedure CheckButtonClick(Sender: TObject);
  81. procedure TBIncIndentClick(Sender: TObject);
  82. procedure TBDecIndentClick(Sender: TObject);
  83. procedure TBCommentClick(Sender: TObject);
  84. procedure TBUncomentClick(Sender: TObject);
  85. procedure FormShow(Sender: TObject);
  86. private
  87. FLightLineStyle: Integer;
  88. FOnCheck: TNotifyEvent;
  89. procedure OnTemplateClick(Sender: TObject);
  90. public
  91. property OnCheck: TNotifyEvent read FOnCheck write FOnCheck;
  92. end;
  93. function GLShaderEditorForm: TShaderMemoForm;
  94. procedure ReleaseGLShaderEditor;
  95. //------------------------------------------------------------------
  96. implementation
  97. //------------------------------------------------------------------
  98. {$R *.dfm}
  99. const
  100. cRegistryKey = 'Software\GLScene\GLSceneShaderEdit';
  101. // ---------------------Syntax keywords
  102. const
  103. GLSLDirectives: array[0..12] of string =
  104. (
  105. '#define',
  106. '#undef',
  107. '#if',
  108. '#ifdef',
  109. '#ifndef',
  110. '#else',
  111. '#elif',
  112. '#endif',
  113. '#error',
  114. '#pragma',
  115. '#extension',
  116. '#version',
  117. '#line'
  118. );
  119. GLSLQualifiers: array[0..33] of string =
  120. (
  121. 'attribute', 'const', 'uniform', 'varying',
  122. 'layout',
  123. 'centroid', 'flat', 'smooth', 'noperspective',
  124. 'patch', 'sample',
  125. 'break', 'continue', 'do', 'for', 'while', 'switch', 'case', 'default',
  126. 'if', 'else',
  127. 'subroutine',
  128. 'in', 'out', 'inout',
  129. 'true', 'false',
  130. 'invariant',
  131. 'discard', 'return',
  132. 'lowp', 'mediump', 'highp', 'precision'
  133. );
  134. GLSLTypes: array[0..85] of string =
  135. (
  136. 'float', 'double', 'int', 'void', 'bool',
  137. 'mat2', 'mat3', 'mat4', 'dmat2', 'dmat3', 'dmat4',
  138. 'mat2x2', 'mat2x3', 'mat2x4', 'dmat2x2', 'dmat2x3', 'dmat2x4',
  139. 'mat3x2', 'mat3x3', 'mat3x4', 'dmat3x2', 'dmat3x3', 'dmat3x4',
  140. 'mat4x2', 'mat4x3', 'mat4x4', 'dmat4x2', 'dmat4x3', 'dmat4x4',
  141. 'vec2', 'vec3', 'vec4', 'ivec2', 'ivec3', 'ivec4', 'bvec2', 'bvec3', 'bvec4', 'dvec2', 'dvec3', 'dvec4',
  142. 'uint', 'uvec2', 'uvec3', 'uvec4',
  143. 'sampler1D', 'sampler2D', 'sampler3D', 'samplerCube',
  144. 'sampler1DShadow', 'sampler2DShadow', 'samplerCubeShadow',
  145. 'sampler1DArray', 'sampler2DArray',
  146. 'sampler1DArrayShadow', 'sampler2DArrayShadow',
  147. 'isampler1D', 'isampler2D', 'isampler3D', 'isamplerCube',
  148. 'isampler1DArray', 'isampler2DArray',
  149. 'usampler1D', 'usampler2D', 'usampler3D', 'usamplerCube',
  150. 'usampler1DArray', 'usampler2DArray',
  151. 'sampler2DRect', 'sampler2DRectShadow', 'isampler2DRect', 'usampler2DRect',
  152. 'samplerBuffer', 'isamplerBuffer', 'usamplerBuffer',
  153. 'sampler2DMS', 'isampler2DMS', 'usampler2DMS',
  154. 'sampler2DMSArray', 'isampler2DMSArray', 'usampler2DMSArray',
  155. 'samplerCubeArray', 'samplerCubeArrayShadow', 'isamplerCubeArray', 'usamplerCubeArray',
  156. 'struct'
  157. );
  158. GLSLBuildIn: array[0..117] of string =
  159. (
  160. 'gl_Color',
  161. 'gl_SecondaryColor',
  162. 'gl_Normal',
  163. 'gl_Vertex',
  164. 'gl_MultiTexCoord0',
  165. 'gl_MultiTexCoord1',
  166. 'gl_MultiTexCoord2',
  167. 'gl_MultiTexCoord3',
  168. 'gl_MultiTexCoord4',
  169. 'gl_MultiTexCoord5',
  170. 'gl_MultiTexCoord6',
  171. 'gl_MultiTexCoord7',
  172. 'gl_FogCoord',
  173. 'gl_FrontColor',
  174. 'gl_BackColor',
  175. 'gl_FrontSecondaryColor',
  176. 'gl_BackSecondaryColor',
  177. 'gl_TexCoord',
  178. 'gl_FogFragCoord',
  179. 'gl_PointCoord',
  180. 'gl_Position',
  181. 'gl_PointSize',
  182. 'gl_ClipVertex',
  183. 'gl_FragCoord',
  184. 'gl_FrontFacing',
  185. 'gl_FragColor',
  186. 'gl_FragData',
  187. 'gl_FragDepth',
  188. 'gl_VertexID',
  189. 'gl_InstanceID',
  190. 'gl_in',
  191. 'gl_out',
  192. 'gl_PrimitiveIDIn',
  193. 'gl_InvocationID',
  194. 'gl_PrimitiveID',
  195. 'gl_Layer',
  196. 'gl_PatchVerticesIn',
  197. 'gl_TessLevelOuter',
  198. 'gl_TessLevelInner',
  199. 'gl_TessCoord',
  200. 'gl_SampleID',
  201. 'gl_SamplePosition',
  202. 'gl_SampleMask',
  203. 'gl_FrontFacing',
  204. 'gl_ClipDistance',
  205. 'gl_MaxVertexAttribs',
  206. 'gl_MaxVertexUniformComponents',
  207. 'gl_MaxVaryingFloats',
  208. 'gl_MaxVaryingComponents',
  209. 'gl_MaxVertexOutputComponents',
  210. 'gl_MaxGeometryInputComponents',
  211. 'gl_MaxGeometryOutputComponents',
  212. 'gl_MaxFragmentInputComponents',
  213. 'gl_MaxVertexTextureImageUnits',
  214. 'gl_MaxCombinedTextureImageUnits',
  215. 'gl_MaxTextureImageUnits',
  216. 'gl_MaxFragmentUniformComponents',
  217. 'gl_MaxDrawBuffers',
  218. 'gl_MaxClipDistances',
  219. 'gl_MaxGeometryTextureImageUnits',
  220. 'gl_MaxGeometryOutputVertices',
  221. 'gl_MaxGeometryTotalOutputComponents',
  222. 'gl_MaxGeometryUniformComponents',
  223. 'gl_MaxGeometryVaryingComponents',
  224. 'gl_MaxTessControlInputComponents',
  225. 'gl_MaxTessControlOutputComponents',
  226. 'gl_MaxTessControlTextureImageUnits',
  227. 'gl_MaxTessControlUniformComponents',
  228. 'gl_MaxTessControlTotalOutputComponents',
  229. 'gl_MaxTessEvaluationInputComponents',
  230. 'gl_MaxTessEvaluationOutputComponents',
  231. 'gl_MaxTessEvaluationTextureImageUnits',
  232. 'gl_MaxTessEvaluationUniformComponents',
  233. 'gl_MaxTessPatchComponents',
  234. 'gl_MaxPatchVertices',
  235. 'gl_MaxTessGenLevel',
  236. 'gl_MaxTextureUnits',
  237. 'gl_MaxTextureCoords',
  238. 'gl_MaxClipPlanes',
  239. 'gl_DepthRange',
  240. 'gl_ModelViewMatrix',
  241. 'gl_ProjectionMatrix',
  242. 'gl_ModelViewProjectionMatrix',
  243. 'gl_TextureMatrix',
  244. 'gl_NormalMatrix',
  245. 'gl_ModelViewMatrixInverse',
  246. 'gl_ProjectionMatrixInverse',
  247. 'gl_ModelViewProjectionMatrixInverse',
  248. 'gl_TextureMatrixInverse',
  249. 'gl_ModelViewMatrixTranspose',
  250. 'gl_ProjectionMatrixTranspose',
  251. 'gl_ModelViewProjectionMatrixTranspose',
  252. 'gl_TextureMatrixTranspose',
  253. 'gl_ModelViewMatrixInverseTranspose',
  254. 'gl_ProjectionMatrixInverseTranspose',
  255. 'gl_ModelViewProjectionMatrixInverseTranspose',
  256. 'gl_TextureMatrixInverseTranspose',
  257. 'gl_NormalScale',
  258. 'gl_ClipPlane',
  259. 'gl_Point',
  260. 'gl_FrontMaterial',
  261. 'gl_BackMaterial',
  262. 'gl_LightSource',
  263. 'gl_LightModel',
  264. 'gl_FrontLightModelProduct',
  265. 'gl_BackLightModelProduct',
  266. 'gl_FrontLightProduct',
  267. 'gl_BackLightProduct',
  268. 'gl_TextureEnvColor',
  269. 'gl_EyePlaneS',
  270. 'gl_EyePlaneT',
  271. 'gl_EyePlaneR',
  272. 'gl_EyePlaneQ',
  273. 'gl_ObjectPlaneS',
  274. 'gl_ObjectPlaneT',
  275. 'gl_ObjectPlaneR',
  276. 'gl_ObjectPlaneQ',
  277. 'gl_Fog'
  278. );
  279. GLSLFunctions: array[0..139] of string =
  280. (
  281. // Angle and Trigonometry Functions
  282. 'radians',
  283. 'degrees',
  284. 'sin',
  285. 'cos',
  286. 'tan',
  287. 'asin',
  288. 'acos',
  289. 'atan',
  290. 'sinh',
  291. 'cosh',
  292. 'tanh',
  293. 'asinh',
  294. 'acosh',
  295. 'atanh',
  296. // Exponetial
  297. 'pow',
  298. 'exp',
  299. 'log',
  300. 'exp2',
  301. 'log2',
  302. 'sqrt',
  303. 'inversesqrt',
  304. // Common
  305. 'abs',
  306. 'sign',
  307. 'floor',
  308. 'trunc',
  309. 'round',
  310. 'roundEven',
  311. 'ceil',
  312. 'fract',
  313. 'mod',
  314. 'min',
  315. 'max',
  316. 'clamp',
  317. 'mix',
  318. 'step',
  319. 'smoothstep',
  320. 'isnan',
  321. 'isinf',
  322. 'floatBitsToInt',
  323. 'floatBitsToUint',
  324. 'intBitsToFloat',
  325. 'uintBitsToFloat',
  326. 'fma',
  327. 'frexp',
  328. 'ldexp',
  329. // Floating-Point Pack and Unpack Functions
  330. 'packUnorm2x16',
  331. 'packUnorm4x8',
  332. 'packSnorm4x8',
  333. 'unpackUnorm2x16',
  334. 'unpackUnorm4x8',
  335. 'unpackSnorm4x8',
  336. 'packDouble2x32',
  337. 'unpackDouble2x32',
  338. // Geometric
  339. 'length',
  340. 'distance',
  341. 'dot',
  342. 'cross',
  343. 'normalize',
  344. 'ftransform',
  345. 'faceforward',
  346. 'reflect',
  347. 'maxtrixCompMult',
  348. 'outerProduct',
  349. 'transpose',
  350. 'determinant',
  351. 'inverse',
  352. // Vector
  353. 'lessThan',
  354. 'lessThanEqual',
  355. 'greaterThan',
  356. 'greaterThanEqual',
  357. 'equal',
  358. 'notEqual',
  359. 'any',
  360. 'all',
  361. 'not',
  362. // Integer Functions
  363. 'uaddCarry',
  364. 'usubBorrow',
  365. 'umulExtended',
  366. 'bitfieldExtract',
  367. 'bitfieldInsert',
  368. 'bitfieldReverse',
  369. 'bitCount',
  370. 'findLSB',
  371. 'findMSB',
  372. // Texture
  373. 'texture1D',
  374. 'texture1DProj',
  375. 'texture1DLod',
  376. 'texture1DProjLod',
  377. 'texture2D',
  378. 'texture2DProj',
  379. 'texture2DLod',
  380. 'texture2DProjLod',
  381. 'texture3D',
  382. 'texture3DProj',
  383. 'texture3DLod',
  384. 'texture3DProjLod',
  385. 'textureCube',
  386. 'textureCubeLod',
  387. 'shadow1D',
  388. 'shadow1DProj',
  389. 'shadow1DLod',
  390. 'shadow1DProjLod',
  391. 'shadow2D',
  392. 'shadow2DProj',
  393. 'shadow2DLod',
  394. 'shadow2DProjLod',
  395. 'textureSize',
  396. 'textureQueryLod',
  397. 'texture',
  398. 'textureProj',
  399. 'textureLod',
  400. 'textureOffset',
  401. 'texelFetch',
  402. 'texelFetchOffset',
  403. 'textureProjOffset',
  404. 'textureLodOffset',
  405. 'textureProjLod',
  406. 'textureProjLodOffset',
  407. 'textureGrad',
  408. 'textureGradOffset',
  409. 'textureProjGrad',
  410. 'textureProjGradOffset',
  411. 'textureGather',
  412. 'textureGatherOffset',
  413. 'textureGatherOffsets',
  414. // Fragment
  415. 'dFdx',
  416. 'dFdy',
  417. 'fwidth',
  418. // Interpolation Functions
  419. 'interpolateAtCentroid',
  420. 'interpolateAtSample',
  421. 'interpolateAtOffset',
  422. // Noise
  423. 'noise1',
  424. 'noise2',
  425. 'noise3',
  426. 'noise4',
  427. // Geometry Shader Functions
  428. 'EmitStreamVertex',
  429. 'EndStreamPrimitive',
  430. 'EmitVertex',
  431. 'EndPrimitive',
  432. // Shader Invocation Control Functions
  433. 'barrier'
  434. );
  435. // ---------------------Shader template
  436. const
  437. cTemplates: array[0..6] of string =
  438. (
  439. '#version 120'#10#13+
  440. #10#13+
  441. 'attribute vec3 Position;'#10#13+
  442. 'attribute vec3 Normal;'#10#13+
  443. 'varying vec3 v2f_Normal;'#10#13+
  444. 'varying vec3 v2f_LightDir;'#10#13+
  445. 'varying vec3 v2f_ViewDir;'#10#13+
  446. #10#13+
  447. 'uniform mat4 ModelMatrix;'#10#13+
  448. 'uniform mat4 ViewProjectionMatrix;'#10#13+
  449. 'uniform mat3 NormalMatrix;'#10#13+
  450. 'uniform vec4 LightPosition;'#10#13+
  451. 'uniform vec4 CameraPosition;'#10#13+
  452. #10#13+
  453. 'void main()'#10#13+
  454. '{'#10#13+
  455. ' vec4 WorldPos = ModelMatrix * vec4(Position,1.0);'#10#13+
  456. ' gl_Position = ViewProjectionMatrix * WorldPos;'#10#13+
  457. ' v2f_Normal = NormalMatrix * Normal;'#10#13+
  458. ' v2f_LightDir = LightPosition.xyz - WorldPos.xyz;'#10#13+
  459. ' v2f_ViewDir = CameraPosition.xyz - WorldPos.xyz;'#10#13+
  460. '}'#10#13,
  461. //-----------------------------------------------------------------------
  462. '#version 120'#10#13+
  463. #10#13+
  464. 'attribute vec3 Position;'#10#13+
  465. 'attribute vec3 Normal;'#10#13+
  466. 'attribute vec3 Tangent;'#10#13+
  467. 'attribute vec3 Binormal;'#10#13+
  468. 'attribute vec2 TexCoord0;'#10#13+
  469. #10#13+
  470. 'varying vec2 v2f_TexCoord;'#10#13+
  471. 'varying vec3 v2f_Normal;'#10#13+
  472. 'varying vec3 v2f_Tangent;'#10#13+
  473. 'varying vec3 v2f_Binormal;'#10#13+
  474. 'varying vec3 v2f_LightDir;'#10#13+
  475. 'varying vec3 v2f_ViewDir;'#10#13+
  476. #10#13+
  477. 'uniform mat4 ModelMatrix;'#10#13+
  478. 'uniform mat4 ViewProjectionMatrix;'#10#13+
  479. 'uniform vec4 LightPosition;'#10#13+
  480. 'uniform vec4 CameraPosition;'#10#13+
  481. 'uniform vec2 BaseTextureRepeat;'#10#13+
  482. #10#13+
  483. 'void main()'#10#13+
  484. '{'#10#13+
  485. ' vec3 WorldPos = (ModelMatrix * vec4(Position,1.0)).xyz;'#10#13+
  486. ' gl_Position = ViewProjectionMatrix * vec4(WorldPos, 1.0);'#10#13+
  487. ' v2f_TexCoord = TexCoord0.xy*BaseTextureRepeat;'#10#13+
  488. ' v2f_Normal = Normal;'#10#13+
  489. ' v2f_Tangent = Tangent;'#10#13+
  490. ' v2f_Binormal = Binormal;'#10#13+
  491. ' v2f_LightDir = LightPosition.xyz - WorldPos.xyz;'#10#13+
  492. ' v2f_ViewDir = CameraPosition.xyz - WorldPos.xyz;'#10#13+
  493. '}'#10#13,
  494. //-----------------------------------------------------------------------
  495. '#version 120'#10#13+
  496. #10#13+
  497. 'varying vec3 v2f_Normal;'#10#13+
  498. 'varying vec3 v2f_LightDir;'#10#13+
  499. 'varying vec3 v2f_ViewDir;'#10#13+
  500. #10#13+
  501. 'uniform vec4 MaterialAmbientColor;'#10#13+
  502. 'uniform vec4 MaterialDiffuseColor;'#10#13+
  503. 'uniform vec4 MaterialSpecularColor;'#10#13+
  504. 'uniform float MaterialShiness;'#10#13+
  505. #10#13+
  506. 'void main()'#10#13+
  507. '{'#10#13+
  508. ' vec3 N = normalize(v2f_Normal);'#10#13+
  509. #10#13+
  510. ' vec3 L = normalize(v2f_LightDir);'#10#13+
  511. ' float DiffuseIntensity = max( dot( N, L ), 0.0);'#10#13+
  512. ' vec4 cDiffuse = DiffuseIntensity * MaterialDiffuseColor;'#10#13+
  513. #10#13+
  514. ' vec4 cSpecular = vec4(0.0);'#10#13+
  515. ' if (DiffuseIntensity > 0.0)'#10#13+
  516. ' {'#10#13+
  517. ' vec3 V = normalize(v2f_ViewDir);'#10#13+
  518. ' vec3 R = reflect(-V, N);'#10#13+
  519. ' float RdotL = max( dot( L, R ), 0.0);'#10#13+
  520. ' if (RdotL > 0.0)'#10#13+
  521. ' cSpecular = pow( RdotL, MaterialShiness) * MaterialSpecularColor;'#10#13+
  522. ' }'#10#13+
  523. #10#13+
  524. ' gl_FragColor = MaterialAmbientColor + cDiffuse + cSpecular;'#10#13+
  525. '}'#10#13,
  526. //-----------------------------------------------------------------------
  527. '#version 120'#10#13+
  528. #10#13+
  529. 'varying vec3 v2f_Normal;'#10#13+
  530. 'varying vec3 v2f_Tangent;'#10#13+
  531. 'varying vec3 v2f_Binormal;'#10#13+
  532. 'varying vec3 v2f_LightDir;'#10#13+
  533. 'varying vec3 v2f_ViewDir;'#10#13+
  534. 'varying vec2 v2f_TexCoord;'#10#13+
  535. #10#13+
  536. 'uniform mat3 NormalMatrix;'#10#13+
  537. 'uniform sampler2D DiffuseMap;'#10#13+
  538. 'uniform sampler2D NormalMap;'#10#13+
  539. #10#13+
  540. 'uniform vec4 MaterialAmbientColor;'#10#13+
  541. 'uniform vec4 MaterialDiffuseColor;'#10#13+
  542. 'uniform vec4 MaterialSpecularColor;'#10#13+
  543. 'uniform float MaterialShiness;'#10#13+
  544. #10#13+
  545. 'void main()'#10#13+
  546. '{'#10#13+
  547. ' vec3 normal = normalize(v2f_Normal);'#10#13+
  548. ' vec3 tangent = normalize(v2f_Tangent);'#10#13+
  549. ' vec3 binormal = normalize(v2f_Binormal);'#10#13+
  550. ' mat3 basis = mat3(tangent, binormal, normal);'#10#13+
  551. ' vec3 N = texture2D(NormalMap, v2f_TexCoord).xyz;'#10#13+
  552. ' N = N * vec3(2.0) - vec3(1.0);'#10#13+
  553. ' N = basis*N;'#10#13+
  554. ' N = NormalMatrix*N;'#10#13+
  555. ' N = normalize(N);'#10#13+
  556. #10#13+
  557. ' vec3 L = normalize(v2f_LightDir);'#10#13+
  558. ' float DiffuseIntensity = max( dot( N, L ), 0.0);'#10#13+
  559. ' vec4 cDiffuse = DiffuseIntensity * MaterialDiffuseColor;'#10#13+
  560. #10#13+
  561. ' vec4 cSpecular = vec4(0.0);'#10#13+
  562. ' if (DiffuseIntensity > 0.0)'#10#13+
  563. ' {'#10#13+
  564. ' vec3 V = normalize(v2f_ViewDir);'#10#13+
  565. ' vec3 R = reflect(-V, N);'#10#13+
  566. ' float RdotL = max( dot( L, R ), 0.0);'#10#13+
  567. ' if (RdotL > 0.0)'#10#13+
  568. ' cSpecular = pow( RdotL, MaterialShiness) * MaterialSpecularColor;'#10#13+
  569. ' }'#10#13+
  570. #10#13+
  571. ' vec4 cBaseColor = texture2D( DiffuseMap, v2f_TexCoord);'#10#13+
  572. ' gl_FragColor = (MaterialAmbientColor + cDiffuse ) * cBaseColor + cSpecular;'#10#13+
  573. '}'#10#13,
  574. //-----------------------------------------------------------------------
  575. '#version 330'#10#13+
  576. 'layout(triangles_adjacency) in;'#10#13+
  577. 'layout(line_strip, max_vertices = 6) out;'#10#13+
  578. 'in vec4 v2g_WorldPos[]; // Vertex position in view space'#10#13+
  579. 'uniform vec4 CameraPosition;'#10#13+
  580. #10#13+
  581. '// calculating facing of a triangle relative to eye'#10#13+
  582. 'float facing(vec4 v0, vec4 v1, vec4 v2, vec4 eye_pos)'#10#13+
  583. '{'#10#13+
  584. ' vec3 e0 = v1.xyz - v0.xyz;'#10#13+
  585. ' vec3 e1 = v2.xyz - v0.xyz;'#10#13+
  586. ' vec4 p;'#10#13+
  587. ' p.xyz = cross(e1, e0);'#10#13+
  588. ' p.w = -dot(v0.xyz, p.xyz);'#10#13+
  589. ' return -dot(p, eye_pos);'#10#13+
  590. '}'#10#13+
  591. #10#13+
  592. '// output lines on silhouette edges by comparing facing of adjacent triangles'#10#13+
  593. 'void main()'#10#13+
  594. '{'#10#13+
  595. ' float f = facing(v2g_WorldPos[0], v2g_WorldPos[2], v2g_WorldPos[4], CameraPosition);'#10#13+
  596. ' // only look at front facing triangles'#10#13+
  597. ' if (f > 0.0)'#10#13+
  598. ' {'#10#13+
  599. ' float f;'#10#13+
  600. ' // test edge 0'#10#13+
  601. ' f = facing(v2g_WorldPos[0], v2g_WorldPos[1], v2g_WorldPos[2], CameraPosition);'#10#13+
  602. ' if (f <= 0)'#10#13+
  603. ' {'#10#13+
  604. ' gl_Position = gl_in[0].gl_Position;'#10#13+
  605. ' EmitVertex();'#10#13+
  606. ' gl_Position = gl_in[2].gl_Position;'#10#13+
  607. ' EmitVertex();'#10#13+
  608. ' EndPrimitive();'#10#13+
  609. ' }'#10#13+
  610. #10#13+
  611. ' // test edge 1'#10#13+
  612. ' f = facing(v2g_WorldPos[2], v2g_WorldPos[3], v2g_WorldPos[4], CameraPosition);'#10#13+
  613. ' if (f <= 0.0)'#10#13+
  614. ' {'#10#13+
  615. ' gl_Position = gl_in[2].gl_Position;'#10#13+
  616. ' EmitVertex();'#10#13+
  617. ' gl_Position = gl_in[4].gl_Position;'#10#13+
  618. ' EmitVertex();'#10#13+
  619. ' EndPrimitive();'#10#13+
  620. ' }'#10#13+
  621. #10#13+
  622. ' // test edge 2'#10#13+
  623. ' f = facing(v2g_WorldPos[4], v2g_WorldPos[5], v2g_WorldPos[0], CameraPosition);'#10#13+
  624. ' if (f <= 0.0)'#10#13+
  625. ' {'#10#13+
  626. ' gl_Position = gl_in[4].gl_Position;'#10#13+
  627. ' EmitVertex();'#10#13+
  628. ' gl_Position = gl_in[0].gl_Position;'#10#13+
  629. ' EmitVertex();'#10#13+
  630. ' EndPrimitive();'#10#13+
  631. ' }'#10#13+
  632. ' }'#10#13+
  633. '}'#10#13,
  634. //-----------------------------------------------------------------------
  635. 'attribute vec3 Position;'#10#13+
  636. 'attribute vec4 Color;'#10#13+
  637. 'attribute vec3 Normal;'#10#13+
  638. 'attribute vec3 Tangent;'#10#13+
  639. 'attribute vec3 Binormal;'#10#13+
  640. 'attribute vec2 TexCoord0;'#10#13+
  641. 'attribute vec2 TexCoord1;'#10#13+
  642. 'attribute vec2 TexCoord2;'#10#13+
  643. 'attribute vec2 TexCoord3;'#10#13+
  644. 'attribute vec2 TexCoord4;'#10#13+
  645. 'attribute vec2 TexCoord5;'#10#13+
  646. 'attribute vec2 TexCoord6;'#10#13+
  647. 'attribute vec2 TexCoord7;'#10#13+
  648. 'attribute vec4 Custom0;'#10#13+
  649. 'attribute vec2 Custom1;'#10#13+
  650. 'attribute vec2 Custom2;'#10#13,
  651. //-----------------------------------------------------------------------
  652. 'in vec3 Position;'#10#13+
  653. 'in vec4 Color;'#10#13+
  654. 'in vec3 Normal;'#10#13+
  655. 'in vec3 Tangent;'#10#13+
  656. 'in vec3 Binormal;'#10#13+
  657. 'in vec2 TexCoord0;'#10#13+
  658. 'in vec2 TexCoord1;'#10#13+
  659. 'in vec2 TexCoord2;'#10#13+
  660. 'in vec2 TexCoord3;'#10#13+
  661. 'in vec2 TexCoord4;'#10#13+
  662. 'in vec2 TexCoord5;'#10#13+
  663. 'in vec2 TexCoord6;'#10#13+
  664. 'in vec2 TexCoord7;'#10#13+
  665. 'in vec4 Custom0;'#10#13+
  666. 'in vec2 Custom1;'#10#13+
  667. 'in vec2 Custom2;'#10#13
  668. );
  669. type
  670. TFriendlyMemo = class(TGLSSynHiMemo);
  671. var
  672. vGLShaderEditor: TShaderMemoForm;
  673. function GLShaderEditorForm: TShaderMemoForm;
  674. begin
  675. if not Assigned(vGLShaderEditor) then
  676. vGLShaderEditor := TShaderMemoForm.Create(nil);
  677. Result := vGLShaderEditor;
  678. end;
  679. procedure ReleaseGLShaderEditor;
  680. begin
  681. if Assigned(vGLShaderEditor) then
  682. begin
  683. vGLShaderEditor.Free;
  684. vGLShaderEditor := nil;
  685. end;
  686. end;
  687. function ReadRegistryInteger(reg: TRegistry; const name: string;
  688. defaultValue: Integer): Integer;
  689. begin
  690. if reg.ValueExists(name) then
  691. Result := reg.ReadInteger(name)
  692. else
  693. Result := defaultValue;
  694. end;
  695. procedure TShaderMemoForm.FormCreate(Sender: TObject);
  696. var
  697. reg: TRegistry;
  698. No: Integer;
  699. item: TMenuItem;
  700. begin
  701. reg := TRegistry.Create;
  702. try
  703. if reg.OpenKey(cRegistryKey, True) then
  704. begin
  705. Left := ReadRegistryInteger(reg, 'Left', Left);
  706. Top := ReadRegistryInteger(reg, 'Top', Top);
  707. Width := ReadRegistryInteger(reg, 'Width', 500);
  708. Height := ReadRegistryInteger(reg, 'Height', 640);
  709. end;
  710. finally
  711. reg.Free;
  712. end;
  713. No := GLSLMemo.Styles.Add(clRed, clWhite, []);
  714. GLSLMemo.AddWord(No, GLSLDirectives);
  715. No := GLSLMemo.Styles.Add(clPurple, clWhite, [fsBold]);
  716. GLSLMemo.AddWord(No, GLSLQualifiers);
  717. No := GLSLMemo.Styles.Add(clBlue, clWhite, [fsBold]);
  718. GLSLMemo.AddWord(No, GLSLTypes);
  719. No := GLSLMemo.Styles.Add(clGray, clWhite, [fsBold]);
  720. GLSLMemo.AddWord(No, GLSLBuildIn);
  721. No := GLSLMemo.Styles.Add(clGreen, clWhite, [fsItalic]);
  722. GLSLMemo.AddWord(No, GLSLFunctions);
  723. No := GLSLMemo.Styles.Add(clYellow, clSilver, [fsItalic]);
  724. GLSLMemo.AddWord(No, GLSLFunctions);
  725. FLightLineStyle := GLSLMemo.Styles.Add(clBlack, clLtGray, []);
  726. GLSLMemo.MultiCommentLeft := '/*';
  727. GLSLMemo.MultiCommentRight := '*/';
  728. GLSLMemo.LineComment := '//';
  729. GLSLMemo.CaseSensitive := True;
  730. GLSLMemo.DelErase := True;
  731. item := NewItem('Attribute block', 0, False, True, OnTemplateClick, 0, '');
  732. item.Tag := 5;
  733. GLSL120.Add(item);
  734. item := NewItem('Basic vertex program', 0, False, True, OnTemplateClick, 0, '');
  735. item.Tag := 0;
  736. GLSL120.Add(item);
  737. item := NewItem('Basic vertex program with TBN pass', 0, False, True, OnTemplateClick, 0, '');
  738. item.Tag := 1;
  739. GLSL120.Add(item);
  740. item := NewItem('Basic fragment program, Phong lighting', 0, False, True, OnTemplateClick, 0, '');
  741. item.Tag := 2;
  742. GLSL120.Add(item);
  743. item := NewItem('Fragment program, normal mapping', 0, False, True, OnTemplateClick, 0, '');
  744. item.Tag := 3;
  745. GLSL120.Add(item);
  746. item := NewItem('Attribute block', 0, False, True, OnTemplateClick, 0, '');
  747. item.Tag := 6;
  748. GLSL330.Add(item);
  749. item := NewItem('Geometry program, edge detection', 0, False, True, OnTemplateClick, 0, '');
  750. item.Tag := 4;
  751. GLSL330.Add(item);
  752. end;
  753. procedure TShaderMemoForm.FormDestroy(Sender: TObject);
  754. var
  755. reg: TRegistry;
  756. begin
  757. reg := TRegistry.Create;
  758. try
  759. if reg.OpenKey(cRegistryKey, True) then
  760. begin
  761. reg.WriteInteger('Left', Left);
  762. reg.WriteInteger('Top', Top);
  763. reg.WriteInteger('Width', Width);
  764. reg.WriteInteger('Height', Height);
  765. end;
  766. finally
  767. reg.Free;
  768. end;
  769. end;
  770. procedure TShaderMemoForm.FormShow(Sender: TObject);
  771. begin
  772. if GLSLMemo.Lines.Count = 0 then
  773. GLSLMemo.Lines.Add('');
  774. end;
  775. procedure TShaderMemoForm.GLSLMemoGutterClick(Sender: TObject; LineNo: Integer);
  776. begin
  777. with GLSLMemo do
  778. begin
  779. LineStyle[LineNo] := FLightLineStyle - LineStyle[LineNo];
  780. end;
  781. end;
  782. procedure TShaderMemoForm.GLSLMemoGutterDraw(Sender: TObject; ACanvas: TCanvas;
  783. LineNo: Integer; rct: TRect);
  784. var
  785. txt: string;
  786. begin
  787. if GLSLMemo.LineStyle[LineNo] = FLightLineStyle then
  788. with rct, ACanvas do
  789. begin
  790. Pen.Color := GLSLMemo.GutterColor;
  791. Brush.Color := clWhite;
  792. Font.Style := Font.Style + [fsBold];
  793. txt := IntToStr(LineNo+1);
  794. TextRect(rct, txt, [tfCenter]);
  795. end;
  796. end;
  797. procedure TShaderMemoForm.GLSLMemoUndoChange(Sender: TObject; CanUndo, CanRedo: Boolean);
  798. begin
  799. TBUndo.Enabled := CanUndo;
  800. TBRedo.Enabled := CanRedo;
  801. end;
  802. procedure TShaderMemoForm.OnTemplateClick(Sender: TObject);
  803. begin
  804. GLSLMemo.InsertTemplate(cTemplates[TMenuItem(Sender).Tag]);
  805. end;
  806. procedure TShaderMemoForm.TBCommentClick(Sender: TObject);
  807. var
  808. I: Integer;
  809. S, E: Integer;
  810. begin
  811. with TFriendlyMemo(GLSLMemo) do
  812. begin
  813. if SelLength > 0 then
  814. begin
  815. S := SelStart.Y;
  816. E := SelEnd.Y;
  817. for I := S to E do
  818. begin
  819. SetCursor(0, I);
  820. InsertChar('/');
  821. InsertChar('/');
  822. end;
  823. SelectLines(S, E);
  824. end;
  825. end;
  826. end;
  827. procedure TShaderMemoForm.TBUncomentClick(Sender: TObject);
  828. var
  829. I: Integer;
  830. S, E: Integer;
  831. C: string;
  832. begin
  833. with TFriendlyMemo(GLSLMemo) do
  834. begin
  835. if SelLength > 0 then
  836. begin
  837. S := SelStart.Y;
  838. E := SelEnd.Y;
  839. for I := S to E do
  840. begin
  841. C := Lines[I];
  842. if (C[1] = '/') and (C[2] = '/') then
  843. begin
  844. Delete(C, 1, 2);
  845. Lines[I] := C;
  846. LineStyle[I] := 0;
  847. end;
  848. end;
  849. SelectLines(S, E);
  850. end;
  851. end;
  852. end;
  853. procedure TShaderMemoForm.TBCopyClick(Sender: TObject);
  854. begin
  855. GLSLMemo.CopyToClipBoard;
  856. end;
  857. procedure TShaderMemoForm.TBCutClick(Sender: TObject);
  858. begin
  859. GLSLMemo.CutToClipBoard;
  860. end;
  861. procedure TShaderMemoForm.TBIncIndentClick(Sender: TObject);
  862. var
  863. I: Integer;
  864. S, E: Integer;
  865. begin
  866. with TFriendlyMemo(GLSLMemo) do
  867. begin
  868. if SelLength > 0 then
  869. begin
  870. S := SelStart.Y;
  871. E := SelEnd.Y;
  872. for I := S to E do
  873. begin
  874. SetCursor(0, I);
  875. InsertChar(#9);
  876. end;
  877. SelectLines(S, E);
  878. end;
  879. end;
  880. end;
  881. procedure TShaderMemoForm.TBDecIndentClick(Sender: TObject);
  882. var
  883. I, J: Integer;
  884. S, E: Integer;
  885. C: string;
  886. begin
  887. with TFriendlyMemo(GLSLMemo) do
  888. begin
  889. if SelLength > 0 then
  890. begin
  891. S := SelStart.Y;
  892. E := SelEnd.Y;
  893. for I := S to E do
  894. begin
  895. C := Lines[I];
  896. for J := 1 to TabSize do
  897. if C[1] = ' ' then
  898. Delete(C, 1, 1);
  899. Lines[I] := C;
  900. end;
  901. SelectLines(S, E);
  902. end;
  903. end;
  904. end;
  905. procedure TShaderMemoForm.TBOpenClick(Sender: TObject);
  906. begin
  907. if OpenDialog.Execute then
  908. GLSLMemo.Lines.LoadFromFile(OpenDialog.FileName);
  909. SetFocus;
  910. end;
  911. procedure TShaderMemoForm.TBPasteClick(Sender: TObject);
  912. begin
  913. GLSLMemo.PasteFromClipBoard;
  914. end;
  915. procedure TShaderMemoForm.TBRedoClick(Sender: TObject);
  916. begin
  917. with GLSLMemo do
  918. begin
  919. Redo;
  920. SetFocus;
  921. end;
  922. end;
  923. procedure TShaderMemoForm.TBSaveClick(Sender: TObject);
  924. begin
  925. if SaveDialog.Execute then
  926. GLSLMemo.Lines.SaveToFile(SaveDialog.FileName);
  927. SetFocus;
  928. end;
  929. procedure TShaderMemoForm.TBStayOnTopClick(Sender: TObject);
  930. begin
  931. if TBStayOnTop.Down then
  932. FormStyle := fsStayOnTop
  933. else
  934. FormStyle := fsNormal;
  935. end;
  936. procedure TShaderMemoForm.TBUndoClick(Sender: TObject);
  937. begin
  938. with GLSLMemo do
  939. begin
  940. Undo;
  941. SetFocus;
  942. end;
  943. end;
  944. procedure TShaderMemoForm.CheckButtonClick(Sender: TObject);
  945. begin
  946. if Assigned(FOnCheck) then
  947. FOnCheck(Self);
  948. end;
  949. //-----------------------------------------------
  950. initialization
  951. //-----------------------------------------------
  952. finalization
  953. ReleaseGLShaderEditor;
  954. end.