GLS.FBORenderer.pas 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644
  1. //
  2. // The graphics engine GLScene
  3. //
  4. unit GLS.FBORenderer;
  5. (* Implements FBO support *)
  6. interface
  7. {$I Stage.Defines.inc}
  8. uses
  9. Winapi.OpenGL,
  10. Winapi.OpenGLext,
  11. System.Classes,
  12. System.SysUtils,
  13. Stage.OpenGLTokens,
  14. Stage.TextureFormat,
  15. Stage.VectorTypes,
  16. Stage.VectorGeometry,
  17. GLS.PersistentClasses,
  18. Stage.PipelineTransform,
  19. GLS.Scene,
  20. GLS.Texture,
  21. GLS.Context,
  22. GLS.Color,
  23. GLS.Material,
  24. GLS.RenderContextInfo,
  25. GLS.State,
  26. GLS.MultiSampleImage,
  27. Stage.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. //----------------------- GLS.FBORenderer classes --------------------------
  137. TGLEnabledRenderBuffer = (erbDepth, erbStencil);
  138. TGLEnabledRenderBuffers = set of TGLEnabledRenderBuffer;
  139. TGLFBOTargetVisibility = (tvDefault, tvFBOOnly);
  140. TGLFBOClearOption = (coColorBufferClear, coDepthBufferClear,
  141. coStencilBufferClear, coUseBufferBackground);
  142. TGLFBOClearOptions = set of TGLFBOClearOption;
  143. TGLTextureArray = array of TGLTexture;
  144. TSetTextureTargetsEvent = procedure(Sender : TObject;
  145. var colorTexs : TGLTextureArray) of object;
  146. TGLFBORenderer = class(TGLBaseSceneObject, IGLMaterialLibrarySupported)
  147. private
  148. FFbo: TGLFrameBuffer;
  149. FDepthRBO: TGLDepthRBO;
  150. FStencilRBO: TGLStencilRBO;
  151. FColorAttachment: Integer;
  152. FRendering: Boolean;
  153. FHasColor: Boolean;
  154. FHasDepth: Boolean;
  155. FHasStencil: Boolean;
  156. FMaterialLibrary: TGLMaterialLibrary;
  157. FColorTextureName: TGLLibMaterialName;
  158. FDepthTextureName: TGLLibMaterialName;
  159. FWidth: Integer;
  160. FHeight: Integer;
  161. FForceTextureDimensions: Boolean;
  162. FStencilPrecision: TGLStencilPrecision;
  163. FRootObject: TGLBaseSceneObject;
  164. FRootVisible: Boolean;
  165. FCamera: TGLCamera;
  166. FEnabledRenderBuffers: TGLEnabledRenderBuffers;
  167. FTargetVisibility: TGLFBOTargetVisibility;
  168. FBeforeRender: TGLDirectRenderEvent;
  169. FPostInitialize: TNotifyEvent;
  170. FAfterRender: TGLDirectRenderEvent;
  171. FPreInitialize: TNotifyEvent;
  172. FBackgroundColor: TGLColor;
  173. FClearOptions: TGLFBOClearOptions;
  174. FAspect: Single;
  175. FSceneScaleFactor: Single;
  176. FUseLibraryAsMultiTarget: Boolean;
  177. FPostGenerateMipmap: Boolean;
  178. FMaxSize: Integer;
  179. FMaxAttachment: Integer;
  180. FStoreCamera: array[0..2] of TGLVector;
  181. FOnSetTextureTargets: TSetTextureTargetsEvent;
  182. // implementing IGLMaterialLibrarySupported
  183. function GetMaterialLibrary: TGLAbstractMaterialLibrary;
  184. procedure SetMaterialLibrary(const Value: TGLAbstractMaterialLibrary);
  185. procedure SetDepthTextureName(const Value: TGLLibMaterialName);
  186. procedure SetColorTextureName(const Value: TGLLibMaterialName);
  187. procedure SetForceTextureDimentions(const Value: Boolean);
  188. procedure SetHeight(Value: Integer);
  189. procedure SetWidth(Value: Integer);
  190. procedure SetLayer(const Value: Integer);
  191. function GetLayer: Integer;
  192. procedure SetLevel(const Value: Integer);
  193. function GetLevel: Integer;
  194. procedure SetStencilPrecision(const Value: TGLStencilPrecision);
  195. procedure SetRootObject(const Value: TGLBaseSceneObject);
  196. function GetViewport: TRectangle;
  197. procedure SetCamera(const Value: TGLCamera);
  198. procedure SetEnabledRenderBuffers(const Value: TGLEnabledRenderBuffers);
  199. procedure SetTargetVisibility(const Value: TGLFBOTargetVisibility);
  200. procedure SetBackgroundColor(const Value: TGLColor);
  201. function StoreSceneScaleFactor: Boolean;
  202. function StoreAspect: Boolean;
  203. procedure SetUseLibraryAsMultiTarget(Value: Boolean);
  204. procedure SetPostGenerateMipmap(const Value: Boolean);
  205. protected
  206. procedure Notification(AComponent: TComponent;
  207. Operation: TOperation); override;
  208. procedure Initialize;
  209. procedure ForceDimensions(Texture: TGLTexture);
  210. procedure RenderToFBO(var ARci: TGLRenderContextInfo);
  211. procedure ApplyCamera(var ARci: TGLRenderContextInfo);
  212. procedure UnApplyCamera(var ARci: TGLRenderContextInfo);
  213. procedure DoBeforeRender(var ARci: TGLRenderContextInfo);
  214. procedure DoAfterRender(var ARci: TGLRenderContextInfo);
  215. procedure DoPreInitialize;
  216. procedure DoPostInitialize;
  217. property HasColor: Boolean read FHasColor;
  218. property HasDepth: Boolean read FHasDepth;
  219. property HasStencil: Boolean read FHasStencil;
  220. property Viewport: TRectangle read GetViewport;
  221. public
  222. constructor Create(AOwner: TComponent); override;
  223. destructor Destroy; override;
  224. procedure DoRender(var ARci: TGLRenderContextInfo; ARenderSelf: Boolean;
  225. ARenderChildren: Boolean); override;
  226. (* Layer (also cube map face) is activated only on
  227. the volume textures, texture array and cube map.
  228. You can select the layer during the drawing to. *)
  229. property Layer: Integer read GetLayer write SetLayer;
  230. // Mipmap Level where will be rendering
  231. property Level: Integer read GetLevel write SetLevel;
  232. published
  233. property Active: Boolean read GetVisible write SetVisible default True;
  234. property PickableTarget: Boolean read GetPickable write SetPickable default False;
  235. (* Force texture dimensions when initializing
  236. only works with TGLBlankImage and TGLFloatDataImage, otherwise does nothing *)
  237. property ForceTextureDimensions: Boolean read FForceTextureDimensions
  238. write SetForceTextureDimentions default True;
  239. property Width: Integer read FWidth write SetWidth default 256;
  240. property Height: Integer read FHeight write SetHeight default 256;
  241. property Aspect: Single read FAspect write FAspect stored StoreAspect;
  242. property ColorTextureName: TGLLibMaterialName read FColorTextureName
  243. write SetColorTextureName;
  244. property DepthTextureName: TGLLibMaterialName read FDepthTextureName
  245. write SetDepthTextureName;
  246. property MaterialLibrary: TGLAbstractMaterialLibrary read GetMaterialLibrary
  247. write SetMaterialLibrary;
  248. property BackgroundColor: TGLColor read FBackgroundColor write SetBackgroundColor;
  249. property ClearOptions: TGLFBOClearOptions read FClearOptions
  250. write FClearOptions;
  251. (* Camera used for rendering to the FBO
  252. if not assigned, use the active view's camera *)
  253. property Camera: TGLCamera read FCamera write SetCamera;
  254. (* Adjust the scene scale of the camera so that the rendering
  255. becomes independent of the width of the fbo renderer
  256. 0 = disabled *)
  257. property SceneScaleFactor: Single read FSceneScaleFactor
  258. write FSceneScaleFactor stored StoreSceneScaleFactor;
  259. (* Root object used when rendering to the FBO
  260. if not assigned, uses itself as root and renders the child objects to the FBO *)
  261. property RootObject: TGLBaseSceneObject read FRootObject
  262. write SetRootObject;
  263. (* Determines if target is rendered to FBO only or rendered normally
  264. in FBO only mode, if RootObject is assigned, the RootObject's Visible flag is modified
  265. in default mode, if RootObject is not assigned, children are rendered normally after being
  266. rendered to the FBO *)
  267. property TargetVisibility: TGLFBOTargetVisibility read FTargetVisibility
  268. write SetTargetVisibility default tvDefault;
  269. // Enables the use of a render buffer if a texture is not assigned
  270. property EnabledRenderBuffers: TGLEnabledRenderBuffers
  271. read FEnabledRenderBuffers write SetEnabledRenderBuffers;
  272. // use stencil buffer
  273. property StencilPrecision: TGLStencilPrecision read FStencilPrecision
  274. write SetStencilPrecision default spDefault;
  275. // called before rendering to the FBO
  276. property BeforeRender: TGLDirectRenderEvent read FBeforeRender write FBeforeRender;
  277. // called after the rendering to the FBO
  278. property AfterRender: TGLDirectRenderEvent read FAfterRender write FAfterRender;
  279. (* Called before the FBO is initialized
  280. the FBO is bound before calling this event *)
  281. property PreInitialize: TNotifyEvent read FPreInitialize write FPreInitialize;
  282. (* Called after the FBO is initialized, but before any rendering
  283. the FBO is bound before calling this event *)
  284. property PostInitialize: TNotifyEvent read FPostInitialize write FPostInitialize;
  285. property UseLibraryAsMultiTarget: Boolean read FUseLibraryAsMultiTarget
  286. write SetUseLibraryAsMultiTarget default False;
  287. (* Control mipmap generation after rendering
  288. texture must have MinFilter with mipmaping *)
  289. property PostGenerateMipmap: Boolean read FPostGenerateMipmap
  290. write SetPostGenerateMipmap default True;
  291. (* Allows multiTargeting to different texture sources instead of all coming
  292. from one single MatLib with UseLibraryAsMultiTarget. OnSetTextureTargets
  293. overrides the other method of setting target textures via the MaterialLibrary,
  294. ColorTextureName and DepthTextureName propertes *)
  295. property OnSetTextureTargets: TSetTextureTargetsEvent read FOnSetTextureTargets
  296. write FOnSetTextureTargets;
  297. end;
  298. //======================================================================
  299. implementation
  300. //======================================================================
  301. //---------------------------------------
  302. //---------- TGLRenderbuffer
  303. //---------------------------------------
  304. constructor TGLRenderbuffer.Create;
  305. begin
  306. inherited Create;
  307. FRenderbufferHandle := TGLRenderbufferHandle.Create;
  308. FWidth := 256;
  309. FHeight := 256;
  310. end;
  311. destructor TGLRenderbuffer.Destroy;
  312. begin
  313. FRenderbufferHandle.DestroyHandle;
  314. FRenderbufferHandle.Free;
  315. inherited Destroy;
  316. end;
  317. function TGLRenderbuffer.GetHandle: Cardinal;
  318. begin
  319. if FRenderbufferHandle.Handle = 0 then
  320. FRenderbufferHandle.AllocateHandle;
  321. Result := FRenderbufferHandle.Handle;
  322. end;
  323. procedure TGLRenderbuffer.InvalidateStorage;
  324. begin
  325. FStorageValid := False;
  326. end;
  327. procedure TGLRenderbuffer.SetHeight(const Value: Integer);
  328. begin
  329. if FHeight <> Value then
  330. begin
  331. FHeight := Value;
  332. InvalidateStorage;
  333. end;
  334. end;
  335. procedure TGLRenderbuffer.SetWidth(const Value: Integer);
  336. begin
  337. if FWidth <> Value then
  338. begin
  339. FWidth := Value;
  340. InvalidateStorage;
  341. end;
  342. end;
  343. procedure TGLRenderbuffer.Bind;
  344. var
  345. internalFormat: cardinal;
  346. begin
  347. FRenderbufferHandle.AllocateHandle;
  348. FRenderbufferHandle.Bind;
  349. if not FStorageValid then
  350. begin
  351. internalFormat := GetInternalFormat;
  352. FRenderbufferHandle.SetStorage(internalFormat, FWidth, FHeight);
  353. end;
  354. end;
  355. procedure TGLRenderbuffer.Unbind;
  356. begin
  357. FRenderbufferHandle.UnBind;
  358. end;
  359. //---------------------------------
  360. //----------- TGLDepthRBO
  361. //---------------------------------
  362. constructor TGLDepthRBO.Create;
  363. begin
  364. inherited Create;
  365. FDepthPrecision := dpDefault;
  366. end;
  367. function TGLDepthRBO.GetInternalFormat: cardinal;
  368. begin
  369. case DepthPrecision of
  370. dp24bits: Result := GL_DEPTH_COMPONENT24;
  371. dp16bits: Result := GL_DEPTH_COMPONENT16;
  372. dp32bits: Result := GL_DEPTH_COMPONENT32;
  373. else
  374. // dpDefault
  375. Result := GL_DEPTH_COMPONENT24_ARB;
  376. end;
  377. end;
  378. procedure TGLDepthRBO.SetDepthPrecision(const Value: TGLDepthPrecision);
  379. begin
  380. if FDepthPrecision <> Value then
  381. begin
  382. FDepthPrecision := Value;
  383. InvalidateStorage;
  384. end;
  385. end;
  386. //-----------------------------------------
  387. //------------- TGLStencilRBO
  388. //-----------------------------------------
  389. constructor TGLStencilRBO.Create;
  390. begin
  391. inherited Create;
  392. FStencilPrecision := spDefault;
  393. end;
  394. function TGLStencilRBO.GetInternalFormat: cardinal;
  395. begin
  396. case StencilPrecision of
  397. spDefault: Result := GL_STENCIL_INDEX;
  398. sp1bit: Result := GL_STENCIL_INDEX1_EXT;
  399. sp4bits: Result := GL_STENCIL_INDEX4_EXT;
  400. sp8bits: Result := GL_STENCIL_INDEX8_EXT;
  401. sp16bits: Result := GL_STENCIL_INDEX16_EXT;
  402. else
  403. // spDefault
  404. Result := GL_STENCIL_INDEX;
  405. end;
  406. end;
  407. procedure TGLStencilRBO.SetStencilPrecision(const Value: TGLStencilPrecision);
  408. begin
  409. if FStencilPrecision <> Value then
  410. begin
  411. FStencilPrecision := Value;
  412. InvalidateStorage;
  413. end;
  414. end;
  415. //-----------------------------------------
  416. //--------------- TGLFrameBuffer
  417. //-----------------------------------------
  418. constructor TGLFrameBuffer.Create;
  419. begin
  420. inherited;
  421. FFrameBufferHandle := TGLFrameBufferHandle.Create;
  422. FWidth := 256;
  423. FHeight := 256;
  424. FLayer := 0;
  425. FLevel := 0;
  426. FTextureMipmap := 0;
  427. FTarget := GL_FRAMEBUFFER;
  428. end;
  429. destructor TGLFrameBuffer.Destroy;
  430. begin
  431. FFrameBufferHandle.DestroyHandle;
  432. FFrameBufferHandle.Free;
  433. inherited Destroy;
  434. end;
  435. procedure TGLFrameBuffer.AttachTexture(n: Cardinal; Texture: TGLTexture);
  436. var
  437. textarget: TGLTextureTarget;
  438. begin
  439. Assert(n < MaxColorAttachments);
  440. Texture.Handle;
  441. FAttachedTexture[n] := Texture;
  442. textarget := Texture.Image.NativeTextureTarget;
  443. // Store mipmaping requires
  444. if not ((Texture.MinFilter in [miNearest, miLinear])
  445. or (textarget = ttTextureRect)) then
  446. FTextureMipmap := FTextureMipmap or (1 shl n);
  447. if Texture.Image is TGLMultiSampleImage then
  448. FTextureMipmap := 0;
  449. AttachTexture(
  450. GL_COLOR_ATTACHMENT0_EXT + n,
  451. DecodeTextureTarget(textarget),
  452. Texture.Handle,
  453. FLevel, FLayer);
  454. end;
  455. procedure TGLFrameBuffer.AttachDepthBuffer(DepthBuffer: TGLDepthRBO);
  456. procedure AttachDepthRB;
  457. begin
  458. // forces initialization
  459. DepthBuffer.Bind;
  460. DepthBuffer.Unbind;
  461. gl.FramebufferRenderbuffer(FTarget, GL_DEPTH_ATTACHMENT_EXT,
  462. GL_RENDERBUFFER_EXT, DepthBuffer.Handle);
  463. end;
  464. var
  465. dp: TGLDepthPrecision;
  466. begin
  467. if Assigned(FDRBO) then
  468. DetachDepthBuffer;
  469. FDRBO := DepthBuffer;
  470. Bind;
  471. AttachDepthRB;
  472. // if default format didn't work, try something else
  473. // crude, but might work
  474. if (Status = fsUnsupported) and (DepthBuffer.DepthPrecision = dpDefault) then
  475. begin
  476. // try the other formats
  477. // best quality first
  478. for dp := high(dp) downto low(dp) do
  479. begin
  480. if dp = dpDefault then
  481. Continue;
  482. DepthBuffer.DepthPrecision := dp;
  483. AttachDepthRB;
  484. if not (Status = fsUnsupported) then
  485. Break;
  486. end;
  487. end;
  488. Status;
  489. Unbind;
  490. end;
  491. procedure TGLFrameBuffer.AttachDepthTexture(Texture: TGLTexture);
  492. begin
  493. FDepthTexture := Texture;
  494. if FDepthTexture.Image is TGLMultisampleImage then
  495. begin
  496. if not IsDepthFormat(FDepthTexture.TextureFormatEx) then
  497. begin
  498. // Force texture properties to depth compatibility
  499. FDepthTexture.TextureFormatEx := tfDEPTH_COMPONENT24;
  500. TGLMultisampleImage(FDepthTexture.Image).Width := Width;
  501. TGLMultisampleImage(FDepthTexture.Image).Height := Height;
  502. end;
  503. FTextureMipmap := 0;
  504. end
  505. else
  506. begin
  507. if not IsDepthFormat(FDepthTexture.TextureFormatEx) then
  508. begin
  509. // Force texture properties to depth compatibility
  510. FDepthTexture.ImageClassName := TGLBlankImage.ClassName;
  511. FDepthTexture.TextureFormatEx := tfDEPTH_COMPONENT24;
  512. TGLBlankImage(FDepthTexture.Image).Width := Width;
  513. TGLBlankImage(FDepthTexture.Image).Height := Height;
  514. end;
  515. if FDepthTexture.TextureFormatEx = tfDEPTH24_STENCIL8 then
  516. begin
  517. TGLBlankImage(FDepthTexture.Image).GetBitmap32.SetColorFormatDataType(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8);
  518. TGLBlankImage(FDepthTexture.Image).ColorFormat := GL_DEPTH_STENCIL;
  519. end
  520. else
  521. begin
  522. TGLBlankImage(FDepthTexture.Image).GetBitmap32.SetColorFormatDataType(GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE);
  523. TGLBlankImage(FDepthTexture.Image).ColorFormat := GL_DEPTH_COMPONENT;
  524. end;
  525. // Depth texture mipmaping
  526. if not ((FDepthTexture.MinFilter in [miNearest, miLinear])) then
  527. FTextureMipmap := FTextureMipmap or Cardinal(1 shl MaxColorAttachments);
  528. end;
  529. AttachTexture(
  530. GL_DEPTH_ATTACHMENT,
  531. DecodeTextureTarget(FDepthTexture.Image.NativeTextureTarget),
  532. FDepthTexture.Handle,
  533. FLevel,
  534. FLayer);
  535. if FDepthTexture.TextureFormatEx = tfDEPTH24_STENCIL8 then
  536. AttachTexture(
  537. GL_STENCIL_ATTACHMENT,
  538. DecodeTextureTarget(FDepthTexture.Image.NativeTextureTarget),
  539. FDepthTexture.Handle,
  540. FLevel,
  541. FLayer);
  542. end;
  543. procedure TGLFrameBuffer.DetachDepthTexture;
  544. begin
  545. if Assigned(FDepthTexture) then
  546. begin
  547. FTextureMipmap := FTextureMipmap and (not (1 shl MaxColorAttachments));
  548. AttachTexture(
  549. GL_DEPTH_ATTACHMENT,
  550. DecodeTextureTarget(FDepthTexture.Image.NativeTextureTarget),
  551. 0, 0, 0);
  552. FDepthTexture := nil;
  553. end;
  554. end;
  555. procedure TGLFrameBuffer.AttachStencilBuffer(StencilBuffer: TGLStencilRBO);
  556. procedure AttachStencilRB;
  557. begin
  558. // forces initialization
  559. StencilBuffer.Bind;
  560. StencilBuffer.Unbind;
  561. gl.FramebufferRenderbuffer(FTarget, GL_STENCIL_ATTACHMENT,
  562. GL_RENDERBUFFER_EXT, StencilBuffer.Handle);
  563. end;
  564. var
  565. sp: TGLStencilPrecision;
  566. begin
  567. if Assigned(FSRBO) then
  568. DetachStencilBuffer;
  569. FSRBO := StencilBuffer;
  570. Bind;
  571. AttachStencilRB;
  572. // if default format didn't work, try something else
  573. // crude, but might work
  574. if (Status = fsUnsupported)
  575. and (StencilBuffer.StencilPrecision = spDefault) then
  576. begin
  577. // try the other formats
  578. // best quality first
  579. for sp := high(sp) downto low(sp) do
  580. begin
  581. if sp = spDefault then
  582. Continue;
  583. StencilBuffer.StencilPrecision := sp;
  584. AttachStencilRB;
  585. if not (Status = fsUnsupported) then
  586. Break;
  587. end;
  588. end;
  589. Status;
  590. Unbind;
  591. end;
  592. procedure TGLFrameBuffer.AttachTexture(
  593. const attachment: Cardinal;
  594. const textarget: Cardinal;
  595. const texture: Cardinal;
  596. const level: TGLint;
  597. const layer: TGLint);
  598. var
  599. storeDFB: Cardinal;
  600. RC: TGLContext;
  601. begin
  602. RC := SafeCurrentGLContext;
  603. storeDFB := RC.GLStates.DrawFrameBuffer;
  604. if storeDFB <> FFrameBufferHandle.Handle then
  605. Bind;
  606. with FFrameBufferHandle do
  607. case textarget of
  608. GL_TEXTURE_1D:
  609. Attach1DTexture(FTarget, attachment, textarget, texture, level);
  610. GL_TEXTURE_2D:
  611. Attach2DTexture(FTarget, attachment, textarget, texture, level);
  612. GL_TEXTURE_RECTANGLE: // Rectangle texture can't be leveled
  613. Attach2DTexture(FTarget, attachment, textarget, texture, 0);
  614. GL_TEXTURE_3D:
  615. Attach3DTexture(FTarget, attachment, textarget, texture, level, layer);
  616. GL_TEXTURE_CUBE_MAP:
  617. Attach2DTexture(FTarget, attachment, GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer, texture, level);
  618. GL_TEXTURE_CUBE_MAP_POSITIVE_X,
  619. GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
  620. GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
  621. GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
  622. GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
  623. GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
  624. Attach2DTexture(FTarget, attachment, textarget, texture, level);
  625. GL_TEXTURE_CUBE_MAP_ARRAY,
  626. GL_TEXTURE_1D_ARRAY,
  627. GL_TEXTURE_2D_ARRAY:
  628. AttachLayer(FTarget, attachment, texture, level, layer);
  629. GL_TEXTURE_2D_MULTISAMPLE: // Multisample texture can't be leveled
  630. Attach2DTexture(FTarget, attachment, textarget, texture, 0);
  631. GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
  632. AttachLayer(FTarget, attachment, texture, 0, layer);
  633. end;
  634. if storeDFB <> FFrameBufferHandle.Handle then
  635. RC.GLStates.SetFrameBuffer(storeDFB);
  636. end;
  637. procedure TGLFrameBuffer.Bind;
  638. begin
  639. if Handle.IsDataNeedUpdate then
  640. ReattachTextures
  641. else
  642. Handle.Bind;
  643. end;
  644. procedure TGLFrameBuffer.Unbind;
  645. begin
  646. FFrameBufferHandle.UnBind;
  647. end;
  648. procedure TGLFrameBuffer.DetachTexture(n: Cardinal);
  649. begin
  650. // textarget ignored when binding 0
  651. if Assigned(FAttachedTexture[n]) then
  652. begin
  653. Bind;
  654. AttachTexture(
  655. GL_COLOR_ATTACHMENT0 + n,
  656. GL_TEXTURE_2D, // target does not matter
  657. 0, 0, 0);
  658. FTextureMipmap := FTextureMipmap and (not (1 shl n));
  659. FAttachedTexture[n] := nil;
  660. Unbind;
  661. end;
  662. end;
  663. procedure TGLFrameBuffer.DetachDepthBuffer;
  664. begin
  665. Bind;
  666. gl.FramebufferRenderbuffer(FTarget, GL_DEPTH_ATTACHMENT,
  667. GL_RENDERBUFFER, 0);
  668. Unbind;
  669. FDRBO := nil;
  670. end;
  671. procedure TGLFrameBuffer.DetachStencilBuffer;
  672. begin
  673. Bind;
  674. gl.FramebufferRenderbuffer(FTarget, GL_STENCIL_ATTACHMENT,
  675. GL_RENDERBUFFER, 0);
  676. Unbind;
  677. FSRBO := nil;
  678. end;
  679. function TGLFrameBuffer.GetStatus: TGLFramebufferStatus;
  680. var
  681. status: cardinal;
  682. begin
  683. status := gl.CheckFramebufferStatus(FTarget);
  684. case status of
  685. GL_FRAMEBUFFER_COMPLETE_EXT: Result := fsComplete;
  686. GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: Result := fsIncompleteAttachment;
  687. GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: Result :=
  688. fsIncompleteMissingAttachment;
  689. GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT: Result :=
  690. fsIncompleteDuplicateAttachment;
  691. GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: Result := fsIncompleteDimensions;
  692. GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: Result := fsIncompleteFormats;
  693. GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: Result := fsIncompleteDrawBuffer;
  694. GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: Result := fsIncompleteReadBuffer;
  695. GL_FRAMEBUFFER_UNSUPPORTED_EXT: Result := fsUnsupported;
  696. GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: Result := fsIncompleteMultisample;
  697. else
  698. Result := fsStatusError;
  699. end;
  700. end;
  701. function TGLFrameBuffer.GetStringStatus(out clarification: string):
  702. TGLFramebufferStatus;
  703. const
  704. cFBOStatus: array[TGLFramebufferStatus] of string = (
  705. 'Complete',
  706. 'Incomplete attachment',
  707. 'Incomplete missing attachment',
  708. 'Incomplete duplicate attachment',
  709. 'Incomplete dimensions',
  710. 'Incomplete formats',
  711. 'Incomplete draw buffer',
  712. 'Incomplete read buffer',
  713. 'Unsupported',
  714. 'Incomplite multisample',
  715. 'Status Error');
  716. begin
  717. Result := GetStatus;
  718. clarification := cFBOStatus[Result];
  719. end;
  720. procedure TGLFrameBuffer.PostRender(const PostGenerateMipmap: Boolean);
  721. var
  722. n: Integer;
  723. textarget: TGLTextureTarget;
  724. begin
  725. if (FTextureMipmap > 0) and PostGenerateMipmap then
  726. begin
  727. for n := 0 to MaxColorAttachments - 1 do
  728. if Assigned(FAttachedTexture[n]) then
  729. begin
  730. if FTextureMipmap and (1 shl n) = 0 then
  731. Continue;
  732. textarget := FAttachedTexture[n].Image.NativeTextureTarget;
  733. with FFrameBufferHandle.RenderingContext.GLStates do
  734. TextureBinding[ActiveTexture, textarget] :=
  735. FAttachedTexture[n].Handle;
  736. gl.GenerateMipmap(DecodeTextureTarget(textarget));
  737. end;
  738. end;
  739. end;
  740. procedure TGLFrameBuffer.PreRender;
  741. begin
  742. end;
  743. procedure TGLFrameBuffer.Render(var rci: TGLRenderContextInfo; baseObject:
  744. TGLBaseSceneObject);
  745. var
  746. backColor: TGLColorVector;
  747. buffer: TGLSceneBuffer;
  748. begin
  749. Bind;
  750. Assert(Status = fsComplete, 'Framebuffer not complete');
  751. buffer := TGLSceneBuffer(rci.buffer);
  752. backColor := ConvertWinColor(buffer.BackgroundColor);
  753. gl.ClearColor(backColor.X, backColor.Y, backColor.Z,
  754. buffer.BackgroundAlpha);
  755. rci.GLStates.SetColorMask(cAllColorComponents);
  756. rci.GLStates.DepthWriteMask := True;
  757. gl.Clear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  758. baseObject.Render(rci);
  759. Unbind;
  760. end;
  761. procedure TGLFrameBuffer.SetHeight(const Value: Integer);
  762. begin
  763. if FHeight <> Value then
  764. begin
  765. FHeight := Value;
  766. end;
  767. end;
  768. procedure TGLFrameBuffer.SetWidth(const Value: Integer);
  769. begin
  770. if FWidth <> Value then
  771. begin
  772. FWidth := Value;
  773. end;
  774. end;
  775. procedure TGLFrameBuffer.ReattachTextures;
  776. var
  777. n: Integer;
  778. bEmpty: Boolean;
  779. s: String;
  780. begin
  781. Handle.AllocateHandle;
  782. Handle.Bind;
  783. // Reattach layered textures
  784. bEmpty := True;
  785. for n := 0 to MaxColorAttachments - 1 do
  786. if Assigned(FAttachedTexture[n]) then
  787. begin
  788. AttachTexture(
  789. GL_COLOR_ATTACHMENT0_EXT + n,
  790. DecodeTextureTarget(FAttachedTexture[n].Image.NativeTextureTarget),
  791. FAttachedTexture[n].Handle,
  792. FLevel,
  793. FLayer);
  794. bEmpty := False;
  795. end;
  796. if Assigned(FDepthTexture) then
  797. begin
  798. AttachTexture(
  799. GL_DEPTH_ATTACHMENT,
  800. DecodeTextureTarget(FDepthTexture.Image.NativeTextureTarget),
  801. FDepthTexture.Handle,
  802. FLevel,
  803. FLayer);
  804. bEmpty := False;
  805. end;
  806. if Assigned(FDRBO) then
  807. begin
  808. FDRBO.Bind;
  809. FDRBO.Unbind;
  810. gl.FramebufferRenderbuffer(FTarget, GL_DEPTH_ATTACHMENT_EXT,
  811. GL_RENDERBUFFER_EXT, FDRBO.Handle);
  812. bEmpty := False;
  813. end;
  814. if Assigned(FSRBO) then
  815. begin
  816. FSRBO.Bind;
  817. FSRBO.Unbind;
  818. gl.FramebufferRenderbuffer(FTarget, GL_STENCIL_ATTACHMENT,
  819. GL_RENDERBUFFER_EXT, FSRBO.Handle);
  820. bEmpty := False;
  821. end;
  822. if not bEmpty and (GetStringStatus(s) <> fsComplete) then
  823. GLSLogger.LogErrorFmt('Framebuffer error: %s. Deactivated', [s]);
  824. Handle.NotifyDataUpdated;
  825. end;
  826. procedure TGLFrameBuffer.SetLayer(const Value: Integer);
  827. var
  828. RC: TGLContext;
  829. begin
  830. if FLayer <> Value then
  831. begin
  832. FLayer := Value;
  833. RC := CurrentGLContext;
  834. if Assigned(RC) then
  835. begin
  836. if RC.GLStates.DrawFrameBuffer = FFrameBufferHandle.Handle then
  837. ReattachTextures;
  838. end;
  839. end;
  840. end;
  841. procedure TGLFrameBuffer.SetLevel(const Value: Integer);
  842. var
  843. RC: TGLContext;
  844. begin
  845. if FLevel <> Value then
  846. begin
  847. FLevel := Value;
  848. RC := CurrentGLContext;
  849. if Assigned(RC) then
  850. begin
  851. if RC.GLStates.DrawFrameBuffer = FFrameBufferHandle.Handle then
  852. ReattachTextures;
  853. end;
  854. end;
  855. end;
  856. //
  857. // ------------------- TGLFBORenderer --------------------------
  858. //
  859. procedure TGLFBORenderer.ApplyCamera(var ARci: TGLRenderContextInfo);
  860. var
  861. sc: Single;
  862. begin
  863. with ARci.PipelineTransformation do
  864. begin
  865. Push;
  866. if Assigned(Camera) then
  867. begin
  868. FStoreCamera[0] := ARci.cameraPosition;
  869. FStoreCamera[1] := ARci.cameraDirection;
  870. FStoreCamera[2] := ARci.cameraUp;
  871. IdentityAll;
  872. sc := FCamera.SceneScale;
  873. if FSceneScaleFactor > 0 then
  874. FCamera.SceneScale := Width / FSceneScaleFactor;
  875. FCamera.ApplyPerspective(Viewport, Width, Height, 96);
  876. // 96 is default dpi
  877. FCamera.SceneScale := sc;
  878. SetViewMatrix(CreateScaleMatrix(Vector3fMake(1.0 / FAspect, 1.0, 1.0)));
  879. FCamera.Apply;
  880. end
  881. else
  882. begin
  883. SetViewMatrix(MatrixMultiply(ViewMatrix^,
  884. CreateScaleMatrix(Vector3fMake(1.0 / FAspect, 1.0, 1.0))));
  885. end;
  886. end;
  887. end;
  888. procedure TGLFBORenderer.UnApplyCamera(var ARci: TGLRenderContextInfo);
  889. begin
  890. ARci.cameraPosition := FStoreCamera[0];
  891. ARci.cameraDirection := FStoreCamera[1];
  892. ARci.cameraUp := FStoreCamera[2];
  893. ARci.PipelineTransformation.Pop;
  894. end;
  895. constructor TGLFBORenderer.Create(AOwner: TComponent);
  896. begin
  897. inherited;
  898. ObjectStyle := [osDirectDraw, osNoVisibilityCulling];
  899. FFbo := TGLFrameBuffer.Create;
  900. FBackgroundColor := TGLColor.Create(Self);
  901. FUseLibraryAsMultiTarget := False;
  902. FForceTextureDimensions := True;
  903. FWidth := 256;
  904. FHeight := 256;
  905. FEnabledRenderBuffers := [erbDepth];
  906. FClearOptions := [coColorBufferClear, coDepthBufferClear,
  907. coStencilBufferClear, coUseBufferBackground];
  908. PickableTarget := False;
  909. FAspect := 1.0;
  910. FSceneScaleFactor := 0.0;
  911. FPostGenerateMipmap := True;
  912. StructureChanged;
  913. end;
  914. destructor TGLFBORenderer.Destroy;
  915. begin
  916. FFbo.Free;
  917. FDepthRBO.Free;
  918. FStencilRBO.Free;
  919. FBackgroundColor.Free;
  920. inherited;
  921. end;
  922. procedure TGLFBORenderer.Notification(AComponent: TComponent;
  923. Operation: TOperation);
  924. begin
  925. inherited;
  926. if (AComponent = FRootObject) and (Operation = opRemove) then
  927. FRootObject := nil;
  928. end;
  929. procedure TGLFBORenderer.DoAfterRender(var ARci: TGLRenderContextInfo);
  930. begin
  931. if Assigned(FAfterRender) then
  932. FAfterRender(Self, ARci);
  933. end;
  934. procedure TGLFBORenderer.DoBeforeRender(var ARci: TGLRenderContextInfo);
  935. begin
  936. if Assigned(FBeforeRender) then
  937. FBeforeRender(Self, ARci);
  938. end;
  939. procedure TGLFBORenderer.DoPostInitialize;
  940. begin
  941. if Assigned(FPostInitialize) then
  942. FPostInitialize(Self);
  943. end;
  944. procedure TGLFBORenderer.DoPreInitialize;
  945. begin
  946. if Assigned(FPreInitialize) then
  947. FPreInitialize(Self);
  948. end;
  949. procedure TGLFBORenderer.DoRender(var ARci: TGLRenderContextInfo;
  950. ARenderSelf, ARenderChildren: Boolean);
  951. begin
  952. if not (csDesigning in ComponentState) then
  953. RenderToFBO(ARci);
  954. if (not Assigned(FRootObject)) and (TargetVisibility = tvDefault) and ARenderChildren
  955. then
  956. RenderChildren(0, Count - 1, ARci);
  957. end;
  958. procedure TGLFBORenderer.ForceDimensions(Texture: TGLTexture);
  959. var
  960. bi: TGLBlankImage;
  961. mi: TGLMultisampleImage;
  962. begin
  963. if Texture.Image is TGLBlankImage then
  964. begin
  965. bi := TGLBlankImage(Texture.Image);
  966. bi.Width := Width;
  967. bi.Height := Height;
  968. end
  969. else if Texture.Image is TGLMultisampleImage then
  970. begin
  971. mi := TGLMultisampleImage(Texture.Image);
  972. mi.Width := Width;
  973. mi.Height := Height;
  974. end;
  975. end;
  976. function TGLFBORenderer.GetViewport: TRectangle;
  977. begin
  978. Result.Left := 0;
  979. Result.Top := 0;
  980. Result.Width := Width;
  981. Result.Height := Height;
  982. end;
  983. procedure TGLFBORenderer.Initialize;
  984. procedure AddOneMultiTarget(colorTex: TGLTexture);
  985. begin
  986. if ForceTextureDimensions then
  987. ForceDimensions(colorTex);
  988. if FColorAttachment >= FMaxAttachment then
  989. begin
  990. GLSLogger.LogError
  991. ('Number of color attachments out of GL_MAX_COLOR_ATTACHMENTS');
  992. Visible := False;
  993. Abort;
  994. end;
  995. FFbo.AttachTexture(FColorAttachment, colorTex);
  996. Inc(FColorAttachment);
  997. end;
  998. const
  999. cDrawBuffers: array [0 .. 15] of Cardinal = (GL_COLOR_ATTACHMENT0,
  1000. GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2,
  1001. GL_COLOR_ATTACHMENT3, GL_COLOR_ATTACHMENT4,
  1002. GL_COLOR_ATTACHMENT5, GL_COLOR_ATTACHMENT6,
  1003. GL_COLOR_ATTACHMENT7, GL_COLOR_ATTACHMENT8,
  1004. GL_COLOR_ATTACHMENT9, GL_COLOR_ATTACHMENT10,
  1005. GL_COLOR_ATTACHMENT11, GL_COLOR_ATTACHMENT12,
  1006. GL_COLOR_ATTACHMENT13, GL_COLOR_ATTACHMENT14,
  1007. GL_COLOR_ATTACHMENT15);
  1008. var
  1009. colorTex: TGLTexture;
  1010. depthTex: TGLTexture;
  1011. I: Integer;
  1012. MulTexture : TGLTextureArray;
  1013. begin
  1014. for I := 0 to MaxColorAttachments - 1 do
  1015. FFbo.DetachTexture(I);
  1016. if FMaxSize = 0 then
  1017. gl.GetIntegerv(GL_MAX_RENDERBUFFER_SIZE, @FMaxSize);
  1018. if Width > FMaxSize then
  1019. begin
  1020. FWidth := FMaxSize;
  1021. GLSLogger.LogWarningFmt('%s.Width out of GL_MAX_RENDERBUFFER_SIZE', [Name]);
  1022. end;
  1023. if Height > FMaxSize then
  1024. begin
  1025. FHeight := FMaxSize;
  1026. GLSLogger.LogWarningFmt('%s.Height out of GL_MAX_RENDERBUFFER_SIZE', [Name]);
  1027. end;
  1028. FFbo.Width := Width;
  1029. FFbo.Height := Height;
  1030. FFbo.Bind;
  1031. DoPreInitialize;
  1032. FFbo.Unbind;
  1033. if Assigned(FMaterialLibrary) then
  1034. begin
  1035. colorTex := FMaterialLibrary.TextureByName(ColorTextureName);
  1036. depthTex := FMaterialLibrary.TextureByName(DepthTextureName);
  1037. end
  1038. else
  1039. begin
  1040. colorTex := nil;
  1041. depthTex := nil;
  1042. end;
  1043. FHasColor := False;
  1044. FHasDepth := False;
  1045. FHasStencil := False;
  1046. FColorAttachment := 0;
  1047. if FUseLibraryAsMultiTarget or Assigned(FOnSetTextureTargets) then
  1048. begin
  1049. if not(gl.ARB_draw_buffers or gl.ATI_draw_buffers) then
  1050. begin
  1051. GLSLogger.LogError('Hardware do not support MRT');
  1052. Active := False;
  1053. exit;
  1054. end;
  1055. if FMaxAttachment = 0 then
  1056. gl.GetIntegerv(GL_MAX_COLOR_ATTACHMENTS, @FMaxAttachment);
  1057. if Assigned(FOnSetTextureTargets) then
  1058. begin
  1059. FOnSetTextureTargets(Self, MulTexture);
  1060. for I := 0 to High(MulTexture) do
  1061. begin
  1062. colorTex := MulTexture[i];
  1063. // Skip depth texture
  1064. if colorTex = depthTex then
  1065. Continue;
  1066. AddOneMultiTarget(colorTex);
  1067. end;
  1068. end
  1069. else
  1070. // Multicolor attachments
  1071. for I := 0 to FMaterialLibrary.Materials.Count - 1 do
  1072. begin
  1073. colorTex := FMaterialLibrary.Materials[I].Material.Texture;
  1074. // Skip depth texture
  1075. if colorTex = depthTex then
  1076. Continue;
  1077. AddOneMultiTarget(colorTex);
  1078. end;
  1079. FHasColor := FColorAttachment > 0;
  1080. end
  1081. else
  1082. begin
  1083. // One color attachment
  1084. if Assigned(colorTex) then
  1085. begin
  1086. if ForceTextureDimensions then
  1087. ForceDimensions(colorTex);
  1088. FFbo.AttachTexture(0, colorTex);
  1089. Inc(FColorAttachment);
  1090. FHasColor := True;
  1091. end;
  1092. end;
  1093. if Assigned(depthTex) then
  1094. begin
  1095. if ForceTextureDimensions then
  1096. ForceDimensions(depthTex);
  1097. FFbo.AttachDepthTexture(depthTex);
  1098. FDepthRBO.Free;
  1099. FDepthRBO := nil;
  1100. FHasDepth := True;
  1101. FHasStencil := depthTex.TextureFormatEx = tfDEPTH24_STENCIL8;
  1102. end
  1103. else if erbDepth in EnabledRenderBuffers then
  1104. begin
  1105. if not Assigned(FDepthRBO) then
  1106. FDepthRBO := TGLDepthRBO.Create;
  1107. FDepthRBO.Width := Width;
  1108. FDepthRBO.Height := Height;
  1109. FFbo.AttachDepthBuffer(FDepthRBO);
  1110. FHasDepth := True;
  1111. end
  1112. else
  1113. begin
  1114. FFbo.DetachDepthBuffer;
  1115. if Assigned(FDepthRBO) then
  1116. begin
  1117. FDepthRBO.Free;
  1118. FDepthRBO := nil;
  1119. end;
  1120. end;
  1121. if erbStencil in EnabledRenderBuffers then
  1122. begin
  1123. if not Assigned(FStencilRBO) then
  1124. FStencilRBO := TGLStencilRBO.Create;
  1125. FStencilRBO.StencilPrecision := FStencilPrecision;
  1126. FStencilRBO.Width := Width;
  1127. FStencilRBO.Height := Height;
  1128. FFbo.AttachStencilBuffer(FStencilRBO);
  1129. FHasStencil := True;
  1130. end
  1131. else
  1132. begin
  1133. if not FHasStencil then
  1134. FFbo.DetachStencilBuffer;
  1135. if Assigned(FStencilRBO) then
  1136. begin
  1137. FStencilRBO.Free;
  1138. FStencilRBO := nil;
  1139. end;
  1140. end;
  1141. FFbo.Bind;
  1142. if FColorAttachment = 0 then
  1143. begin
  1144. gl.DrawBuffer(GL_NONE);
  1145. gl.ReadBuffer(GL_NONE);
  1146. end
  1147. else
  1148. gl.DrawBuffers(FColorAttachment, @cDrawBuffers);
  1149. DoPostInitialize;
  1150. FFbo.Unbind;
  1151. gl.CheckError;
  1152. ClearStructureChanged;
  1153. end;
  1154. procedure TGLFBORenderer.RenderToFBO(var ARci: TGLRenderContextInfo);
  1155. function GetClearBits: cardinal;
  1156. begin
  1157. Result := 0;
  1158. if HasColor and (coColorBufferClear in FClearOptions) then
  1159. Result := Result or GL_COLOR_BUFFER_BIT;
  1160. if HasDepth and (coDepthBufferClear in FClearOptions) then
  1161. Result := Result or GL_DEPTH_BUFFER_BIT;
  1162. if HasStencil and (coStencilBufferClear in FClearOptions) then
  1163. Result := Result or GL_STENCIL_BUFFER_BIT;
  1164. end;
  1165. type
  1166. TGLStoredStates = record
  1167. ColorClearValue: TGLColorVector;
  1168. ColorWriteMask: TGLColorMask;
  1169. Tests: TGLStates;
  1170. end;
  1171. function StoreStates: TGLStoredStates;
  1172. begin
  1173. Result.ColorClearValue := ARci.GLStates.ColorClearValue;
  1174. Result.ColorWriteMask := ARci.GLStates.ColorWriteMask[0];
  1175. Result.Tests := [stDepthTest, stStencilTest] * ARci.GLStates.States;
  1176. end;
  1177. procedure RestoreStates(const aStates: TGLStoredStates);
  1178. begin
  1179. ARci.GLStates.ColorClearValue := aStates.ColorClearValue;
  1180. ARci.GLStates.SetColorMask(aStates.ColorWriteMask);
  1181. if stDepthTest in aStates.Tests then
  1182. ARci.GLStates.Enable(stDepthTest)
  1183. else
  1184. ARci.GLStates.Disable(stDepthTest);
  1185. if stStencilTest in aStates.Tests then
  1186. ARci.GLStates.Enable(stStencilTest)
  1187. else
  1188. ARci.GLStates.Disable(stStencilTest);
  1189. end;
  1190. var
  1191. backColor: TGLColorVector;
  1192. buffer: TGLSceneBuffer;
  1193. savedStates: TGLStoredStates;
  1194. w, h: Integer;
  1195. s: string;
  1196. begin
  1197. if (ARci.drawState = dsPicking) and not PickableTarget then
  1198. Exit;
  1199. if not TGLFramebufferHandle.IsSupported then
  1200. begin
  1201. GLSLogger.LogError('Framebuffer not supported - deactivated');
  1202. Active := False;
  1203. Exit;
  1204. end;
  1205. // prevent recursion
  1206. if FRendering then
  1207. Exit;
  1208. FRendering := True;
  1209. if (ocStructure in Changes) or Assigned(FOnSetTextureTargets) then
  1210. begin
  1211. Initialize;
  1212. if not Active then
  1213. Exit;
  1214. end;
  1215. ApplyCamera(ARci);
  1216. try
  1217. savedStates := StoreStates;
  1218. FFbo.Bind;
  1219. if FFbo.GetStringStatus(s) <> fsComplete then
  1220. begin
  1221. GLSLogger.LogErrorFmt('Framebuffer error: %s. Deactivated', [s]);
  1222. Active := False;
  1223. Exit;
  1224. end;
  1225. DoBeforeRender(ARci);
  1226. if Assigned(Camera) then
  1227. Camera.Scene.SetupLights(ARci.GLStates.MaxLights);
  1228. w := Width;
  1229. h := Height;
  1230. if FFbo.Level > 0 then
  1231. begin
  1232. w := w shr FFbo.Level;
  1233. h := h shr FFbo.Level;
  1234. if w = 0 then
  1235. w := 1;
  1236. if h = 0 then
  1237. h := 1;
  1238. end;
  1239. ARci.GLStates.Viewport := Vector4iMake(0, 0, w, h);
  1240. buffer := ARci.buffer as TGLSceneBuffer;
  1241. if HasColor then
  1242. ARci.GLStates.SetColorMask(cAllColorComponents)
  1243. else
  1244. ARci.GLStates.SetColorMask([]);
  1245. ARci.GLStates.DepthWriteMask := HasDepth;
  1246. if HasStencil then
  1247. ARci.GLStates.Enable(stStencilTest)
  1248. else
  1249. ARci.GLStates.Disable(stStencilTest);
  1250. if coUseBufferBackground in FClearOptions then
  1251. begin
  1252. backColor := ConvertWinColor(buffer.BackgroundColor);
  1253. backColor.W := buffer.BackgroundAlpha;
  1254. ARci.GLStates.ColorClearValue := backColor;
  1255. end
  1256. else
  1257. begin
  1258. ARci.GLStates.ColorClearValue := FBackgroundColor.Color;
  1259. end;
  1260. gl.Clear(GetClearBits);
  1261. FFbo.PreRender;
  1262. // render to fbo
  1263. if Assigned(RootObject) then
  1264. begin
  1265. // if object should only be rendered to the fbo
  1266. // ensure it's visible before rendering to fbo
  1267. if TargetVisibility = tvFBOOnly then
  1268. RootObject.Visible := True;
  1269. RootObject.Render(ARci);
  1270. // then make it invisible afterwards
  1271. if TargetVisibility = tvFBOOnly then
  1272. RootObject.Visible := False;
  1273. end
  1274. else if (Count > 0) then
  1275. RenderChildren(0, Count - 1, ARci);
  1276. FFbo.PostRender(FPostGenerateMipmap);
  1277. RestoreStates(savedStates);
  1278. ARci.GLStates.Viewport := Vector4iMake(0, 0, ARci.viewPortSize.cx,
  1279. ARci.viewPortSize.cy);
  1280. finally
  1281. FFbo.Unbind;
  1282. FRendering := False;
  1283. DoAfterRender(ARci);
  1284. UnApplyCamera(ARci);
  1285. if Assigned(Camera) then
  1286. Camera.Scene.SetupLights(ARci.GLStates.MaxLights);
  1287. end;
  1288. end;
  1289. procedure TGLFBORenderer.SetBackgroundColor(const Value: TGLColor);
  1290. begin
  1291. FBackgroundColor.Assign(Value);
  1292. end;
  1293. procedure TGLFBORenderer.SetCamera(const Value: TGLCamera);
  1294. begin
  1295. if FCamera <> Value then
  1296. begin
  1297. FCamera := Value;
  1298. StructureChanged;
  1299. end;
  1300. end;
  1301. procedure TGLFBORenderer.SetColorTextureName(const Value: TGLLibMaterialName);
  1302. begin
  1303. if FColorTextureName <> Value then
  1304. begin
  1305. FColorTextureName := Value;
  1306. StructureChanged;
  1307. end;
  1308. end;
  1309. procedure TGLFBORenderer.SetDepthTextureName(const Value: TGLLibMaterialName);
  1310. begin
  1311. if FDepthTextureName <> Value then
  1312. begin
  1313. FDepthTextureName := Value;
  1314. StructureChanged;
  1315. end;
  1316. end;
  1317. procedure TGLFBORenderer.SetEnabledRenderBuffers(const Value
  1318. : TGLEnabledRenderBuffers);
  1319. begin
  1320. if FEnabledRenderBuffers <> Value then
  1321. begin
  1322. FEnabledRenderBuffers := Value;
  1323. StructureChanged;
  1324. end;
  1325. end;
  1326. procedure TGLFBORenderer.SetForceTextureDimentions(const Value: Boolean);
  1327. begin
  1328. if FForceTextureDimensions <> Value then
  1329. begin
  1330. FForceTextureDimensions := Value;
  1331. StructureChanged;
  1332. end;
  1333. end;
  1334. function TGLFBORenderer.GetMaterialLibrary: TGLAbstractMaterialLibrary;
  1335. begin
  1336. Result := FMaterialLibrary;
  1337. end;
  1338. procedure TGLFBORenderer.SetMaterialLibrary(const Value: TGLAbstractMaterialLibrary);
  1339. begin
  1340. if FMaterialLibrary <> Value then
  1341. begin
  1342. if Value is TGLMaterialLibrary then
  1343. begin
  1344. FMaterialLibrary := TGLMaterialLibrary(Value);
  1345. StructureChanged;
  1346. end;
  1347. end;
  1348. end;
  1349. procedure TGLFBORenderer.SetUseLibraryAsMultiTarget(Value: Boolean);
  1350. begin
  1351. if FUseLibraryAsMultiTarget <> Value then
  1352. begin
  1353. FUseLibraryAsMultiTarget := Value;
  1354. StructureChanged;
  1355. end;
  1356. end;
  1357. procedure TGLFBORenderer.SetPostGenerateMipmap(const Value: Boolean);
  1358. begin
  1359. if FPostGenerateMipmap <> Value then
  1360. FPostGenerateMipmap := Value;
  1361. end;
  1362. procedure TGLFBORenderer.SetRootObject(const Value: TGLBaseSceneObject);
  1363. begin
  1364. if FRootObject <> Value then
  1365. begin
  1366. if Assigned(FRootObject) then
  1367. FRootObject.RemoveFreeNotification(Self);
  1368. FRootObject := Value;
  1369. if Assigned(FRootObject) then
  1370. FRootObject.FreeNotification(Self);
  1371. StructureChanged;
  1372. end;
  1373. end;
  1374. procedure TGLFBORenderer.SetStencilPrecision(const Value: TGLStencilPrecision);
  1375. begin
  1376. if FStencilPrecision <> Value then
  1377. begin
  1378. FStencilPrecision := Value;
  1379. StructureChanged;
  1380. end;
  1381. end;
  1382. procedure TGLFBORenderer.SetTargetVisibility(const Value
  1383. : TGLFBOTargetVisibility);
  1384. begin
  1385. if FTargetVisibility <> Value then
  1386. begin
  1387. if Assigned(RootObject) then
  1388. begin
  1389. if (TargetVisibility = tvFBOOnly) then
  1390. begin
  1391. // we went from fbo only, restore root's old visibility
  1392. RootObject.Visible := FRootVisible;
  1393. end
  1394. else
  1395. begin
  1396. // we're going to fbo only, save root visibility for later
  1397. FRootVisible := RootObject.Visible;
  1398. end;
  1399. end;
  1400. FTargetVisibility := Value;
  1401. StructureChanged;
  1402. end;
  1403. end;
  1404. function TGLFBORenderer.StoreSceneScaleFactor: Boolean;
  1405. begin
  1406. Result := (FSceneScaleFactor <> 0.0);
  1407. end;
  1408. function TGLFBORenderer.StoreAspect: Boolean;
  1409. begin
  1410. Result := (FAspect <> 1.0);
  1411. end;
  1412. procedure TGLFBORenderer.SetWidth(Value: Integer);
  1413. begin
  1414. if FWidth <> Value then
  1415. begin
  1416. FWidth := Value;
  1417. StructureChanged;
  1418. end;
  1419. end;
  1420. procedure TGLFBORenderer.SetHeight(Value: Integer);
  1421. begin
  1422. if FHeight <> Value then
  1423. begin
  1424. FHeight := Value;
  1425. StructureChanged;
  1426. end;
  1427. end;
  1428. procedure TGLFBORenderer.SetLayer(const Value: Integer);
  1429. begin
  1430. if Value <> FFbo.Layer then
  1431. begin
  1432. if FRendering or (ocStructure in Changes) then
  1433. FFbo.Layer := Value
  1434. else
  1435. begin
  1436. FFbo.Bind;
  1437. FFbo.Layer := Value;
  1438. FFbo.Unbind;
  1439. end;
  1440. end;
  1441. end;
  1442. function TGLFBORenderer.GetLayer: Integer;
  1443. begin
  1444. Result := FFbo.Layer;
  1445. end;
  1446. procedure TGLFBORenderer.SetLevel(const Value: Integer);
  1447. var
  1448. w, h: Integer;
  1449. begin
  1450. if Value <> FFbo.Level then
  1451. begin
  1452. if FRendering or (ocStructure in Changes) then
  1453. begin
  1454. FFbo.Level := Value;
  1455. w := Width;
  1456. h := Height;
  1457. if FFbo.Level > 0 then
  1458. begin
  1459. w := w shr FFbo.Level;
  1460. h := h shr FFbo.Level;
  1461. if w = 0 then
  1462. w := 1;
  1463. if h = 0 then
  1464. h := 1;
  1465. CurrentGLContext.GLStates.Viewport := Vector4iMake(0, 0, w, h);
  1466. end;
  1467. end
  1468. else
  1469. begin
  1470. FFbo.Bind;
  1471. FFbo.Level := Value;
  1472. FFbo.Unbind;
  1473. end;
  1474. end;
  1475. end;
  1476. function TGLFBORenderer.GetLevel: Integer;
  1477. begin
  1478. Result := FFbo.Level;
  1479. end;
  1480. //-------------------------------------------------
  1481. initialization
  1482. //-------------------------------------------------
  1483. RegisterClasses([TGLFBORenderer]);
  1484. end.