GLFBO.pas 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. //
  2. // This unit is part of the GLScene Engine, http://glscene.org
  3. //
  4. unit GLFBO;
  5. (*
  6. Implements FBO support for GLScene.
  7. Original author of the unit is Riz.
  8. Modified by DaStr, C4 and YarUnderoaker.
  9. *)
  10. interface
  11. {$I GLScene.inc}
  12. uses
  13. Winapi.OpenGL,
  14. Winapi.OpenGLext,
  15. System.SysUtils,
  16. OpenGLTokens,
  17. GLScene,
  18. GLContext,
  19. GLState,
  20. GLTexture,
  21. GLColor,
  22. GLRenderContextInfo,
  23. GLMultisampleImage,
  24. GLGraphics,
  25. GLTextureFormat,
  26. GLVectorTypes,
  27. GLS.Logger;
  28. const
  29. MaxColorAttachments = 32;
  30. type
  31. TGLRenderbuffer = class
  32. private
  33. FRenderbufferHandle: TGLRenderbufferHandle;
  34. FWidth: Integer;
  35. FHeight: Integer;
  36. FStorageValid: Boolean;
  37. function GetHandle: Cardinal;
  38. procedure SetHeight(const Value: Integer);
  39. procedure SetWidth(const Value: Integer);
  40. protected
  41. function GetInternalFormat: cardinal; virtual; abstract;
  42. procedure InvalidateStorage;
  43. public
  44. constructor Create;
  45. destructor Destroy; override;
  46. procedure Bind;
  47. procedure Unbind;
  48. (* Handle to the OpenGL render buffer object.
  49. If the handle hasn't already been allocated, it will be allocated
  50. by this call (ie. do not use if no OpenGL context is active!) *)
  51. property Handle: Cardinal read GetHandle;
  52. property Width: Integer read FWidth write SetWidth;
  53. property Height: Integer read FHeight write SetHeight;
  54. end;
  55. TGLDepthRBO = class(TGLRenderbuffer)
  56. private
  57. FDepthPrecision: TGLDepthPrecision;
  58. procedure SetDepthPrecision(const Value: TGLDepthPrecision);
  59. protected
  60. function GetInternalFormat: cardinal; override;
  61. public
  62. constructor Create;
  63. property DepthPrecision: TGLDepthPrecision read FDepthPrecision write
  64. SetDepthPrecision;
  65. end;
  66. TGLStencilPrecision = (spDefault, sp1bit, sp4bits, sp8bits, sp16bits);
  67. TGLStencilRBO = class(TGLRenderbuffer)
  68. private
  69. FStencilPrecision: TGLStencilPrecision;
  70. procedure SetStencilPrecision(const Value: TGLStencilPrecision);
  71. protected
  72. function GetInternalFormat: cardinal; override;
  73. public
  74. constructor Create;
  75. property StencilPrecision: TGLStencilPrecision read FStencilPrecision write
  76. SetStencilPrecision;
  77. end;
  78. TGLFrameBuffer = class
  79. private
  80. FFrameBufferHandle: TGLFramebufferHandle;
  81. FTarget: Cardinal;
  82. FWidth: Integer;
  83. FHeight: Integer;
  84. FLayer: Integer;
  85. FLevel: Integer;
  86. FTextureMipmap: cardinal;
  87. FAttachedTexture: array[0..MaxColorAttachments - 1] of TGLTexture;
  88. FDepthTexture: TGLTexture;
  89. FDRBO: TGLDepthRBO;
  90. FSRBO: TGLStencilRBO;
  91. function GetStatus: TGLFramebufferStatus;
  92. procedure SetHeight(const Value: Integer);
  93. procedure SetWidth(const Value: Integer);
  94. procedure SetLayer(const Value: Integer);
  95. procedure SetLevel(const Value: Integer);
  96. protected
  97. procedure AttachTexture(
  98. const attachment: Cardinal;
  99. const textarget: Cardinal;
  100. const texture: Cardinal;
  101. const level: TGLint;
  102. const layer: TGLint); overload;
  103. procedure ReattachTextures;
  104. public
  105. constructor Create;
  106. destructor Destroy; override;
  107. // attaches a depth rbo to the fbo
  108. // the depth buffer must have the same dimentions as the fbo
  109. procedure AttachDepthBuffer(DepthBuffer: TGLDepthRBO); overload;
  110. // detaches depth attachment from the fbo
  111. procedure DetachDepthBuffer;
  112. // attaches a stencil rbo to the fbo
  113. // the stencil buffer must have the same dimentions as the fbo
  114. procedure AttachStencilBuffer(StencilBuffer: TGLStencilRBO); overload;
  115. // detaches stencil attachment from the fbo
  116. procedure DetachStencilBuffer;
  117. // attaches a depth texture to the fbo
  118. // the depth texture must have the same dimentions as the fbo
  119. procedure AttachDepthTexture(Texture: TGLTexture); overload;
  120. procedure DetachDepthTexture;
  121. procedure AttachTexture(n: Cardinal; Texture: TGLTexture); overload;
  122. procedure DetachTexture(n: Cardinal);
  123. function GetStringStatus(out clarification: string): TGLFramebufferStatus;
  124. property Status: TGLFramebufferStatus read GetStatus;
  125. procedure Bind;
  126. procedure Unbind;
  127. procedure PreRender;
  128. procedure Render(var rci: TGLRenderContextInfo; baseObject: TGLBaseSceneObject);
  129. procedure PostRender(const PostGenerateMipmap: Boolean);
  130. property Handle: TGLFramebufferHandle read FFrameBufferHandle;
  131. property Width: Integer read FWidth write SetWidth;
  132. property Height: Integer read FHeight write SetHeight;
  133. property Layer: Integer read FLayer write SetLayer;
  134. property Level: Integer read FLevel write SetLevel;
  135. end;
  136. //-------------------------------------------------------------------------
  137. implementation
  138. //-------------------------------------------------------------------------
  139. //---------------------------------------
  140. //---------- TGLRenderbuffer
  141. //---------------------------------------
  142. constructor TGLRenderbuffer.Create;
  143. begin
  144. inherited Create;
  145. FRenderbufferHandle := TGLRenderbufferHandle.Create;
  146. FWidth := 256;
  147. FHeight := 256;
  148. end;
  149. destructor TGLRenderbuffer.Destroy;
  150. begin
  151. FRenderbufferHandle.DestroyHandle;
  152. FRenderbufferHandle.Free;
  153. inherited Destroy;
  154. end;
  155. function TGLRenderbuffer.GetHandle: Cardinal;
  156. begin
  157. if FRenderbufferHandle.Handle = 0 then
  158. FRenderbufferHandle.AllocateHandle;
  159. Result := FRenderbufferHandle.Handle;
  160. end;
  161. procedure TGLRenderbuffer.InvalidateStorage;
  162. begin
  163. FStorageValid := False;
  164. end;
  165. procedure TGLRenderbuffer.SetHeight(const Value: Integer);
  166. begin
  167. if FHeight <> Value then
  168. begin
  169. FHeight := Value;
  170. InvalidateStorage;
  171. end;
  172. end;
  173. procedure TGLRenderbuffer.SetWidth(const Value: Integer);
  174. begin
  175. if FWidth <> Value then
  176. begin
  177. FWidth := Value;
  178. InvalidateStorage;
  179. end;
  180. end;
  181. procedure TGLRenderbuffer.Bind;
  182. var
  183. internalFormat: cardinal;
  184. begin
  185. FRenderbufferHandle.AllocateHandle;
  186. FRenderbufferHandle.Bind;
  187. if not FStorageValid then
  188. begin
  189. internalFormat := GetInternalFormat;
  190. FRenderbufferHandle.SetStorage(internalFormat, FWidth, FHeight);
  191. end;
  192. end;
  193. procedure TGLRenderbuffer.Unbind;
  194. begin
  195. FRenderbufferHandle.UnBind;
  196. end;
  197. //---------------------------------
  198. //----------- TGLDepthRBO
  199. //---------------------------------
  200. constructor TGLDepthRBO.Create;
  201. begin
  202. inherited Create;
  203. FDepthPrecision := dpDefault;
  204. end;
  205. function TGLDepthRBO.GetInternalFormat: cardinal;
  206. begin
  207. case DepthPrecision of
  208. dp24bits: Result := GL_DEPTH_COMPONENT24;
  209. dp16bits: Result := GL_DEPTH_COMPONENT16;
  210. dp32bits: Result := GL_DEPTH_COMPONENT32;
  211. else
  212. // dpDefault
  213. Result := GL_DEPTH_COMPONENT24_ARB;
  214. end;
  215. end;
  216. procedure TGLDepthRBO.SetDepthPrecision(const Value: TGLDepthPrecision);
  217. begin
  218. if FDepthPrecision <> Value then
  219. begin
  220. FDepthPrecision := Value;
  221. InvalidateStorage;
  222. end;
  223. end;
  224. //-----------------------------------------
  225. //------------- TGLStencilRBO
  226. //-----------------------------------------
  227. constructor TGLStencilRBO.Create;
  228. begin
  229. inherited Create;
  230. FStencilPrecision := spDefault;
  231. end;
  232. function TGLStencilRBO.GetInternalFormat: cardinal;
  233. begin
  234. case StencilPrecision of
  235. spDefault: Result := GL_STENCIL_INDEX;
  236. sp1bit: Result := GL_STENCIL_INDEX1_EXT;
  237. sp4bits: Result := GL_STENCIL_INDEX4_EXT;
  238. sp8bits: Result := GL_STENCIL_INDEX8_EXT;
  239. sp16bits: Result := GL_STENCIL_INDEX16_EXT;
  240. else
  241. // spDefault
  242. Result := GL_STENCIL_INDEX;
  243. end;
  244. end;
  245. procedure TGLStencilRBO.SetStencilPrecision(const Value: TGLStencilPrecision);
  246. begin
  247. if FStencilPrecision <> Value then
  248. begin
  249. FStencilPrecision := Value;
  250. InvalidateStorage;
  251. end;
  252. end;
  253. //-----------------------------------------
  254. //--------------- TGLFrameBuffer
  255. //-----------------------------------------
  256. constructor TGLFrameBuffer.Create;
  257. begin
  258. inherited;
  259. FFrameBufferHandle := TGLFrameBufferHandle.Create;
  260. FWidth := 256;
  261. FHeight := 256;
  262. FLayer := 0;
  263. FLevel := 0;
  264. FTextureMipmap := 0;
  265. FTarget := GL_FRAMEBUFFER;
  266. end;
  267. destructor TGLFrameBuffer.Destroy;
  268. begin
  269. FFrameBufferHandle.DestroyHandle;
  270. FFrameBufferHandle.Free;
  271. inherited Destroy;
  272. end;
  273. procedure TGLFrameBuffer.AttachTexture(n: Cardinal; Texture: TGLTexture);
  274. var
  275. textarget: TGLTextureTarget;
  276. begin
  277. Assert(n < MaxColorAttachments);
  278. Texture.Handle;
  279. FAttachedTexture[n] := Texture;
  280. textarget := Texture.Image.NativeTextureTarget;
  281. // Store mipmaping requires
  282. if not ((Texture.MinFilter in [miNearest, miLinear])
  283. or (textarget = ttTextureRect)) then
  284. FTextureMipmap := FTextureMipmap or (1 shl n);
  285. if Texture.Image is TGLMultiSampleImage then
  286. FTextureMipmap := 0;
  287. AttachTexture(
  288. GL_COLOR_ATTACHMENT0_EXT + n,
  289. DecodeTextureTarget(textarget),
  290. Texture.Handle,
  291. FLevel, FLayer);
  292. end;
  293. procedure TGLFrameBuffer.AttachDepthBuffer(DepthBuffer: TGLDepthRBO);
  294. procedure AttachDepthRB;
  295. begin
  296. // forces initialization
  297. DepthBuffer.Bind;
  298. DepthBuffer.Unbind;
  299. gl.FramebufferRenderbuffer(FTarget, GL_DEPTH_ATTACHMENT_EXT,
  300. GL_RENDERBUFFER_EXT, DepthBuffer.Handle);
  301. end;
  302. var
  303. dp: TGLDepthPrecision;
  304. begin
  305. if Assigned(FDRBO) then
  306. DetachDepthBuffer;
  307. FDRBO := DepthBuffer;
  308. Bind;
  309. AttachDepthRB;
  310. // if default format didn't work, try something else
  311. // crude, but might work
  312. if (Status = fsUnsupported) and (DepthBuffer.DepthPrecision = dpDefault) then
  313. begin
  314. // try the other formats
  315. // best quality first
  316. for dp := high(dp) downto low(dp) do
  317. begin
  318. if dp = dpDefault then
  319. Continue;
  320. DepthBuffer.DepthPrecision := dp;
  321. AttachDepthRB;
  322. if not (Status = fsUnsupported) then
  323. Break;
  324. end;
  325. end;
  326. Status;
  327. Unbind;
  328. end;
  329. procedure TGLFrameBuffer.AttachDepthTexture(Texture: TGLTexture);
  330. begin
  331. FDepthTexture := Texture;
  332. if FDepthTexture.Image is TGLMultisampleImage then
  333. begin
  334. if not IsDepthFormat(FDepthTexture.TextureFormatEx) then
  335. begin
  336. // Force texture properties to depth compatibility
  337. FDepthTexture.TextureFormatEx := tfDEPTH_COMPONENT24;
  338. TGLMultisampleImage(FDepthTexture.Image).Width := Width;
  339. TGLMultisampleImage(FDepthTexture.Image).Height := Height;
  340. end;
  341. FTextureMipmap := 0;
  342. end
  343. else
  344. begin
  345. if not IsDepthFormat(FDepthTexture.TextureFormatEx) then
  346. begin
  347. // Force texture properties to depth compatibility
  348. FDepthTexture.ImageClassName := TGLBlankImage.ClassName;
  349. FDepthTexture.TextureFormatEx := tfDEPTH_COMPONENT24;
  350. TGLBlankImage(FDepthTexture.Image).Width := Width;
  351. TGLBlankImage(FDepthTexture.Image).Height := Height;
  352. end;
  353. if FDepthTexture.TextureFormatEx = tfDEPTH24_STENCIL8 then
  354. begin
  355. TGLBlankImage(FDepthTexture.Image).GetBitmap32.SetColorFormatDataType(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8);
  356. TGLBlankImage(FDepthTexture.Image).ColorFormat := GL_DEPTH_STENCIL;
  357. end
  358. else
  359. begin
  360. TGLBlankImage(FDepthTexture.Image).GetBitmap32.SetColorFormatDataType(GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE);
  361. TGLBlankImage(FDepthTexture.Image).ColorFormat := GL_DEPTH_COMPONENT;
  362. end;
  363. // Depth texture mipmaping
  364. if not ((FDepthTexture.MinFilter in [miNearest, miLinear])) then
  365. FTextureMipmap := FTextureMipmap or Cardinal(1 shl MaxColorAttachments);
  366. end;
  367. AttachTexture(
  368. GL_DEPTH_ATTACHMENT,
  369. DecodeTextureTarget(FDepthTexture.Image.NativeTextureTarget),
  370. FDepthTexture.Handle,
  371. FLevel,
  372. FLayer);
  373. if FDepthTexture.TextureFormatEx = tfDEPTH24_STENCIL8 then
  374. AttachTexture(
  375. GL_STENCIL_ATTACHMENT,
  376. DecodeTextureTarget(FDepthTexture.Image.NativeTextureTarget),
  377. FDepthTexture.Handle,
  378. FLevel,
  379. FLayer);
  380. end;
  381. procedure TGLFrameBuffer.DetachDepthTexture;
  382. begin
  383. if Assigned(FDepthTexture) then
  384. begin
  385. FTextureMipmap := FTextureMipmap and (not (1 shl MaxColorAttachments));
  386. AttachTexture(
  387. GL_DEPTH_ATTACHMENT,
  388. DecodeTextureTarget(FDepthTexture.Image.NativeTextureTarget),
  389. 0, 0, 0);
  390. FDepthTexture := nil;
  391. end;
  392. end;
  393. procedure TGLFrameBuffer.AttachStencilBuffer(StencilBuffer: TGLStencilRBO);
  394. procedure AttachStencilRB;
  395. begin
  396. // forces initialization
  397. StencilBuffer.Bind;
  398. StencilBuffer.Unbind;
  399. gl.FramebufferRenderbuffer(FTarget, GL_STENCIL_ATTACHMENT,
  400. GL_RENDERBUFFER_EXT, StencilBuffer.Handle);
  401. end;
  402. var
  403. sp: TGLStencilPrecision;
  404. begin
  405. if Assigned(FSRBO) then
  406. DetachStencilBuffer;
  407. FSRBO := StencilBuffer;
  408. Bind;
  409. AttachStencilRB;
  410. // if default format didn't work, try something else
  411. // crude, but might work
  412. if (Status = fsUnsupported)
  413. and (StencilBuffer.StencilPrecision = spDefault) then
  414. begin
  415. // try the other formats
  416. // best quality first
  417. for sp := high(sp) downto low(sp) do
  418. begin
  419. if sp = spDefault then
  420. Continue;
  421. StencilBuffer.StencilPrecision := sp;
  422. AttachStencilRB;
  423. if not (Status = fsUnsupported) then
  424. Break;
  425. end;
  426. end;
  427. Status;
  428. Unbind;
  429. end;
  430. procedure TGLFrameBuffer.AttachTexture(
  431. const attachment: Cardinal;
  432. const textarget: Cardinal;
  433. const texture: Cardinal;
  434. const level: TGLint;
  435. const layer: TGLint);
  436. var
  437. storeDFB: Cardinal;
  438. RC: TGLContext;
  439. begin
  440. RC := SafeCurrentGLContext;
  441. storeDFB := RC.GLStates.DrawFrameBuffer;
  442. if storeDFB <> FFrameBufferHandle.Handle then
  443. Bind;
  444. with FFrameBufferHandle do
  445. case textarget of
  446. GL_TEXTURE_1D:
  447. Attach1DTexture(FTarget, attachment, textarget, texture, level);
  448. GL_TEXTURE_2D:
  449. Attach2DTexture(FTarget, attachment, textarget, texture, level);
  450. GL_TEXTURE_RECTANGLE: // Rectangle texture can't be leveled
  451. Attach2DTexture(FTarget, attachment, textarget, texture, 0);
  452. GL_TEXTURE_3D:
  453. Attach3DTexture(FTarget, attachment, textarget, texture, level, layer);
  454. GL_TEXTURE_CUBE_MAP:
  455. Attach2DTexture(FTarget, attachment, GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer, texture, level);
  456. GL_TEXTURE_CUBE_MAP_POSITIVE_X,
  457. GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
  458. GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
  459. GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
  460. GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
  461. GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
  462. Attach2DTexture(FTarget, attachment, textarget, texture, level);
  463. GL_TEXTURE_CUBE_MAP_ARRAY,
  464. GL_TEXTURE_1D_ARRAY,
  465. GL_TEXTURE_2D_ARRAY:
  466. AttachLayer(FTarget, attachment, texture, level, layer);
  467. GL_TEXTURE_2D_MULTISAMPLE: // Multisample texture can't be leveled
  468. Attach2DTexture(FTarget, attachment, textarget, texture, 0);
  469. GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
  470. AttachLayer(FTarget, attachment, texture, 0, layer);
  471. end;
  472. if storeDFB <> FFrameBufferHandle.Handle then
  473. RC.GLStates.SetFrameBuffer(storeDFB);
  474. end;
  475. procedure TGLFrameBuffer.Bind;
  476. begin
  477. if Handle.IsDataNeedUpdate then
  478. ReattachTextures
  479. else
  480. Handle.Bind;
  481. end;
  482. procedure TGLFrameBuffer.Unbind;
  483. begin
  484. FFrameBufferHandle.UnBind;
  485. end;
  486. procedure TGLFrameBuffer.DetachTexture(n: Cardinal);
  487. begin
  488. // textarget ignored when binding 0
  489. if Assigned(FAttachedTexture[n]) then
  490. begin
  491. Bind;
  492. AttachTexture(
  493. GL_COLOR_ATTACHMENT0 + n,
  494. GL_TEXTURE_2D, // target does not matter
  495. 0, 0, 0);
  496. FTextureMipmap := FTextureMipmap and (not (1 shl n));
  497. FAttachedTexture[n] := nil;
  498. Unbind;
  499. end;
  500. end;
  501. procedure TGLFrameBuffer.DetachDepthBuffer;
  502. begin
  503. Bind;
  504. gl.FramebufferRenderbuffer(FTarget, GL_DEPTH_ATTACHMENT,
  505. GL_RENDERBUFFER, 0);
  506. Unbind;
  507. FDRBO := nil;
  508. end;
  509. procedure TGLFrameBuffer.DetachStencilBuffer;
  510. begin
  511. Bind;
  512. gl.FramebufferRenderbuffer(FTarget, GL_STENCIL_ATTACHMENT,
  513. GL_RENDERBUFFER, 0);
  514. Unbind;
  515. FSRBO := nil;
  516. end;
  517. function TGLFrameBuffer.GetStatus: TGLFramebufferStatus;
  518. var
  519. status: cardinal;
  520. begin
  521. status := gl.CheckFramebufferStatus(FTarget);
  522. case status of
  523. GL_FRAMEBUFFER_COMPLETE_EXT: Result := fsComplete;
  524. GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: Result := fsIncompleteAttachment;
  525. GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: Result :=
  526. fsIncompleteMissingAttachment;
  527. GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT: Result :=
  528. fsIncompleteDuplicateAttachment;
  529. GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: Result := fsIncompleteDimensions;
  530. GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: Result := fsIncompleteFormats;
  531. GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: Result := fsIncompleteDrawBuffer;
  532. GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: Result := fsIncompleteReadBuffer;
  533. GL_FRAMEBUFFER_UNSUPPORTED_EXT: Result := fsUnsupported;
  534. GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: Result := fsIncompleteMultisample;
  535. else
  536. Result := fsStatusError;
  537. end;
  538. end;
  539. function TGLFrameBuffer.GetStringStatus(out clarification: string):
  540. TGLFramebufferStatus;
  541. const
  542. cFBOStatus: array[TGLFramebufferStatus] of string = (
  543. 'Complete',
  544. 'Incomplete attachment',
  545. 'Incomplete missing attachment',
  546. 'Incomplete duplicate attachment',
  547. 'Incomplete dimensions',
  548. 'Incomplete formats',
  549. 'Incomplete draw buffer',
  550. 'Incomplete read buffer',
  551. 'Unsupported',
  552. 'Incomplite multisample',
  553. 'Status Error');
  554. begin
  555. Result := GetStatus;
  556. clarification := cFBOStatus[Result];
  557. end;
  558. procedure TGLFrameBuffer.PostRender(const PostGenerateMipmap: Boolean);
  559. var
  560. n: Integer;
  561. textarget: TGLTextureTarget;
  562. begin
  563. if (FTextureMipmap > 0) and PostGenerateMipmap then
  564. begin
  565. for n := 0 to MaxColorAttachments - 1 do
  566. if Assigned(FAttachedTexture[n]) then
  567. begin
  568. if FTextureMipmap and (1 shl n) = 0 then
  569. Continue;
  570. textarget := FAttachedTexture[n].Image.NativeTextureTarget;
  571. with FFrameBufferHandle.RenderingContext.GLStates do
  572. TextureBinding[ActiveTexture, textarget] :=
  573. FAttachedTexture[n].Handle;
  574. gl.GenerateMipmap(DecodeTextureTarget(textarget));
  575. end;
  576. end;
  577. end;
  578. procedure TGLFrameBuffer.PreRender;
  579. begin
  580. end;
  581. procedure TGLFrameBuffer.Render(var rci: TGLRenderContextInfo; baseObject:
  582. TGLBaseSceneObject);
  583. var
  584. backColor: TColorVector;
  585. buffer: TGLSceneBuffer;
  586. begin
  587. Bind;
  588. Assert(Status = fsComplete, 'Framebuffer not complete');
  589. buffer := TGLSceneBuffer(rci.buffer);
  590. backColor := ConvertWinColor(buffer.BackgroundColor);
  591. gl.ClearColor(backColor.X, backColor.Y, backColor.Z,
  592. buffer.BackgroundAlpha);
  593. rci.GLStates.SetColorMask(cAllColorComponents);
  594. rci.GLStates.DepthWriteMask := True;
  595. gl.Clear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  596. baseObject.Render(rci);
  597. Unbind;
  598. end;
  599. procedure TGLFrameBuffer.SetHeight(const Value: Integer);
  600. begin
  601. if FHeight <> Value then
  602. begin
  603. FHeight := Value;
  604. end;
  605. end;
  606. procedure TGLFrameBuffer.SetWidth(const Value: Integer);
  607. begin
  608. if FWidth <> Value then
  609. begin
  610. FWidth := Value;
  611. end;
  612. end;
  613. procedure TGLFrameBuffer.ReattachTextures;
  614. var
  615. n: Integer;
  616. bEmpty: Boolean;
  617. s: String;
  618. begin
  619. Handle.AllocateHandle;
  620. Handle.Bind;
  621. // Reattach layered textures
  622. bEmpty := True;
  623. for n := 0 to MaxColorAttachments - 1 do
  624. if Assigned(FAttachedTexture[n]) then
  625. begin
  626. AttachTexture(
  627. GL_COLOR_ATTACHMENT0_EXT + n,
  628. DecodeTextureTarget(FAttachedTexture[n].Image.NativeTextureTarget),
  629. FAttachedTexture[n].Handle,
  630. FLevel,
  631. FLayer);
  632. bEmpty := False;
  633. end;
  634. if Assigned(FDepthTexture) then
  635. begin
  636. AttachTexture(
  637. GL_DEPTH_ATTACHMENT,
  638. DecodeTextureTarget(FDepthTexture.Image.NativeTextureTarget),
  639. FDepthTexture.Handle,
  640. FLevel,
  641. FLayer);
  642. bEmpty := False;
  643. end;
  644. if Assigned(FDRBO) then
  645. begin
  646. FDRBO.Bind;
  647. FDRBO.Unbind;
  648. gl.FramebufferRenderbuffer(FTarget, GL_DEPTH_ATTACHMENT_EXT,
  649. GL_RENDERBUFFER_EXT, FDRBO.Handle);
  650. bEmpty := False;
  651. end;
  652. if Assigned(FSRBO) then
  653. begin
  654. FSRBO.Bind;
  655. FSRBO.Unbind;
  656. gl.FramebufferRenderbuffer(FTarget, GL_STENCIL_ATTACHMENT,
  657. GL_RENDERBUFFER_EXT, FSRBO.Handle);
  658. bEmpty := False;
  659. end;
  660. if not bEmpty and (GetStringStatus(s) <> fsComplete) then
  661. GLSLogger.LogErrorFmt('Framebuffer error: %s. Deactivated', [s]);
  662. Handle.NotifyDataUpdated;
  663. end;
  664. procedure TGLFrameBuffer.SetLayer(const Value: Integer);
  665. var
  666. RC: TGLContext;
  667. begin
  668. if FLayer <> Value then
  669. begin
  670. FLayer := Value;
  671. RC := CurrentGLContext;
  672. if Assigned(RC) then
  673. begin
  674. if RC.GLStates.DrawFrameBuffer = FFrameBufferHandle.Handle then
  675. ReattachTextures;
  676. end;
  677. end;
  678. end;
  679. procedure TGLFrameBuffer.SetLevel(const Value: Integer);
  680. var
  681. RC: TGLContext;
  682. begin
  683. if FLevel <> Value then
  684. begin
  685. FLevel := Value;
  686. RC := CurrentGLContext;
  687. if Assigned(RC) then
  688. begin
  689. if RC.GLStates.DrawFrameBuffer = FFrameBufferHandle.Handle then
  690. ReattachTextures;
  691. end;
  692. end;
  693. end;
  694. end.