GLS.InitOpenGL.pas 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. //
  2. // The graphics engine GLScene
  3. //
  4. unit GLS.InitOpenGL;
  5. (*
  6. Initialisation of OpenGL for Vcl adapted from github.com/LUXOPHIA
  7. *)
  8. interface
  9. uses
  10. Winapi.OpenGL,
  11. Winapi.OpenGLext,
  12. Winapi.Windows,
  13. Vcl.Forms,
  14. System.SysUtils;
  15. type
  16. TGLOpenGL = class
  17. private
  18. CustomForm: TCustomForm;
  19. _WND: HWND;
  20. _DC: HDC;
  21. protected
  22. _PFD: TPixelFormatDescriptor;
  23. _PFI: Integer;
  24. _RC: HGLRC;
  25. procedure SetPFD(const PFD_: TPixelFormatDescriptor);
  26. procedure SetPFI(const PFI_: Integer);
  27. procedure CreateWindow;
  28. procedure DestroyWindow;
  29. procedure ValidatePFD(const PFD_: TPixelFormatDescriptor);
  30. procedure ValidatePFI(const PFI_: Integer);
  31. procedure CreateDC;
  32. procedure DestroyDC;
  33. procedure CreateRC;
  34. procedure DestroyRC;
  35. public
  36. constructor Create;
  37. destructor Destroy; override;
  38. property PFD: TPixelFormatDescriptor read _PFD write SetPFD;
  39. property PFI: Integer read _PFI write SetPFI;
  40. property RC: HGLRC read _RC;
  41. class function DefaultPFD: TPixelFormatDescriptor;
  42. procedure BeginGL;
  43. procedure EndGL;
  44. procedure InitOpenGL;
  45. procedure ApplyPixelFormat(const DC_: HDC);
  46. end;
  47. TGLShader = class
  48. private
  49. protected
  50. _ID: Cardinal;
  51. public
  52. constructor Create(const Kind_: Cardinal);
  53. destructor Destroy; override;
  54. property ID: Cardinal read _ID;
  55. procedure SetSource(const Source_: String);
  56. end;
  57. TGLShaderV = class(TGLShader)
  58. private
  59. protected
  60. public
  61. constructor Create;
  62. destructor Destroy; override;
  63. end;
  64. TGLShaderG = class(TGLShader)
  65. private
  66. protected
  67. public
  68. constructor Create;
  69. destructor Destroy; override;
  70. end;
  71. TGLShaderF = class(TGLShader)
  72. private
  73. protected
  74. public
  75. constructor Create;
  76. destructor Destroy; override;
  77. end;
  78. TGLProgram = class
  79. private
  80. protected
  81. _ID: Cardinal;
  82. public
  83. constructor Create;
  84. destructor Destroy; override;
  85. procedure Attach(const Shader_: TGLShader);
  86. procedure Detach(const Shader_: TGLShader);
  87. procedure Link;
  88. procedure Use;
  89. end;
  90. TGLBuffer<_TYPE_: record > = class
  91. public type
  92. _PValue_ = ^_TYPE_;
  93. private
  94. protected
  95. _ID: Cardinal;
  96. _Kind: Cardinal;
  97. _Count: Integer;
  98. _Head: _PValue_;
  99. procedure SetCount(const Count_: Integer);
  100. public
  101. constructor Create(const Kind_: Cardinal);
  102. destructor Destroy; override;
  103. property ID: Cardinal read _ID;
  104. property Count: Integer read _Count write SetCount;
  105. procedure Bind;
  106. procedure Unbind;
  107. procedure Map;
  108. procedure Unmap;
  109. end;
  110. TGLBufferV<_TYPE_: record > = class(TGLBuffer<_TYPE_>)
  111. private
  112. protected
  113. public
  114. constructor Create;
  115. destructor Destroy; override;
  116. end;
  117. TGLBufferI<_TYPE_: record > = class(TGLBuffer<_TYPE_>)
  118. private
  119. protected
  120. public
  121. constructor Create;
  122. destructor Destroy; override;
  123. end;
  124. TGLBufferU<_TYPE_: record > = class(TGLBuffer<_TYPE_>)
  125. private
  126. protected
  127. public
  128. constructor Create;
  129. destructor Destroy; override;
  130. end;
  131. TGLArray = class
  132. private
  133. protected
  134. _ID: Cardinal;
  135. public
  136. constructor Create;
  137. destructor Destroy; override;
  138. property ID: Cardinal read _ID;
  139. procedure BeginBind;
  140. procedure EndBind;
  141. end;
  142. var
  143. GLOpenGL: TGLOpenGL;
  144. implementation //-------------------------------------------------------------
  145. procedure TGLOpenGL.SetPFD(const PFD_: TPixelFormatDescriptor);
  146. begin
  147. DestroyRC;
  148. DestroyDC;
  149. CreateDC;
  150. ValidatePFD(PFD_);
  151. CreateRC;
  152. end;
  153. procedure TGLOpenGL.SetPFI(const PFI_: Integer);
  154. begin
  155. DestroyRC;
  156. DestroyDC;
  157. CreateDC;
  158. ValidatePFI(PFI_);
  159. CreateRC;
  160. end;
  161. procedure TGLOpenGL.CreateWindow;
  162. begin
  163. CustomForm := TCustomForm.CreateNew(nil);
  164. _WND := CustomForm.Handle;
  165. end;
  166. procedure TGLOpenGL.DestroyWindow;
  167. begin
  168. CustomForm.Free;
  169. end;
  170. // ------------------------------------------------------------------------------
  171. procedure TGLOpenGL.ValidatePFD(const PFD_: TPixelFormatDescriptor);
  172. var
  173. I: Integer;
  174. begin
  175. _PFD := PFD_;
  176. I := ChoosePixelFormat(_DC, @_PFD);
  177. Assert(I > 0, 'Not found the PixelFormat with a close setting!');
  178. ValidatePFI(I);
  179. end;
  180. procedure TGLOpenGL.ValidatePFI(const PFI_: Integer);
  181. begin
  182. _PFI := PFI_;
  183. Assert(DescribePixelFormat(_DC, _PFI, SizeOf(TPixelFormatDescriptor), _PFD),
  184. 'Not found the PixelFormat of the index!');
  185. end;
  186. // ------------------------------------------------------------------------------
  187. procedure TGLOpenGL.CreateDC;
  188. begin
  189. _DC := GetDC(_WND);
  190. end;
  191. procedure TGLOpenGL.DestroyDC;
  192. begin
  193. ReleaseDC(0, _DC);
  194. end;
  195. // ------------------------------------------------------------------------------
  196. procedure TGLOpenGL.CreateRC;
  197. begin
  198. ApplyPixelFormat(_DC);
  199. _RC := wglCreateContext(_DC);
  200. end;
  201. procedure TGLOpenGL.DestroyRC;
  202. begin
  203. wglDeleteContext(_RC);
  204. end;
  205. constructor TGLOpenGL.Create;
  206. begin
  207. inherited;
  208. CreateWindow;
  209. CreateDC;
  210. ValidatePFD(DefaultPFD);
  211. CreateRC;
  212. InitOpenGL;
  213. end;
  214. destructor TGLOpenGL.Destroy;
  215. begin
  216. DestroyRC;
  217. DestroyDC;
  218. DestroyWindow;
  219. inherited;
  220. end;
  221. class function TGLOpenGL.DefaultPFD: TPixelFormatDescriptor;
  222. begin
  223. with Result do
  224. begin
  225. nSize := SizeOf(TPixelFormatDescriptor);
  226. nVersion := 1;
  227. dwFlags := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;
  228. iPixelType := PFD_TYPE_RGBA;
  229. cColorBits := 24;
  230. cRedBits := 0;
  231. cRedShift := 0;
  232. cGreenBits := 0;
  233. cGreenShift := 0;
  234. cBlueBits := 0;
  235. cBlueShift := 0;
  236. cAlphaBits := 0;
  237. cAlphaShift := 0;
  238. cAccumBits := 0;
  239. cAccumRedBits := 0;
  240. cAccumGreenBits := 0;
  241. cAccumBlueBits := 0;
  242. cAccumAlphaBits := 0;
  243. cDepthBits := 32;
  244. cStencilBits := 0;
  245. cAuxBuffers := 0;
  246. iLayerType := PFD_MAIN_PLANE;
  247. bReserved := 0;
  248. dwLayerMask := 0;
  249. dwVisibleMask := 0;
  250. dwDamageMask := 0;
  251. end;
  252. end;
  253. procedure TGLOpenGL.BeginGL;
  254. begin
  255. wglMakeCurrent(_DC, _RC);
  256. end;
  257. procedure TGLOpenGL.EndGL;
  258. begin
  259. wglMakeCurrent(_DC, 0);
  260. end;
  261. // ------------------------------------------------------------------------------
  262. procedure TGLOpenGL.InitOpenGL;
  263. begin
  264. BeginGL;
  265. glEnable(GL_DEPTH_TEST);
  266. glEnable(GL_CULL_FACE);
  267. EndGL;
  268. end;
  269. // ------------------------------------------------------------------------------
  270. procedure TGLOpenGL.ApplyPixelFormat(const DC_: HDC);
  271. begin
  272. Assert(SetPixelFormat(DC_, _PFI, @_PFD), 'SetPixelFormat() is failed!');
  273. end;
  274. constructor TGLShader.Create(const Kind_: Cardinal);
  275. begin
  276. inherited Create;
  277. _ID := glCreateShader(Kind_);
  278. end;
  279. destructor TGLShader.Destroy;
  280. begin
  281. glDeleteShader(_ID);
  282. inherited;
  283. end;
  284. procedure TGLShader.SetSource(const Source_: String);
  285. var
  286. P: PAnsiChar;
  287. N: Integer;
  288. E: Integer;
  289. Cs: array of PGLchar;
  290. CsN: Integer;
  291. begin
  292. P := PAnsiChar(AnsiString(Source_));
  293. N := Length(Source_);
  294. glShaderSource(_ID, 1, @P, @N);
  295. glCompileShader(_ID);
  296. glGetShaderiv(_ID, GL_COMPILE_STATUS, @E);
  297. if E = GL_FALSE then
  298. begin
  299. glGetShaderiv(_ID, GL_INFO_LOG_LENGTH, @N);
  300. SetLength(Cs, N);
  301. glGetShaderInfoLog(_ID, N, @CsN, @Cs[0]);
  302. Assert(False, AnsiString(Cs));
  303. end;
  304. end;
  305. constructor TGLShaderV.Create;
  306. begin
  307. inherited Create(GL_VERTEX_SHADER);
  308. end;
  309. destructor TGLShaderV.Destroy;
  310. begin
  311. inherited;
  312. end;
  313. constructor TGLShaderG.Create;
  314. begin
  315. inherited Create(GL_GEOMETRY_SHADER);
  316. end;
  317. destructor TGLShaderG.Destroy;
  318. begin
  319. inherited;
  320. end;
  321. constructor TGLShaderF.Create;
  322. begin
  323. inherited Create(GL_FRAGMENT_SHADER);
  324. end;
  325. destructor TGLShaderF.Destroy;
  326. begin
  327. inherited;
  328. end;
  329. constructor TGLProgram.Create;
  330. begin
  331. inherited;
  332. _ID := glCreateProgram;
  333. end;
  334. destructor TGLProgram.Destroy;
  335. begin
  336. glDeleteProgram(_ID);
  337. inherited;
  338. end;
  339. procedure TGLProgram.Attach(const Shader_: TGLShader);
  340. begin
  341. glAttachShader(_ID, Shader_.ID);
  342. end;
  343. procedure TGLProgram.Detach(const Shader_: TGLShader);
  344. begin
  345. glDetachShader(_ID, Shader_.ID);
  346. end;
  347. // ------------------------------------------------------------------------------
  348. procedure TGLProgram.Link;
  349. begin
  350. glLinkProgram(_ID);
  351. end;
  352. // ------------------------------------------------------------------------------
  353. procedure TGLProgram.Use;
  354. begin
  355. glUseProgram(_ID);
  356. end;
  357. procedure TGLBuffer<_TYPE_>.SetCount(const Count_: Integer);
  358. begin
  359. _Count := Count_;
  360. Bind;
  361. glBufferData(_Kind, SizeOf(_TYPE_) * _Count, nil, GL_DYNAMIC_DRAW);
  362. Unbind;
  363. end;
  364. constructor TGLBuffer<_TYPE_>.Create(const Kind_: Cardinal);
  365. begin
  366. inherited Create;
  367. glGenBuffers(1, @_ID);
  368. _Kind := Kind_;
  369. Count := 0;
  370. end;
  371. destructor TGLBuffer<_TYPE_>.Destroy;
  372. begin
  373. glDeleteBuffers(1, @_ID);
  374. inherited;
  375. end;
  376. procedure TGLBuffer<_TYPE_>.Bind;
  377. begin
  378. glBindBuffer(_Kind, _ID);
  379. end;
  380. procedure TGLBuffer<_TYPE_>.Unbind;
  381. begin
  382. glBindBuffer(_Kind, 0);
  383. end;
  384. // ------------------------------------------------------------------------------
  385. procedure TGLBuffer<_TYPE_>.Map;
  386. begin
  387. Bind;
  388. _Head := glMapBuffer(_Kind, GL_READ_WRITE);
  389. end;
  390. procedure TGLBuffer<_TYPE_>.Unmap;
  391. begin
  392. glUnmapBuffer(_Kind);
  393. Unbind;
  394. end;
  395. constructor TGLBufferV<_TYPE_>.Create;
  396. begin
  397. inherited Create(GL_ARRAY_BUFFER);
  398. end;
  399. destructor TGLBufferV<_TYPE_>.Destroy;
  400. begin
  401. inherited;
  402. end;
  403. constructor TGLBufferI<_TYPE_>.Create;
  404. begin
  405. inherited Create(GL_ELEMENT_ARRAY_BUFFER);
  406. end;
  407. destructor TGLBufferI<_TYPE_>.Destroy;
  408. begin
  409. inherited;
  410. end;
  411. constructor TGLBufferU<_TYPE_>.Create;
  412. begin
  413. inherited Create(GL_UNIFORM_BUFFER);
  414. end;
  415. destructor TGLBufferU<_TYPE_>.Destroy;
  416. begin
  417. inherited;
  418. end;
  419. constructor TGLArray.Create;
  420. begin
  421. inherited Create;
  422. glGenVertexArrays(1, @_ID);
  423. end;
  424. destructor TGLArray.Destroy;
  425. begin
  426. glDeleteVertexArrays(1, @_ID);
  427. inherited;
  428. end;
  429. procedure TGLArray.BeginBind;
  430. begin
  431. glBindVertexArray(_ID);
  432. end;
  433. procedure TGLArray.EndBind;
  434. begin
  435. glBindVertexArray(0);
  436. end;
  437. initialization //-------------------------------------------------------------
  438. GLOpenGL := TGLOpenGL.Create;
  439. GLOpenGL.BeginGL;
  440. InitOpenGLext;
  441. finalization
  442. GLOpenGL.EndGL;
  443. GLOpenGL.Free;
  444. end.