Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

653 wiersze
26 KiB

  1. unit uglcFrameBufferObject;
  2. { Package: OpenGLCore
  3. Prefix: glc - OpenGL Core
  4. Beschreibung: diese Unit enthält eine Klassen-Kapselung der OpenGL FrameBufferObjekte
  5. Beispiel:
  6. var
  7. fbo: TglcFrameBufferObject;
  8. tex: TglcTextureBuffer;
  9. buf: TglcRenderBuffer;
  10. fbo := TglcFrameBufferObject;
  11. try
  12. ffbo.SetSize(800, 600);
  13. // creating texture buffer as color buffer
  14. tex := TglcTextureBuffer.Create(TglcFormat.fmRGBA, TglcInternalFormat.ifRGBA16F);
  15. fbo.AddBuffer(tex, TglcAttachment.atColor0, true);
  16. // creating render buffer as depth buffer
  17. buf := TglcRenderBuffer.Create(TglcInternalFormat.ifDepthComponent);
  18. fbo.AddBuffer(buf, TglcAttachment.atDepth, true);
  19. // render to frame buffer object
  20. fbo.Bind;
  21. // do normal rendering
  22. fbo.Unbind;
  23. // use texture buffer
  24. tex.Bind;
  25. // do normal rendering
  26. tex.Unbind;
  27. finally
  28. FreeAndNil(fbo);
  29. end; }
  30. {$mode objfpc}{$H+}
  31. interface
  32. uses
  33. Classes, SysUtils, fgl, dglOpenGl, uglcTypes;
  34. type
  35. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  36. TglcBufferType = (btRenderBuffer, btTextureBuffer);
  37. TglcBuffer = class(TObject)
  38. private
  39. fBufferType: TglcBufferType;
  40. fWidth: Integer;
  41. fHeight: Integer;
  42. procedure SetWidth(const aValue: Integer);
  43. procedure SetHeight(const aValue: Integer);
  44. public
  45. property Width : Integer read fWidth write SetWidth;
  46. property Height: Integer read fHeight write SetHeight;
  47. property BufferType: TglcBufferType read fBufferType;
  48. procedure SetSize(const aWidth, aHeight: Integer); virtual;
  49. end;
  50. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  51. EglcRenderBuffer = class(Exception);
  52. TglcRenderBuffer = class(TglcBuffer)
  53. private
  54. fID: gluInt;
  55. fFormat: TglcInternalFormat;
  56. procedure UpdateRenderBufferStorage;
  57. procedure SetFormat(const aValue: TglcInternalFormat);
  58. public
  59. property ID: gluInt read fID;
  60. property Format: TglcInternalFormat read fFormat write SetFormat;
  61. procedure SetSize(const aWidth, aHeight: Integer); override;
  62. procedure Bind;
  63. procedure Unbind;
  64. constructor Create(const aFormat: TglcInternalFormat);
  65. destructor Destroy; override;
  66. end;
  67. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  68. EglcTextureBuffer = class(exception);
  69. TglcTextureBuffer = class(TglcBuffer)
  70. private
  71. fID: GLuint;
  72. fFormat: TglcFormat;
  73. fInternalFormat: TglcInternalFormat;
  74. fBorder: Boolean;
  75. procedure UpdateTexImage;
  76. procedure SetFormat(const aValue: TglcFormat);
  77. procedure SetInternalFormat(const aValue: TglcInternalFormat);
  78. procedure SetBorder(const aValue: Boolean);
  79. public
  80. property ID : GLuint read fID;
  81. property Border : Boolean read fBorder write SetBorder;
  82. property Format : TglcFormat read fFormat write SetFormat;
  83. property InternalFormat: TglcInternalFormat read fInternalFormat write SetInternalFormat;
  84. procedure SetSize(const aWidth, aHeight: Integer); override;
  85. procedure Bind(const aEnableTextureUnit: Boolean = true);
  86. procedure Unbind(const aDisableTextureUnit: Boolean = true);
  87. constructor Create(const aFormat: TglcFormat; const aInternalFormat: TglcInternalFormat);
  88. destructor Destroy; override;
  89. end;
  90. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  91. EglcFrameBufferObject = class(Exception);
  92. TglcFrameBufferObject = class(TObject)
  93. private type
  94. TglcAttachmentContainer = class(TObject)
  95. Buffer: TglcBuffer;
  96. Attachment: TglcAttachment;
  97. OwnsObject: Boolean;
  98. constructor Create(const aBuffer: TglcBuffer; const aAttachment: TglcAttachment; const aOwnsObject: Boolean = true);
  99. destructor Destroy; override;
  100. end;
  101. TglcAttachmentContainerList = specialize TFPGObjectList<TglcAttachmentContainer>;
  102. private
  103. fID: GLuint;
  104. fOwnsObjects: Boolean;
  105. fWidth: Integer;
  106. fHeight: Integer;
  107. fBuffers: TglcAttachmentContainerList;
  108. function GetBuffer(const aIndex: Integer): TglcBuffer;
  109. procedure SetBuffer(const aIndex: Integer; const aValue: TglcBuffer);
  110. function GetAttachment(const aIndex: Integer): TglcAttachment;
  111. procedure SetAttachment(const aIndex: Integer; const aValue: TglcAttachment);
  112. function GetBufferCount: Integer;
  113. procedure Attach(const aIndex: Integer);
  114. procedure Detach(const aIndex: Integer);
  115. procedure SetWidth(const aValue: Integer);
  116. procedure SetHeight(const aValue: Integer);
  117. procedure CheckFrameBufferStatus;
  118. procedure UpdateAndCheckFBO;
  119. public
  120. property ID : GLuint read fID;
  121. property Count : Integer read GetBufferCount;
  122. property OwnsObjects: Boolean read fOwnsObjects;
  123. property Width : Integer read fWidth write SetWidth;
  124. property Height : Integer read fHeight write SetHeight;
  125. property Attachments[const aIndex: Integer]: TglcAttachment read GetAttachment write SetAttachment;
  126. property Buffers [const aIndex: Integer]: TglcBuffer read GetBuffer write SetBuffer;
  127. procedure AddBuffer(const aBuffer: TglcBuffer; const aAttachment: TglcAttachment; const aOwnsBuffer: Boolean = true);
  128. procedure DelBuffer(const aIndex: Integer);
  129. function RemBuffer(const aBuffer: TglcBuffer): Integer;
  130. function IndexOfBuffer(const aBuffer: TglcBuffer): Integer;
  131. procedure SetSize(const aWidth, aHeight: Integer);
  132. function CheckAttachment(const aAttachment: TglcAttachment): Boolean;
  133. procedure Bind(const aSetViewport: Boolean = true);
  134. procedure Unbind(const aResetViewport: Boolean = true);
  135. constructor Create(const aOwnBuffers: Boolean = true);
  136. destructor Destroy; override;
  137. end;
  138. implementation
  139. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  140. //TglcBuffer////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  141. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  142. procedure TglcBuffer.SetWidth(const aValue: Integer);
  143. begin
  144. SetSize(aValue, fHeight);
  145. end;
  146. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  147. procedure TglcBuffer.SetHeight(const aValue: Integer);
  148. begin
  149. SetSize(fWidth, aValue);
  150. end;
  151. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  152. procedure TglcBuffer.SetSize(const aWidth, aHeight: Integer);
  153. begin
  154. fWidth := aWidth;
  155. fHeight := aHeight;
  156. end;
  157. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  158. //TglcRenderBuffer//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  159. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  160. procedure TglcRenderBuffer.UpdateRenderBufferStorage;
  161. begin
  162. glGetError; //clear Erroros
  163. Bind;
  164. glRenderbufferStorage(GL_RENDERBUFFER, GLenum(fFormat), fWidth, fHeight);
  165. Unbind;
  166. glcCheckAndRaiseError;
  167. end;
  168. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  169. procedure TglcRenderBuffer.SetFormat(const aValue: TglcInternalFormat);
  170. begin
  171. fFormat := aValue;
  172. UpdateRenderBufferStorage;
  173. end;
  174. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  175. procedure TglcRenderBuffer.SetSize(const aWidth, aHeight: Integer);
  176. begin
  177. if (aWidth <= 0) or (aHeight <= 0) then
  178. raise EglcRenderBuffer.Create('invalid width or height');
  179. if (aWidth <> fWidth) or (aHeight <> fHeight) then begin
  180. inherited SetSize(aWidth, aHeight);
  181. UpdateRenderBufferStorage;
  182. end;
  183. end;
  184. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  185. procedure TglcRenderBuffer.Bind;
  186. begin
  187. glBindRenderbuffer(GL_RENDERBUFFER, fID);
  188. end;
  189. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  190. procedure TglcRenderBuffer.Unbind;
  191. begin
  192. glBindRenderbuffer(GL_RENDERBUFFER, 0);
  193. end;
  194. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  195. constructor TglcRenderBuffer.Create(const aFormat: TglcInternalFormat);
  196. begin
  197. inherited Create;
  198. fBufferType := btRenderBuffer;
  199. glGenRenderbuffers(1, @fID);
  200. fFormat := aFormat;
  201. SetSize(64, 64);
  202. end;
  203. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  204. destructor TglcRenderBuffer.Destroy;
  205. begin
  206. glDeleteRenderbuffers(1, @fID);
  207. inherited Destroy;
  208. end;
  209. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  210. //TglcTextureBuffer/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  211. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  212. procedure TglcTextureBuffer.UpdateTexImage;
  213. begin
  214. glGetError; //clear errors
  215. Bind(false);
  216. glTexImage2D(GL_TEXTURE_2D, 0, GLenum(fInternalFormat), fWidth, fHeight, GLint(Byte(fBorder) and Byte(1)), GLenum(fFormat), GL_UNSIGNED_BYTE, nil);
  217. Unbind(false);
  218. glcCheckAndRaiseError;
  219. end;
  220. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  221. procedure TglcTextureBuffer.SetFormat(const aValue: TglcFormat);
  222. begin
  223. if (fFormat <> aValue) then begin
  224. fFormat := aValue;
  225. UpdateTexImage;
  226. end;
  227. end;
  228. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  229. procedure TglcTextureBuffer.SetInternalFormat(const aValue: TglcInternalFormat);
  230. begin
  231. if (fInternalFormat <> aValue) then begin
  232. fInternalFormat := aValue;
  233. UpdateTexImage;
  234. end;
  235. end;
  236. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  237. procedure TglcTextureBuffer.SetBorder(const aValue: Boolean);
  238. begin
  239. if (fBorder <> aValue) then begin
  240. fBorder := aValue;
  241. UpdateTexImage;
  242. end;
  243. end;
  244. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  245. procedure TglcTextureBuffer.SetSize(const aWidth, aHeight: Integer);
  246. begin
  247. if (aWidth <= 0) or (aHeight <= 0) then
  248. raise EglcTextureBuffer.Create('invalid width or height');
  249. if (aWidth <> fWidth) or (aHeight <> fHeight) then begin
  250. inherited SetSize(aWidth, aHeight);
  251. UpdateTexImage;
  252. end;
  253. end;
  254. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  255. procedure TglcTextureBuffer.Bind(const aEnableTextureUnit: Boolean = true);
  256. begin
  257. if aEnableTextureUnit then
  258. glEnable(GL_TEXTURE_2D);
  259. glBindTexture(GL_TEXTURE_2D, fID);
  260. end;
  261. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  262. procedure TglcTextureBuffer.Unbind(const aDisableTextureUnit: Boolean = true);
  263. begin
  264. if aDisableTextureUnit then
  265. glDisable(GL_TEXTURE_2D);
  266. glBindTexture(GL_TEXTURE_2D, 0);
  267. end;
  268. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  269. constructor TglcTextureBuffer.Create(const aFormat: TglcFormat; const aInternalFormat: TglcInternalFormat);
  270. begin
  271. inherited Create;
  272. fBufferType := btTextureBuffer;
  273. glGenTextures(1, @fID);
  274. Bind(false);
  275. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  276. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  277. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  278. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  279. Unbind(false);
  280. fFormat := aFormat;
  281. fInternalFormat := aInternalFormat;
  282. SetSize(64, 64);
  283. end;
  284. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  285. destructor TglcTextureBuffer.Destroy;
  286. begin
  287. glDeleteTextures(1, @fID);
  288. inherited Destroy;
  289. end;
  290. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  291. //TglcAttachment////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  292. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  293. constructor TglcFrameBufferObject.TglcAttachmentContainer.Create(const aBuffer: TglcBuffer;
  294. const aAttachment: TglcAttachment; const aOwnsObject: Boolean);
  295. begin
  296. inherited Create;
  297. Buffer := aBuffer;
  298. Attachment := aAttachment;
  299. OwnsObject := aOwnsObject;
  300. end;
  301. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  302. destructor TglcFrameBufferObject.TglcAttachmentContainer.Destroy;
  303. begin
  304. if OwnsObject then
  305. Buffer.Free;
  306. inherited Destroy;
  307. end;
  308. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  309. //TglcFrameBufferObject/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  310. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  311. function TglcFrameBufferObject.GetBuffer(const aIndex: Integer): TglcBuffer;
  312. begin
  313. if (aIndex >= 0) and (aIndex < fBuffers.Count) then
  314. result := fBuffers[aIndex].Buffer
  315. else
  316. raise EglcFrameBufferObject.Create('Index out of Bounds: ' + IntToStr(aIndex));
  317. end;
  318. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  319. procedure TglcFrameBufferObject.SetBuffer(const aIndex: Integer; const aValue: TglcBuffer);
  320. begin
  321. if (aIndex < 0) or (aIndex >= fBuffers.Count) then
  322. raise EglcFrameBufferObject.Create('Index out of Bounds: ' + IntToStr(aIndex));
  323. if not Assigned(aValue) then
  324. raise EglcFrameBufferObject.Create('invalid buffer');
  325. Detach(aIndex);
  326. fBuffers[aIndex].Buffer := aValue;
  327. Attach(aIndex);
  328. UpdateAndCheckFBO;
  329. end;
  330. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  331. function TglcFrameBufferObject.GetAttachment(const aIndex: Integer): TglcAttachment;
  332. begin
  333. if (aIndex >= 0) and (aIndex < fBuffers.Count) then
  334. result := fBuffers[aIndex].Attachment
  335. else
  336. raise EglcFrameBufferObject.Create('Index out of Bounds: ' + IntToStr(aIndex));
  337. end;
  338. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  339. procedure TglcFrameBufferObject.SetAttachment(const aIndex: Integer; const aValue: TglcAttachment);
  340. begin
  341. if (aIndex < 0) or (aIndex >= fBuffers.Count) then
  342. raise EglcFrameBufferObject.Create('Index out of Bounds: ' + IntToStr(aIndex));
  343. if not CheckAttachment(aValue) then
  344. raise EglcFrameBufferObject.Create('Attachment already assigned');
  345. Detach(aIndex);
  346. fBuffers[aIndex].Attachment := aValue;
  347. Attach(aIndex);
  348. UpdateAndCheckFBO;
  349. end;
  350. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  351. procedure TglcFrameBufferObject.Attach(const aIndex: Integer);
  352. var
  353. a: TglcAttachment;
  354. b: TglcBuffer;
  355. begin
  356. a := Attachments[aIndex];
  357. b := Buffers[aIndex];
  358. Bind(false);
  359. if (b.BufferType = btRenderBuffer) then
  360. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GLenum(a), GL_RENDERBUFFER, (b as TglcRenderBuffer).ID)
  361. else
  362. glFramebufferTexture2D(GL_FRAMEBUFFER, GLenum(a), GL_TEXTURE_2D, (b as TglcTextureBuffer).ID, 0);
  363. Unbind(false);
  364. end;
  365. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  366. procedure TglcFrameBufferObject.Detach(const aIndex: Integer);
  367. var
  368. a: TglcAttachment;
  369. b: TglcBuffer;
  370. begin
  371. a := Attachments[aIndex];
  372. b := Buffers[aIndex];
  373. Bind(false);
  374. if (b.BufferType = btRenderBuffer) then
  375. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GLenum(a), GL_RENDERBUFFER, 0)
  376. else
  377. glFramebufferTexture2D(GL_FRAMEBUFFER, GLenum(a), GL_TEXTURE_2D, 0, 0);
  378. Unbind(false);
  379. end;
  380. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  381. //legt die neue Breite fest
  382. //@Value: Breite;
  383. procedure TglcFrameBufferObject.SetWidth(const aValue: Integer);
  384. begin
  385. SetSize(aValue, fHeight);
  386. end;
  387. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  388. //legt die neue Höhe fest
  389. //@Value: neue Höhe;
  390. procedure TglcFrameBufferObject.SetHeight(const aValue: Integer);
  391. begin
  392. SetSize(fWidth, aValue);
  393. end;
  394. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  395. procedure TglcFrameBufferObject.CheckFrameBufferStatus;
  396. begin
  397. case glCheckFramebufferStatus(GL_FRAMEBUFFER) of
  398. GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
  399. raise EglcFrameBufferObject.Create('Incomplete attachment');
  400. GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
  401. raise EglcFrameBufferObject.Create('Missing attachment');
  402. GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
  403. raise EglcFrameBufferObject.Create('Incomplete dimensions');
  404. GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
  405. raise EglcFrameBufferObject.Create('Incomplete formats');
  406. GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
  407. raise EglcFrameBufferObject.Create('Incomplete draw buffer');
  408. GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
  409. raise EglcFrameBufferObject.Create('Incomplete read buffer');
  410. GL_FRAMEBUFFER_UNSUPPORTED:
  411. raise EglcFrameBufferObject.Create('Framebufferobjects unsupported');
  412. end;
  413. end;
  414. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  415. //prüft das FrameBufferObjekt auf Fehler
  416. procedure TglcFrameBufferObject.UpdateAndCheckFBO;
  417. function IsColorAttachment(const a: TglcAttachment): Boolean;
  418. begin
  419. result := (GLenum(a) >= GL_COLOR_ATTACHMENT0) and (GLenum(a) <= GL_COLOR_ATTACHMENT15);
  420. end;
  421. var
  422. buff: array of GLenum;
  423. b: GLboolean;
  424. i: Integer;
  425. begin
  426. if (fBuffers.Count = 0) then
  427. exit;
  428. Bind(false);
  429. //find ColorBuffers
  430. SetLength(buff, 0);
  431. for i := 0 to fBuffers.Count-1 do
  432. if IsColorAttachment(fBuffers[i].Attachment) then begin
  433. SetLength(buff, Length(buff) + 1);
  434. buff[High(buff)] := GLenum(fBuffers[i].Attachment);
  435. end;
  436. //set Read and Draw Buffer
  437. if (Length(buff) = 0) then begin
  438. glReadBuffer(GL_NONE);
  439. glDrawBuffer(GL_NONE);
  440. end else begin
  441. glDrawBuffers(Length(buff), @buff[0]);
  442. glGetBooleanv(GL_DOUBLEBUFFER, @b);
  443. if b then
  444. glReadBuffer(GL_BACK)
  445. else
  446. glReadBuffer(GL_FRONT);
  447. end;
  448. Unbind(false);
  449. end;
  450. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  451. function TglcFrameBufferObject.GetBufferCount: Integer;
  452. begin
  453. result := fBuffers.Count;
  454. end;
  455. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  456. procedure TglcFrameBufferObject.AddBuffer(const aBuffer: TglcBuffer;
  457. const aAttachment: TglcAttachment; const aOwnsBuffer: Boolean);
  458. begin
  459. if not Assigned(aBuffer) then
  460. raise EglcFrameBufferObject.Create('invalid buffer');
  461. if not CheckAttachment(aAttachment) then
  462. raise EglcFrameBufferObject.Create('attachment already assigned');
  463. fBuffers.Add(TglcAttachmentContainer.Create(aBuffer, aAttachment, fOwnsObjects and aOwnsBuffer));
  464. if OwnsObjects then
  465. aBuffer.SetSize(fWidth, fHeight);
  466. Attach(fBuffers.Count-1);
  467. UpdateAndCheckFBO;
  468. end;
  469. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  470. procedure TglcFrameBufferObject.DelBuffer(const aIndex: Integer);
  471. begin
  472. if (aIndex >= 0) and (aIndex < fBuffers.Count) then begin
  473. Detach(aIndex);
  474. fBuffers.Delete(aIndex);
  475. UpdateAndCheckFBO;
  476. end else
  477. raise EglcFrameBufferObject.Create('Index out of Bounds: ' + IntToStr(aIndex));
  478. end;
  479. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  480. function TglcFrameBufferObject.RemBuffer(const aBuffer: TglcBuffer): Integer;
  481. begin
  482. result := IndexOfBuffer(aBuffer);
  483. if (result >= 0) then
  484. DelBuffer(result);
  485. end;
  486. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  487. function TglcFrameBufferObject.IndexOfBuffer(const aBuffer: TglcBuffer): Integer;
  488. var
  489. i: Integer;
  490. begin
  491. for i := 0 to fBuffers.Count-1 do
  492. if (fBuffers[i].Buffer = aBuffer) then begin
  493. result := i;
  494. exit;
  495. end;
  496. result := -1;
  497. end;
  498. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  499. //legt die Größe neu fest
  500. //@Width: neue Breite;
  501. //@Height: neue Höhe;
  502. procedure TglcFrameBufferObject.SetSize(const aWidth, aHeight: Integer);
  503. var
  504. c: TglcAttachmentContainer;
  505. begin
  506. if (aWidth <= 0) or (aHeight <= 0) then
  507. raise EglcFrameBufferObject.Create('invalid width or height');
  508. fWidth := aWidth;
  509. fHeight := aHeight;
  510. if OwnsObjects then
  511. for c in fBuffers do
  512. if c.OwnsObject then
  513. c.Buffer.SetSize(fWidth, fHeight);
  514. end;
  515. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  516. function TglcFrameBufferObject.CheckAttachment(const aAttachment: TglcAttachment): Boolean;
  517. var
  518. i: Integer;
  519. begin
  520. result := false;
  521. for i := 0 to fBuffers.Count-1 do
  522. if (fBuffers[i].Attachment = aAttachment) then
  523. exit;
  524. result := true;
  525. end;
  526. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  527. //Bindet das FrameBufferObjekt
  528. procedure TglcFrameBufferObject.Bind(const aSetViewport: Boolean = true);
  529. begin
  530. glBindFramebuffer(GL_FRAMEBUFFER, fID);
  531. if aSetViewport then begin
  532. glPushAttrib(GL_VIEWPORT_BIT);
  533. glViewPort(0, 0, fWidth, fHeight);
  534. end;
  535. end;
  536. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  537. //Entbindet das FrameBufferObjekt
  538. procedure TglcFrameBufferObject.Unbind(const aResetViewport: Boolean = true);
  539. begin
  540. if aResetViewport then
  541. glPopAttrib;
  542. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  543. end;
  544. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  545. //erzeugt das Objekt
  546. constructor TglcFrameBufferObject.Create(const aOwnBuffers: Boolean = true);
  547. begin
  548. inherited Create;
  549. glGenFramebuffers(1, @fID);
  550. fWidth := 64;
  551. fHeight := 64;
  552. fOwnsObjects := aOwnBuffers;
  553. fBuffers := TglcAttachmentContainerList.Create(true); //containers are always owned by this object!
  554. end;
  555. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  556. //gibt das Objekt frei
  557. destructor TglcFrameBufferObject.Destroy;
  558. begin
  559. fBuffers.Free;
  560. glDeleteFramebuffers(1, @fID);
  561. inherited Destroy;
  562. end;
  563. end.