GXS.FBO.pas 20 KB

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