You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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