1 unit uglcFrameBufferObject;
4 Prefix: glc - OpenGL Core
5 Beschreibung: diese Unit enthält eine Klassen-Kapselung der OpenGL FrameBufferObjekte
8 fbo: TglcFrameBufferObject;
9 tex: TglcTextureBuffer;
10 buf: TglcRenderBuffer;
12 fbo := TglcFrameBufferObject.Create;
14 ffbo.SetSize(800, 600);
16 // creating texture buffer as color buffer
17 tex := TglcTextureBuffer.Create(TglcFormat.fmRGBA, TglcInternalFormat.ifRGBA16F);
18 fbo.AddBuffer(tex, TglcAttachment.atColor0, true);
20 // creating render buffer as depth buffer
21 buf := TglcRenderBuffer.Create(TglcInternalFormat.ifDepthComponent);
22 fbo.AddBuffer(buf, TglcAttachment.atDepth, true);
24 // render to frame buffer object
26 // do normal rendering
31 // do normal rendering
42 Classes, SysUtils, fgl, {$IFNDEF OPENGL_ES}dglOpenGl{$ELSE}dglOpenGLES{$ENDIF}, uglcTypes;
45 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
46 TglcBufferType = (btRenderBuffer, btTextureBuffer);
47 TglcBuffer = class(TObject)
49 fBufferType: TglcBufferType;
53 procedure SetWidth(const aValue: Integer);
54 procedure SetHeight(const aValue: Integer);
56 property Width : Integer read fWidth write SetWidth;
57 property Height: Integer read fHeight write SetHeight;
58 property BufferType: TglcBufferType read fBufferType;
60 procedure SetSize(const aWidth, aHeight: Integer); virtual;
63 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
64 EglcRenderBuffer = class(Exception);
65 TglcRenderBuffer = class(TglcBuffer)
68 fFormat: TglcInternalFormat;
70 procedure UpdateRenderBufferStorage;
71 procedure SetFormat(const aValue: TglcInternalFormat);
73 property ID: gluInt read fID;
74 property Format: TglcInternalFormat read fFormat write SetFormat;
76 procedure SetSize(const aWidth, aHeight: Integer); override;
80 constructor Create(const aFormat: TglcInternalFormat);
81 destructor Destroy; override;
84 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
85 EglcTextureBuffer = class(exception);
86 TglcTextureBuffer = class(TglcBuffer)
90 fInternalFormat: TglcInternalFormat;
93 procedure UpdateTexImage;
94 procedure SetFormat(const aValue: TglcFormat);
95 procedure SetInternalFormat(const aValue: TglcInternalFormat);
96 procedure SetBorder(const aValue: Boolean);
98 property ID : GLuint read fID;
99 property Border : Boolean read fBorder write SetBorder;
100 property Format : TglcFormat read fFormat write SetFormat;
101 property InternalFormat: TglcInternalFormat read fInternalFormat write SetInternalFormat;
103 procedure SetSize(const aWidth, aHeight: Integer); override;
104 procedure Bind(const aEnableTextureUnit: Boolean = true);
105 procedure Unbind(const aDisableTextureUnit: Boolean = true);
107 constructor Create(const aFormat: TglcFormat; const aInternalFormat: TglcInternalFormat);
108 destructor Destroy; override;
111 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
112 EglcFrameBufferObject = class(Exception);
113 TglcFrameBufferObject = class(TObject)
115 TglcAttachmentContainer = class(TObject)
117 Attachment: TglcAttachment;
119 constructor Create(const aBuffer: TglcBuffer; const aAttachment: TglcAttachment; const aOwnsObject: Boolean = true);
120 destructor Destroy; override;
122 TglcAttachmentContainerList = specialize TFPGObjectList<TglcAttachmentContainer>;
125 fOwnsObjects: Boolean;
128 fBuffers: TglcAttachmentContainerList;
130 fOldViewport: array[0..3] of GLint;
133 function GetBuffer(const aIndex: Integer): TglcBuffer;
134 procedure SetBuffer(const aIndex: Integer; const aValue: TglcBuffer);
136 function GetAttachment(const aIndex: Integer): TglcAttachment;
137 procedure SetAttachment(const aIndex: Integer; const aValue: TglcAttachment);
139 function GetBufferCount: Integer;
141 procedure Attach(const aIndex: Integer);
142 procedure Detach(const aIndex: Integer);
144 procedure SetWidth(const aValue: Integer);
145 procedure SetHeight(const aValue: Integer);
146 procedure CheckFrameBufferStatus;
147 procedure UpdateAndCheckFBO;
149 property ID : GLuint read fID;
150 property Count : Integer read GetBufferCount;
151 property OwnsObjects: Boolean read fOwnsObjects;
152 property Width : Integer read fWidth write SetWidth;
153 property Height : Integer read fHeight write SetHeight;
154 property Attachments[const aIndex: Integer]: TglcAttachment read GetAttachment write SetAttachment;
155 property Buffers [const aIndex: Integer]: TglcBuffer read GetBuffer write SetBuffer;
157 procedure AddBuffer(const aBuffer: TglcBuffer; const aAttachment: TglcAttachment; const aOwnsBuffer: Boolean = true);
158 procedure DelBuffer(const aIndex: Integer);
159 function RemBuffer(const aBuffer: TglcBuffer): Integer;
160 function IndexOfBuffer(const aBuffer: TglcBuffer): Integer;
162 procedure SetSize(const aWidth, aHeight: Integer);
163 function CheckAttachment(const aAttachment: TglcAttachment): Boolean;
165 procedure Bind(const aSetViewport: Boolean = true);
166 procedure Unbind(const aResetViewport: Boolean = true);
168 constructor Create(const aOwnBuffers: Boolean = true);
169 destructor Destroy; override;
174 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
175 //TglcBuffer////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
176 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
177 procedure TglcBuffer.SetWidth(const aValue: Integer);
179 SetSize(aValue, fHeight);
182 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
183 procedure TglcBuffer.SetHeight(const aValue: Integer);
185 SetSize(fWidth, aValue);
188 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
189 procedure TglcBuffer.SetSize(const aWidth, aHeight: Integer);
195 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
196 //TglcRenderBuffer//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
197 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
198 procedure TglcRenderBuffer.UpdateRenderBufferStorage;
200 glGetError; //clear Erroros
202 glRenderbufferStorage(GL_RENDERBUFFER, GLenum(fFormat), fWidth, fHeight);
204 glcCheckAndRaiseError;
207 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
208 procedure TglcRenderBuffer.SetFormat(const aValue: TglcInternalFormat);
211 UpdateRenderBufferStorage;
214 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
215 procedure TglcRenderBuffer.SetSize(const aWidth, aHeight: Integer);
217 if (aWidth <= 0) or (aHeight <= 0) then
218 raise EglcRenderBuffer.Create('invalid width or height');
219 if (aWidth <> fWidth) or (aHeight <> fHeight) then begin
220 inherited SetSize(aWidth, aHeight);
221 UpdateRenderBufferStorage;
225 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
226 procedure TglcRenderBuffer.Bind;
228 glBindRenderbuffer(GL_RENDERBUFFER, fID);
231 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
232 procedure TglcRenderBuffer.Unbind;
234 glBindRenderbuffer(GL_RENDERBUFFER, 0);
237 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
238 constructor TglcRenderBuffer.Create(const aFormat: TglcInternalFormat);
241 fBufferType := btRenderBuffer;
242 glGenRenderbuffers(1, @fID);
247 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
248 destructor TglcRenderBuffer.Destroy;
250 glDeleteRenderbuffers(1, @fID);
254 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
255 //TglcTextureBuffer/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
256 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
257 procedure TglcTextureBuffer.UpdateTexImage;
259 glGetError; //clear errors
261 glTexImage2D(GL_TEXTURE_2D, 0, GLenum(fInternalFormat), fWidth, fHeight, GLint(Byte(fBorder) and Byte(1)), GLenum(fFormat), GL_UNSIGNED_BYTE, nil);
263 glcCheckAndRaiseError;
266 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
267 procedure TglcTextureBuffer.SetFormat(const aValue: TglcFormat);
269 if (fFormat <> aValue) then begin
275 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
276 procedure TglcTextureBuffer.SetInternalFormat(const aValue: TglcInternalFormat);
278 if (fInternalFormat <> aValue) then begin
279 fInternalFormat := aValue;
284 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
285 procedure TglcTextureBuffer.SetBorder(const aValue: Boolean);
287 if (fBorder <> aValue) then begin
293 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
294 procedure TglcTextureBuffer.SetSize(const aWidth, aHeight: Integer);
296 if (aWidth <= 0) or (aHeight <= 0) then
297 raise EglcTextureBuffer.Create('invalid width or height');
298 if (aWidth <> fWidth) or (aHeight <> fHeight) then begin
299 inherited SetSize(aWidth, aHeight);
304 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
305 procedure TglcTextureBuffer.Bind(const aEnableTextureUnit: Boolean = true);
307 if aEnableTextureUnit then
308 glEnable(GL_TEXTURE_2D);
309 glBindTexture(GL_TEXTURE_2D, fID);
312 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
313 procedure TglcTextureBuffer.Unbind(const aDisableTextureUnit: Boolean = true);
315 if aDisableTextureUnit then
316 glDisable(GL_TEXTURE_2D);
317 glBindTexture(GL_TEXTURE_2D, 0);
320 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
321 constructor TglcTextureBuffer.Create(const aFormat: TglcFormat; const aInternalFormat: TglcInternalFormat);
324 fBufferType := btTextureBuffer;
326 glGenTextures(1, @fID);
328 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, {$IFNDEF OPENGL_ES}GL_CLAMP{$ELSE}GL_CLAMP_TO_EDGE{$ENDIF});
329 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, {$IFNDEF OPENGL_ES}GL_CLAMP{$ELSE}GL_CLAMP_TO_EDGE{$ENDIF});
330 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
331 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
335 fInternalFormat := aInternalFormat;
339 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
340 destructor TglcTextureBuffer.Destroy;
342 glDeleteTextures(1, @fID);
346 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
347 //TglcAttachment////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
348 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
349 constructor TglcFrameBufferObject.TglcAttachmentContainer.Create(const aBuffer: TglcBuffer;
350 const aAttachment: TglcAttachment; const aOwnsObject: Boolean);
354 Attachment := aAttachment;
355 OwnsObject := aOwnsObject;
358 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
359 destructor TglcFrameBufferObject.TglcAttachmentContainer.Destroy;
366 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
367 //TglcFrameBufferObject/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
368 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
369 function TglcFrameBufferObject.GetBuffer(const aIndex: Integer): TglcBuffer;
371 if (aIndex >= 0) and (aIndex < fBuffers.Count) then
372 result := fBuffers[aIndex].Buffer
374 raise EglcFrameBufferObject.Create('Index out of Bounds: ' + IntToStr(aIndex));
377 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
378 procedure TglcFrameBufferObject.SetBuffer(const aIndex: Integer; const aValue: TglcBuffer);
380 if (aIndex < 0) or (aIndex >= fBuffers.Count) then
381 raise EglcFrameBufferObject.Create('Index out of Bounds: ' + IntToStr(aIndex));
383 if not Assigned(aValue) then
384 raise EglcFrameBufferObject.Create('invalid buffer');
387 fBuffers[aIndex].Buffer := aValue;
392 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
393 function TglcFrameBufferObject.GetAttachment(const aIndex: Integer): TglcAttachment;
395 if (aIndex >= 0) and (aIndex < fBuffers.Count) then
396 result := fBuffers[aIndex].Attachment
398 raise EglcFrameBufferObject.Create('Index out of Bounds: ' + IntToStr(aIndex));
401 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
402 procedure TglcFrameBufferObject.SetAttachment(const aIndex: Integer; const aValue: TglcAttachment);
404 if (aIndex < 0) or (aIndex >= fBuffers.Count) then
405 raise EglcFrameBufferObject.Create('Index out of Bounds: ' + IntToStr(aIndex));
407 if not CheckAttachment(aValue) then
408 raise EglcFrameBufferObject.Create('Attachment already assigned');
411 fBuffers[aIndex].Attachment := aValue;
416 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
417 procedure TglcFrameBufferObject.Attach(const aIndex: Integer);
422 a := Attachments[aIndex];
423 b := Buffers[aIndex];
425 if (b.BufferType = btRenderBuffer) then
426 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GLenum(a), GL_RENDERBUFFER, (b as TglcRenderBuffer).ID)
428 glFramebufferTexture2D(GL_FRAMEBUFFER, GLenum(a), GL_TEXTURE_2D, (b as TglcTextureBuffer).ID, 0);
432 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
433 procedure TglcFrameBufferObject.Detach(const aIndex: Integer);
438 a := Attachments[aIndex];
439 b := Buffers[aIndex];
441 if (b.BufferType = btRenderBuffer) then
442 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GLenum(a), GL_RENDERBUFFER, 0)
444 glFramebufferTexture2D(GL_FRAMEBUFFER, GLenum(a), GL_TEXTURE_2D, 0, 0);
448 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
449 //legt die neue Breite fest
451 procedure TglcFrameBufferObject.SetWidth(const aValue: Integer);
453 SetSize(aValue, fHeight);
456 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
457 //legt die neue Höhe fest
459 procedure TglcFrameBufferObject.SetHeight(const aValue: Integer);
461 SetSize(fWidth, aValue);
464 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
465 procedure TglcFrameBufferObject.CheckFrameBufferStatus;
467 case glCheckFramebufferStatus(GL_FRAMEBUFFER) of
468 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
469 raise EglcFrameBufferObject.Create('Incomplete attachment');
470 GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
471 raise EglcFrameBufferObject.Create('Missing attachment');
473 GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
474 raise EglcFrameBufferObject.Create('Incomplete dimensions');
475 GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
476 raise EglcFrameBufferObject.Create('Incomplete formats');
477 GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
478 raise EglcFrameBufferObject.Create('Incomplete draw buffer');
479 GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
480 raise EglcFrameBufferObject.Create('Incomplete read buffer');
482 GL_FRAMEBUFFER_UNSUPPORTED:
483 raise EglcFrameBufferObject.Create('Framebufferobjects unsupported');
487 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
488 //prüft das FrameBufferObjekt auf Fehler
489 procedure TglcFrameBufferObject.UpdateAndCheckFBO;
491 function IsColorAttachment(const a: TglcAttachment): Boolean;
493 result := (GLenum(a) >= GL_COLOR_ATTACHMENT0) and (GLenum(a) <= GL_COLOR_ATTACHMENT15);
497 buff: array of GLenum;
503 if (fBuffers.Count = 0) then
509 for i := 0 to fBuffers.Count-1 do
510 if IsColorAttachment(fBuffers[i].Attachment) then begin
511 SetLength(buff, Length(buff) + 1);
512 buff[High(buff)] := GLenum(fBuffers[i].Attachment);
515 //set Read and Draw Buffer
516 if (Length(buff) = 0) then begin
517 glReadBuffer(GL_NONE);
519 glDrawBuffer(GL_NONE);
523 glDrawBuffers(1, @buff[0]);
526 glDrawBuffers(Length(buff), @buff[0]);
528 glGetBooleanv(GL_DOUBLEBUFFER, @b);
530 glReadBuffer(GL_BACK)
532 glReadBuffer(GL_FRONT);
534 glReadBuffer(GL_FRONT);
540 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
541 function TglcFrameBufferObject.GetBufferCount: Integer;
543 result := fBuffers.Count;
546 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
547 procedure TglcFrameBufferObject.AddBuffer(const aBuffer: TglcBuffer;
548 const aAttachment: TglcAttachment; const aOwnsBuffer: Boolean);
550 if not Assigned(aBuffer) then
551 raise EglcFrameBufferObject.Create('invalid buffer');
552 if not CheckAttachment(aAttachment) then
553 raise EglcFrameBufferObject.Create('attachment already assigned');
555 fBuffers.Add(TglcAttachmentContainer.Create(aBuffer, aAttachment, fOwnsObjects and aOwnsBuffer));
557 aBuffer.SetSize(fWidth, fHeight);
558 Attach(fBuffers.Count-1);
563 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
564 procedure TglcFrameBufferObject.DelBuffer(const aIndex: Integer);
566 if (aIndex >= 0) and (aIndex < fBuffers.Count) then begin
568 fBuffers.Delete(aIndex);
571 raise EglcFrameBufferObject.Create('Index out of Bounds: ' + IntToStr(aIndex));
574 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
575 function TglcFrameBufferObject.RemBuffer(const aBuffer: TglcBuffer): Integer;
577 result := IndexOfBuffer(aBuffer);
578 if (result >= 0) then
582 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
583 function TglcFrameBufferObject.IndexOfBuffer(const aBuffer: TglcBuffer): Integer;
587 for i := 0 to fBuffers.Count-1 do
588 if (fBuffers[i].Buffer = aBuffer) then begin
595 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
596 //legt die Größe neu fest
597 //@Width: neue Breite;
598 //@Height: neue Höhe;
599 procedure TglcFrameBufferObject.SetSize(const aWidth, aHeight: Integer);
601 c: TglcAttachmentContainer;
603 if (aWidth <= 0) or (aHeight <= 0) then
604 raise EglcFrameBufferObject.Create('invalid width or height');
611 c.Buffer.SetSize(fWidth, fHeight);
614 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
615 function TglcFrameBufferObject.CheckAttachment(const aAttachment: TglcAttachment): Boolean;
620 for i := 0 to fBuffers.Count-1 do
621 if (fBuffers[i].Attachment = aAttachment) then
626 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
627 //Bindet das FrameBufferObjekt
628 procedure TglcFrameBufferObject.Bind(const aSetViewport: Boolean = true);
630 glBindFramebuffer(GL_FRAMEBUFFER, fID);
631 if aSetViewport then begin
633 glPushAttrib(GL_VIEWPORT_BIT);
635 glGetIntegerv(GL_VIEWPORT, @fOldViewport[0]);
637 glViewPort(0, 0, fWidth, fHeight);
641 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
642 //Entbindet das FrameBufferObjekt
643 procedure TglcFrameBufferObject.Unbind(const aResetViewport: Boolean = true);
645 if aResetViewport then
649 glViewport(fOldViewport[0], fOldViewport[1], fOldViewport[2], fOldViewport[3]);
651 glBindFramebuffer(GL_FRAMEBUFFER, 0);
654 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
656 constructor TglcFrameBufferObject.Create(const aOwnBuffers: Boolean = true);
660 glGenFramebuffers(1, @fID);
663 fOwnsObjects := aOwnBuffers;
664 fBuffers := TglcAttachmentContainerList.Create(true); //containers are always owned by this object!
667 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
668 //gibt das Objekt frei
669 destructor TglcFrameBufferObject.Destroy;
672 glDeleteFramebuffers(1, @fID);