Scene.InitOpenGL.pas 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. //
  2. // The graphics platform GLScene https://github.com/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. System.SysUtils,
  14. Vcl.Forms;
  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. //=====================================================================
  145. implementation
  146. //=====================================================================
  147. procedure TGLOpenGL.SetPFD(const PFD_: TPixelFormatDescriptor);
  148. begin
  149. DestroyRC;
  150. DestroyDC;
  151. CreateDC;
  152. ValidatePFD(PFD_);
  153. CreateRC;
  154. end;
  155. procedure TGLOpenGL.SetPFI(const PFI_: Integer);
  156. begin
  157. DestroyRC;
  158. DestroyDC;
  159. CreateDC;
  160. ValidatePFI(PFI_);
  161. CreateRC;
  162. end;
  163. procedure TGLOpenGL.CreateWindow;
  164. begin
  165. CustomForm := TCustomForm.CreateNew(nil);
  166. _WND := CustomForm.Handle;
  167. end;
  168. procedure TGLOpenGL.DestroyWindow;
  169. begin
  170. CustomForm.Free;
  171. end;
  172. // ------------------------------------------------------------------------------
  173. procedure TGLOpenGL.ValidatePFD(const PFD_: TPixelFormatDescriptor);
  174. var
  175. I: Integer;
  176. begin
  177. _PFD := PFD_;
  178. I := ChoosePixelFormat(_DC, @_PFD);
  179. Assert(I > 0, 'Not found the PixelFormat with a close setting!');
  180. ValidatePFI(I);
  181. end;
  182. procedure TGLOpenGL.ValidatePFI(const PFI_: Integer);
  183. begin
  184. _PFI := PFI_;
  185. Assert(DescribePixelFormat(_DC, _PFI, SizeOf(TPixelFormatDescriptor), _PFD),
  186. 'Not found the PixelFormat of the index!');
  187. end;
  188. // ------------------------------------------------------------------------------
  189. procedure TGLOpenGL.CreateDC;
  190. begin
  191. _DC := GetDC(_WND);
  192. end;
  193. procedure TGLOpenGL.DestroyDC;
  194. begin
  195. ReleaseDC(0, _DC);
  196. end;
  197. // ------------------------------------------------------------------------------
  198. procedure TGLOpenGL.CreateRC;
  199. begin
  200. ApplyPixelFormat(_DC);
  201. _RC := wglCreateContext(_DC);
  202. end;
  203. procedure TGLOpenGL.DestroyRC;
  204. begin
  205. wglDeleteContext(_RC);
  206. end;
  207. constructor TGLOpenGL.Create;
  208. begin
  209. inherited;
  210. CreateWindow;
  211. CreateDC;
  212. ValidatePFD(DefaultPFD);
  213. CreateRC;
  214. InitOpenGL;
  215. end;
  216. destructor TGLOpenGL.Destroy;
  217. begin
  218. DestroyRC;
  219. DestroyDC;
  220. DestroyWindow;
  221. inherited;
  222. end;
  223. class function TGLOpenGL.DefaultPFD: TPixelFormatDescriptor;
  224. begin
  225. with Result do
  226. begin
  227. nSize := SizeOf(TPixelFormatDescriptor);
  228. nVersion := 1;
  229. dwFlags := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;
  230. iPixelType := PFD_TYPE_RGBA;
  231. cColorBits := 24;
  232. cRedBits := 0;
  233. cRedShift := 0;
  234. cGreenBits := 0;
  235. cGreenShift := 0;
  236. cBlueBits := 0;
  237. cBlueShift := 0;
  238. cAlphaBits := 0;
  239. cAlphaShift := 0;
  240. cAccumBits := 0;
  241. cAccumRedBits := 0;
  242. cAccumGreenBits := 0;
  243. cAccumBlueBits := 0;
  244. cAccumAlphaBits := 0;
  245. cDepthBits := 32;
  246. cStencilBits := 0;
  247. cAuxBuffers := 0;
  248. iLayerType := PFD_MAIN_PLANE;
  249. bReserved := 0;
  250. dwLayerMask := 0;
  251. dwVisibleMask := 0;
  252. dwDamageMask := 0;
  253. end;
  254. end;
  255. procedure TGLOpenGL.BeginGL;
  256. begin
  257. wglMakeCurrent(_DC, _RC);
  258. end;
  259. procedure TGLOpenGL.EndGL;
  260. begin
  261. wglMakeCurrent(_DC, 0);
  262. end;
  263. // ------------------------------------------------------------------------------
  264. procedure TGLOpenGL.InitOpenGL;
  265. begin
  266. BeginGL;
  267. glEnable(GL_DEPTH_TEST);
  268. glEnable(GL_CULL_FACE);
  269. EndGL;
  270. end;
  271. // ------------------------------------------------------------------------------
  272. procedure TGLOpenGL.ApplyPixelFormat(const DC_: HDC);
  273. begin
  274. Assert(SetPixelFormat(DC_, _PFI, @_PFD), 'SetPixelFormat() is failed!');
  275. end;
  276. constructor TGLShader.Create(const Kind_: Cardinal);
  277. begin
  278. inherited Create;
  279. _ID := glCreateShader(Kind_);
  280. end;
  281. destructor TGLShader.Destroy;
  282. begin
  283. glDeleteShader(_ID);
  284. inherited;
  285. end;
  286. procedure TGLShader.SetSource(const Source_: String);
  287. var
  288. P: PAnsiChar;
  289. N: Integer;
  290. E: Integer;
  291. Cs: array of PGLchar;
  292. CsN: Integer;
  293. begin
  294. P := PAnsiChar(AnsiString(Source_));
  295. N := Length(Source_);
  296. glShaderSource(_ID, 1, @P, @N);
  297. glCompileShader(_ID);
  298. glGetShaderiv(_ID, GL_COMPILE_STATUS, @E);
  299. if E = GL_FALSE then
  300. begin
  301. glGetShaderiv(_ID, GL_INFO_LOG_LENGTH, @N);
  302. SetLength(Cs, N);
  303. glGetShaderInfoLog(_ID, N, @CsN, @Cs[0]);
  304. Assert(False, AnsiString(Cs));
  305. end;
  306. end;
  307. constructor TGLShaderV.Create;
  308. begin
  309. inherited Create(GL_VERTEX_SHADER);
  310. end;
  311. destructor TGLShaderV.Destroy;
  312. begin
  313. inherited;
  314. end;
  315. constructor TGLShaderG.Create;
  316. begin
  317. inherited Create(GL_GEOMETRY_SHADER);
  318. end;
  319. destructor TGLShaderG.Destroy;
  320. begin
  321. inherited;
  322. end;
  323. constructor TGLShaderF.Create;
  324. begin
  325. inherited Create(GL_FRAGMENT_SHADER);
  326. end;
  327. destructor TGLShaderF.Destroy;
  328. begin
  329. inherited;
  330. end;
  331. constructor TGLProgram.Create;
  332. begin
  333. inherited;
  334. _ID := glCreateProgram;
  335. end;
  336. destructor TGLProgram.Destroy;
  337. begin
  338. glDeleteProgram(_ID);
  339. inherited;
  340. end;
  341. procedure TGLProgram.Attach(const Shader_: TGLShader);
  342. begin
  343. glAttachShader(_ID, Shader_.ID);
  344. end;
  345. procedure TGLProgram.Detach(const Shader_: TGLShader);
  346. begin
  347. glDetachShader(_ID, Shader_.ID);
  348. end;
  349. // ------------------------------------------------------------------------------
  350. procedure TGLProgram.Link;
  351. begin
  352. glLinkProgram(_ID);
  353. end;
  354. // ------------------------------------------------------------------------------
  355. procedure TGLProgram.Use;
  356. begin
  357. glUseProgram(_ID);
  358. end;
  359. procedure TGLBuffer<_TYPE_>.SetCount(const Count_: Integer);
  360. begin
  361. _Count := Count_;
  362. Bind;
  363. glBufferData(_Kind, SizeOf(_TYPE_) * _Count, nil, GL_DYNAMIC_DRAW);
  364. Unbind;
  365. end;
  366. constructor TGLBuffer<_TYPE_>.Create(const Kind_: Cardinal);
  367. begin
  368. inherited Create;
  369. glGenBuffers(1, @_ID);
  370. _Kind := Kind_;
  371. Count := 0;
  372. end;
  373. destructor TGLBuffer<_TYPE_>.Destroy;
  374. begin
  375. glDeleteBuffers(1, @_ID);
  376. inherited;
  377. end;
  378. procedure TGLBuffer<_TYPE_>.Bind;
  379. begin
  380. glBindBuffer(_Kind, _ID);
  381. end;
  382. procedure TGLBuffer<_TYPE_>.Unbind;
  383. begin
  384. glBindBuffer(_Kind, 0);
  385. end;
  386. // ------------------------------------------------------------------------------
  387. procedure TGLBuffer<_TYPE_>.Map;
  388. begin
  389. Bind;
  390. _Head := glMapBuffer(_Kind, GL_READ_WRITE);
  391. end;
  392. procedure TGLBuffer<_TYPE_>.Unmap;
  393. begin
  394. glUnmapBuffer(_Kind);
  395. Unbind;
  396. end;
  397. constructor TGLBufferV<_TYPE_>.Create;
  398. begin
  399. inherited Create(GL_ARRAY_BUFFER);
  400. end;
  401. destructor TGLBufferV<_TYPE_>.Destroy;
  402. begin
  403. inherited;
  404. end;
  405. constructor TGLBufferI<_TYPE_>.Create;
  406. begin
  407. inherited Create(GL_ELEMENT_ARRAY_BUFFER);
  408. end;
  409. destructor TGLBufferI<_TYPE_>.Destroy;
  410. begin
  411. inherited;
  412. end;
  413. constructor TGLBufferU<_TYPE_>.Create;
  414. begin
  415. inherited Create(GL_UNIFORM_BUFFER);
  416. end;
  417. destructor TGLBufferU<_TYPE_>.Destroy;
  418. begin
  419. inherited;
  420. end;
  421. constructor TGLArray.Create;
  422. begin
  423. inherited Create;
  424. glGenVertexArrays(1, @_ID);
  425. end;
  426. destructor TGLArray.Destroy;
  427. begin
  428. glDeleteVertexArrays(1, @_ID);
  429. inherited;
  430. end;
  431. procedure TGLArray.BeginBind;
  432. begin
  433. glBindVertexArray(_ID);
  434. end;
  435. procedure TGLArray.EndBind;
  436. begin
  437. glBindVertexArray(0);
  438. end;
  439. // ====================================================================
  440. initialization
  441. // ====================================================================
  442. GLOpenGL := TGLOpenGL.Create;
  443. GLOpenGL.BeginGL;
  444. InitOpenGLext;
  445. finalization
  446. GLOpenGL.EndGL;
  447. GLOpenGL.Free;
  448. end.