123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878 |
- //
- // The graphics engine GLXEngine. The unit of GXScene for Delphi
- //
- unit GXS.FBORenderer;
- (* Implements FBO support *)
- interface
- {$I Stage.Defines.inc}
- uses
- Winapi.OpenGL,
- Winapi.OpenGLext,
- System.Classes,
- System.SysUtils,
- FMX.Dialogs,
- GXS.PersistentClasses,
- Stage.VectorGeometry,
- GXS.Scene,
- GXS.Texture,
- GXS.Context,
- GXS.FBO,
- GXS.Color,
- GXS.Material,
- GXS.RenderContextInfo,
- GXS.State,
- Stage.PipelineTransform,
- Stage.TextureFormat,
- Stage.VectorTypes,
- GXS.MultisampleImage;
- type
- TgxEnabledRenderBuffer = (erbDepth, erbStencil);
- TgxEnabledRenderBuffers = set of TgxEnabledRenderBuffer;
- TgxFBOTargetVisibility = (tvDefault, tvFBOOnly);
- TgxFBOClearOption = (coColorBufferClear, coDepthBufferClear, coStencilBufferClear, coUseBufferBackground);
- TgxFBOClearOptions = set of TgxFBOClearOption;
- TgxTextureArray = array of TgxTexture;
- TSetTextureTargetsEvent = procedure(Sender: TObject; var colorTexs: TgxTextureArray) of object;
- TgxFBORenderer = class(TgxBaseSceneObject, IgxMaterialLibrarySupported)
- private
- FFbo: TgxFrameBuffer;
- FDepthRBO: TgxDepthRBO;
- FStencilRBO: TgxStencilRBO;
- FColorAttachment: Integer;
- FRendering: Boolean;
- FHasColor: Boolean;
- FHasDepth: Boolean;
- FHasStencil: Boolean;
- FMaterialLibrary: TgxMaterialLibrary;
- FColorTextureName: TgxLibMaterialName;
- FDepthTextureName: TgxLibMaterialName;
- FWidth: Integer;
- FHeight: Integer;
- FForceTextureDimensions: Boolean;
- FStencilPrecision: TgxStencilPrecision;
- FRootObject: TgxBaseSceneObject;
- FRootVisible: Boolean;
- FCamera: TgxCamera;
- FEnabledRenderBuffers: TgxEnabledRenderBuffers;
- FTargetVisibility: TgxFBOTargetVisibility;
- FBeforeRender: TDirectRenderEvent;
- FPostInitialize: TNotifyEvent;
- FAfterRender: TDirectRenderEvent;
- FPreInitialize: TNotifyEvent;
- FBackgroundColor: TgxColor;
- FClearOptions: TgxFBOClearOptions;
- FAspect: Single;
- FSceneScaleFactor: Single;
- FUseLibraryAsMultiTarget: Boolean;
- FPostGenerateMipmap: Boolean;
- FMaxSize: Integer;
- FMaxAttachment: Integer;
- FStoreCamera: array [0 .. 2] of TVector4f;
- FOnSetTextureTargets: TSetTextureTargetsEvent;
- // implementing IGLMaterialLibrarySupported
- function GetMaterialLibrary: TgxAbstractMaterialLibrary;
- procedure SetMaterialLibrary(const Value: TgxAbstractMaterialLibrary);
- procedure SetDepthTextureName(const Value: TgxLibMaterialName);
- procedure SetColorTextureName(const Value: TgxLibMaterialName);
- procedure SetForceTextureDimentions(const Value: Boolean);
- procedure SetHeight(Value: Integer);
- procedure SetWidth(Value: Integer);
- procedure SetLayer(const Value: Integer);
- function GetLayer: Integer;
- procedure SetLevel(const Value: Integer);
- function GetLevel: Integer;
- procedure SetStencilPrecision(const Value: TgxStencilPrecision);
- procedure SetRootObject(const Value: TgxBaseSceneObject);
- function GetViewport: TRectangle;
- procedure SetCamera(const Value: TgxCamera);
- procedure SetEnabledRenderBuffers(const Value: TgxEnabledRenderBuffers);
- procedure SetTargetVisibility(const Value: TgxFBOTargetVisibility);
- procedure SetBackgroundColor(const Value: TgxColor);
- function StoreSceneScaleFactor: Boolean;
- function StoreAspect: Boolean;
- procedure SetUseLibraryAsMultiTarget(Value: Boolean);
- procedure SetPostGenerateMipmap(const Value: Boolean);
- protected
- procedure Notification(AComponent: TComponent; Operation: TOperation); override;
- procedure Initialize;
- procedure ForceDimensions(Texture: TgxTexture);
- procedure RenderToFBO(var ARci: TgxRenderContextInfo);
- procedure ApplyCamera(var ARci: TgxRenderContextInfo);
- procedure UnApplyCamera(var ARci: TgxRenderContextInfo);
- procedure DoBeforeRender(var ARci: TgxRenderContextInfo);
- procedure DoAfterRender(var ARci: TgxRenderContextInfo);
- procedure DoPreInitialize;
- procedure DoPostInitialize;
- property HasColor: Boolean read FHasColor;
- property HasDepth: Boolean read FHasDepth;
- property HasStencil: Boolean read FHasStencil;
- property Viewport: TRectangle read GetViewport;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure DoRender(var ARci: TgxRenderContextInfo; ARenderSelf: Boolean; ARenderChildren: Boolean); override;
- (* Layer (also cube map face) is activated only on
- the volume textures, texture array and cube map.
- You can select the layer during the drawing to. *)
- property Layer: Integer read GetLayer write SetLayer;
- // Mipmap Level where will be rendering
- property Level: Integer read GetLevel write SetLevel;
- published
- property Active: Boolean read GetVisible write SetVisible default True;
- property PickableTarget: Boolean read GetPickable write SetPickable default False;
- { force texture dimensions when initializing
- only works with TgxBlankImage and GLfloatDataImage, otherwise does nothing }
- property ForceTextureDimensions: Boolean read FForceTextureDimensions write SetForceTextureDimentions default True;
- property Width: Integer read FWidth write SetWidth default 256;
- property Height: Integer read FHeight write SetHeight default 256;
- property Aspect: Single read FAspect write FAspect stored StoreAspect;
- property ColorTextureName: TgxLibMaterialName read FColorTextureName write SetColorTextureName;
- property DepthTextureName: TgxLibMaterialName read FDepthTextureName write SetDepthTextureName;
- property MaterialLibrary: TgxAbstractMaterialLibrary read GetMaterialLibrary write SetMaterialLibrary;
- property BackgroundColor: TgxColor read FBackgroundColor write SetBackgroundColor;
- property ClearOptions: TgxFBOClearOptions read FClearOptions write FClearOptions;
- { camera used for rendering to the FBO
- if not assigned, use the active view's camera }
- property Camera: TgxCamera read FCamera write SetCamera;
- { adjust the scene scale of the camera so that the rendering
- becomes independent of the width of the fbo renderer
- 0 = disabled }
- property SceneScaleFactor: Single read FSceneScaleFactor write FSceneScaleFactor stored StoreSceneScaleFactor;
- { root object used when rendering to the FBO
- if not assigned, uses itself as root and renders the child objects to the FBO }
- property RootObject: TgxBaseSceneObject read FRootObject write SetRootObject;
- { determines if target is rendered to FBO only or rendered normally
- in FBO only mode, if RootObject is assigned, the RootObject's Visible flag is modified
- in default mode, if RootObject is not assigned, children are rendered normally after being
- rendered to the FBO }
- property TargetVisibility: TgxFBOTargetVisibility read FTargetVisibility write SetTargetVisibility default tvDefault;
- { Enables the use of a render buffer if a texture is not assigned }
- property EnabledRenderBuffers: TgxEnabledRenderBuffers read FEnabledRenderBuffers write SetEnabledRenderBuffers;
- { use stencil buffer }
- property StencilPrecision: TgxStencilPrecision read FStencilPrecision write SetStencilPrecision default spDefault;
- { called before rendering to the FBO }
- property BeforeRender: TDirectRenderEvent read FBeforeRender write FBeforeRender;
- { called after the rendering to the FBO }
- property AfterRender: TDirectRenderEvent read FAfterRender write FAfterRender;
- { Called before the FBO is initialized
- the FBO is bound before calling this event }
- property PreInitialize: TNotifyEvent read FPreInitialize write FPreInitialize;
- { Called after the FBO is initialized, but before any rendering
- the FBO is bound before calling this event }
- property PostInitialize: TNotifyEvent read FPostInitialize write FPostInitialize;
- property UseLibraryAsMultiTarget: Boolean read FUseLibraryAsMultiTarget write SetUseLibraryAsMultiTarget default False;
- { Control mipmap generation after rendering
- texture must have MinFilter with mipmaping }
- property PostGenerateMipmap: Boolean read FPostGenerateMipmap write SetPostGenerateMipmap default True;
- { Allows multiTargeting to different texture sources instead of all coming
- from one single MatLib with UseLibraryAsMultiTarget. OnSetTextureTargets
- overrides the other method of setting target textures via the MaterialLibrary,
- ColorTextureName and DepthTextureName propertes }
- property OnSetTextureTargets: TSetTextureTargetsEvent read FOnSetTextureTargets write FOnSetTextureTargets;
- end;
- //------------------------------------------------------------------------------
- implementation
- //------------------------------------------------------------------------------
- //------------------------------------------------------------------------------
- // TgxFBORenderer
- //------------------------------------------------------------------------------
- procedure TgxFBORenderer.ApplyCamera(var ARci: TgxRenderContextInfo);
- var
- sc: Single;
- begin
- with ARci.PipelineTransformation do
- begin
- Push;
- if Assigned(Camera) then
- begin
- FStoreCamera[0] := ARci.cameraPosition;
- FStoreCamera[1] := ARci.cameraDirection;
- FStoreCamera[2] := ARci.cameraUp;
- IdentityAll;
- sc := FCamera.SceneScale;
- if FSceneScaleFactor > 0 then
- FCamera.SceneScale := Width / FSceneScaleFactor;
- FCamera.ApplyPerspective(Viewport, Width, Height, 96);
- // 96 is default dpi
- FCamera.SceneScale := sc;
- SetViewMatrix(CreateScaleMatrix(Vector3fMake(1.0 / FAspect, 1.0, 1.0)));
- FCamera.Apply;
- end
- else
- begin
- SetViewMatrix(MatrixMultiply(ViewMatrix^, CreateScaleMatrix(Vector3fMake(1.0 / FAspect, 1.0, 1.0))));
- end;
- end;
- end;
- procedure TgxFBORenderer.UnApplyCamera(var ARci: TgxRenderContextInfo);
- begin
- ARci.cameraPosition := FStoreCamera[0];
- ARci.cameraDirection := FStoreCamera[1];
- ARci.cameraUp := FStoreCamera[2];
- ARci.PipelineTransformation.Pop;
- end;
- constructor TgxFBORenderer.Create(AOwner: TComponent);
- begin
- inherited;
- ObjectStyle := [osDirectDraw, osNoVisibilityCulling];
- FFbo := TgxFrameBuffer.Create;
- FBackgroundColor := TgxColor.Create(Self);
- FUseLibraryAsMultiTarget := False;
- FForceTextureDimensions := True;
- FWidth := 256;
- FHeight := 256;
- FEnabledRenderBuffers := [erbDepth];
- FClearOptions := [coColorBufferClear, coDepthBufferClear, coStencilBufferClear, coUseBufferBackground];
- PickableTarget := False;
- FAspect := 1.0;
- FSceneScaleFactor := 0.0;
- FPostGenerateMipmap := True;
- StructureChanged;
- end;
- destructor TgxFBORenderer.Destroy;
- begin
- FFbo.Free;
- FDepthRBO.Free;
- FStencilRBO.Free;
- FBackgroundColor.Free;
- inherited;
- end;
- procedure TgxFBORenderer.Notification(AComponent: TComponent; Operation: TOperation);
- begin
- inherited;
- if (AComponent = FRootObject) and (Operation = opRemove) then
- FRootObject := nil;
- end;
- procedure TgxFBORenderer.DoAfterRender(var ARci: TgxRenderContextInfo);
- begin
- if Assigned(FAfterRender) then
- FAfterRender(Self, ARci);
- end;
- procedure TgxFBORenderer.DoBeforeRender(var ARci: TgxRenderContextInfo);
- begin
- if Assigned(FBeforeRender) then
- FBeforeRender(Self, ARci);
- end;
- procedure TgxFBORenderer.DoPostInitialize;
- begin
- if Assigned(FPostInitialize) then
- FPostInitialize(Self);
- end;
- procedure TgxFBORenderer.DoPreInitialize;
- begin
- if Assigned(FPreInitialize) then
- FPreInitialize(Self);
- end;
- procedure TgxFBORenderer.DoRender(var ARci: TgxRenderContextInfo; ARenderSelf, ARenderChildren: Boolean);
- begin
- if not(csDesigning in ComponentState) then
- RenderToFBO(ARci);
- if (not Assigned(FRootObject)) and (TargetVisibility = tvDefault) and ARenderChildren then
- RenderChildren(0, Count - 1, ARci);
- end;
- procedure TgxFBORenderer.ForceDimensions(Texture: TgxTexture);
- var
- bi: TgxBlankImage;
- mi: TgxMultisampleImage;
- begin
- if Texture.Image is TgxBlankImage then
- begin
- bi := TgxBlankImage(Texture.Image);
- bi.Width := Width;
- bi.Height := Height;
- end
- else if Texture.Image is TgxMultisampleImage then
- begin
- mi := TgxMultisampleImage(Texture.Image);
- mi.Width := Width;
- mi.Height := Height;
- end;
- end;
- function TgxFBORenderer.GetViewport: TRectangle;
- begin
- Result.Left := 0;
- Result.Top := 0;
- Result.Width := Width;
- Result.Height := Height;
- end;
- procedure TgxFBORenderer.Initialize;
- procedure AddOneMultiTarget(colorTex: TgxTexture);
- begin
- if ForceTextureDimensions then
- ForceDimensions(colorTex);
- if FColorAttachment >= FMaxAttachment then
- begin
- ShowMessage('Number of color attachments out of GL_MAX_COLOR_ATTACHMENTS');
- Visible := False;
- Abort;
- end;
- FFbo.AttachTexture(FColorAttachment, colorTex);
- Inc(FColorAttachment);
- end;
- const
- cDrawBuffers: array [0 .. 15] of GLenum = (GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2,
- GL_COLOR_ATTACHMENT3, GL_COLOR_ATTACHMENT4, GL_COLOR_ATTACHMENT5, GL_COLOR_ATTACHMENT6, GL_COLOR_ATTACHMENT7,
- GL_COLOR_ATTACHMENT8, GL_COLOR_ATTACHMENT9, GL_COLOR_ATTACHMENT10, GL_COLOR_ATTACHMENT11, GL_COLOR_ATTACHMENT12,
- GL_COLOR_ATTACHMENT13, GL_COLOR_ATTACHMENT14, GL_COLOR_ATTACHMENT15);
- var
- colorTex: TgxTexture;
- depthTex: TgxTexture;
- I: Integer;
- MulTexture: TgxTextureArray;
- begin
- for I := 0 to MaxColorAttachments - 1 do
- FFbo.DetachTexture(I);
- if FMaxSize = 0 then
- glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, @FMaxSize);
- if Width > FMaxSize then
- begin
- FWidth := FMaxSize;
- ShowMessage(Format('%s.Width out of GL_MAX_RENDERBUFFER_SIZE', [Name]));
- end;
- if Height > FMaxSize then
- begin
- FHeight := FMaxSize;
- ShowMessage(Format('%s.Height out of GL_MAX_RENDERBUFFER_SIZE', [Name]));
- end;
- FFbo.Width := Width;
- FFbo.Height := Height;
- FFbo.Bind;
- DoPreInitialize;
- FFbo.Unbind;
- if Assigned(FMaterialLibrary) then
- begin
- colorTex := FMaterialLibrary.TextureByName(ColorTextureName);
- depthTex := FMaterialLibrary.TextureByName(DepthTextureName);
- end
- else
- begin
- colorTex := nil;
- depthTex := nil;
- end;
- FHasColor := False;
- FHasDepth := False;
- FHasStencil := False;
- FColorAttachment := 0;
- if FUseLibraryAsMultiTarget or Assigned(FOnSetTextureTargets) then
- begin
- if FMaxAttachment = 0 then
- glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, @FMaxAttachment);
- if Assigned(FOnSetTextureTargets) then
- begin
- FOnSetTextureTargets(Self, MulTexture);
- for I := 0 to High(MulTexture) do
- begin
- colorTex := MulTexture[I];
- // Skip depth texture
- if colorTex = depthTex then
- Continue;
- AddOneMultiTarget(colorTex);
- end;
- end
- else
- // Multicolor attachments
- for I := 0 to FMaterialLibrary.Materials.Count - 1 do
- begin
- colorTex := FMaterialLibrary.Materials[I].Material.Texture;
- // Skip depth texture
- if colorTex = depthTex then
- Continue;
- AddOneMultiTarget(colorTex);
- end;
- FHasColor := FColorAttachment > 0;
- end
- else
- begin
- // One color attachment
- if Assigned(colorTex) then
- begin
- if ForceTextureDimensions then
- ForceDimensions(colorTex);
- FFbo.AttachTexture(0, colorTex);
- Inc(FColorAttachment);
- FHasColor := True;
- end;
- end;
- if Assigned(depthTex) then
- begin
- if ForceTextureDimensions then
- ForceDimensions(depthTex);
- FFbo.AttachDepthTexture(depthTex);
- FDepthRBO.Free;
- FDepthRBO := nil;
- FHasDepth := True;
- FHasStencil := depthTex.TextureFormatEx = tfDEPTH24_STENCIL8;
- end
- else if erbDepth in EnabledRenderBuffers then
- begin
- if not Assigned(FDepthRBO) then
- FDepthRBO := TgxDepthRBO.Create;
- FDepthRBO.Width := Width;
- FDepthRBO.Height := Height;
- FFbo.AttachDepthBuffer(FDepthRBO);
- FHasDepth := True;
- end
- else
- begin
- FFbo.DetachDepthBuffer;
- if Assigned(FDepthRBO) then
- begin
- FDepthRBO.Free;
- FDepthRBO := nil;
- end;
- end;
- if erbStencil in EnabledRenderBuffers then
- begin
- if not Assigned(FStencilRBO) then
- FStencilRBO := TgxStencilRBO.Create;
- FStencilRBO.StencilPrecision := FStencilPrecision;
- FStencilRBO.Width := Width;
- FStencilRBO.Height := Height;
- FFbo.AttachStencilBuffer(FStencilRBO);
- FHasStencil := True;
- end
- else
- begin
- if not FHasStencil then
- FFbo.DetachStencilBuffer;
- if Assigned(FStencilRBO) then
- begin
- FStencilRBO.Free;
- FStencilRBO := nil;
- end;
- end;
- FFbo.Bind;
- if FColorAttachment = 0 then
- begin
- glDrawBuffer(GL_NONE);
- glReadBuffer(GL_NONE);
- end
- else
- glDrawBuffers(FColorAttachment, @cDrawBuffers);
- DoPostInitialize;
- FFbo.Unbind;
- /// CheckOpenGLError;
- ClearStructureChanged;
- end;
- procedure TgxFBORenderer.RenderToFBO(var ARci: TgxRenderContextInfo);
- function GetClearBits: cardinal;
- begin
- Result := 0;
- if HasColor and (coColorBufferClear in FClearOptions) then
- Result := Result or GL_COLOR_BUFFER_BIT;
- if HasDepth and (coDepthBufferClear in FClearOptions) then
- Result := Result or GL_DEPTH_BUFFER_BIT;
- if HasStencil and (coStencilBufferClear in FClearOptions) then
- Result := Result or GL_STENCIL_BUFFER_BIT;
- end;
- type
- TgxStoredStates = record
- ColorClearValue: TgxColorVector;
- ColorWriteMask: TgxColorMask;
- Tests: TgxStates;
- end;
- function StoreStates: TgxStoredStates;
- begin
- Result.ColorClearValue := ARci.gxStates.ColorClearValue;
- Result.ColorWriteMask := ARci.gxStates.ColorWriteMask[0];
- Result.Tests := [stDepthTest, stStencilTest] * ARci.gxStates.States;
- end;
- procedure RestoreStates(const aStates: TgxStoredStates);
- begin
- ARci.gxStates.ColorClearValue := aStates.ColorClearValue;
- ARci.gxStates.SetColorMask(aStates.ColorWriteMask);
- if stDepthTest in aStates.Tests then
- ARci.gxStates.Enable(stDepthTest)
- else
- ARci.gxStates.Disable(stDepthTest);
- if stStencilTest in aStates.Tests then
- ARci.gxStates.Enable(stStencilTest)
- else
- ARci.gxStates.Disable(stStencilTest);
- end;
- var
- backColor: TgxColorVector;
- buffer: TgxSceneBuffer;
- savedStates: TgxStoredStates;
- w, h: Integer;
- s: string;
- begin
- if (ARci.drawState = dsPicking) and not PickableTarget then
- exit;
- if TgxFramebufferHandle.IsSupported = True then
- begin
- ShowMessage('Framebuffer not supported - deactivated');
- Active := False;
- exit;
- end;
- // prevent recursion
- if FRendering then
- exit;
- FRendering := True;
- if (ocStructure in Changes) or Assigned(FOnSetTextureTargets) then
- begin
- Initialize;
- if not Active then
- exit;
- end;
- ApplyCamera(ARci);
- try
- savedStates := StoreStates;
- FFbo.Bind;
- if FFbo.GetStringStatus(s) <> fsComplete then
- begin
- ShowMessage(Format('Framebuffer error: %s. Deactivated', [s]));
- Active := False;
- exit;
- end;
- DoBeforeRender(ARci);
- if Assigned(Camera) then
- Camera.Scene.SetupLights(ARci.gxStates.MaxLights);
- w := Width;
- h := Height;
- if FFbo.Level > 0 then
- begin
- w := w shr FFbo.Level;
- h := h shr FFbo.Level;
- if w = 0 then
- w := 1;
- if h = 0 then
- h := 1;
- end;
- ARci.gxStates.Viewport := Vector4iMake(0, 0, w, h);
- buffer := ARci.buffer as TgxSceneBuffer;
- if HasColor then
- ARci.gxStates.SetColorMask(cAllColorComponents)
- else
- ARci.gxStates.SetColorMask([]);
- ARci.gxStates.DepthWriteMask := HasDepth;
- if HasStencil then
- ARci.gxStates.Enable(stStencilTest)
- else
- ARci.gxStates.Disable(stStencilTest);
- if coUseBufferBackground in FClearOptions then
- begin
- backColor := ConvertWinColor(buffer.BackgroundColor);
- backColor.w := buffer.BackgroundAlpha;
- ARci.gxStates.ColorClearValue := backColor;
- end
- else
- begin
- ARci.gxStates.ColorClearValue := FBackgroundColor.Color;
- end;
- glClear(GetClearBits);
- FFbo.PreRender;
- // render to fbo
- if Assigned(RootObject) then
- begin
- // if object should only be rendered to the fbo
- // ensure it's visible before rendering to fbo
- if TargetVisibility = tvFBOOnly then
- RootObject.Visible := True;
- RootObject.Render(ARci);
- // then make it invisible afterwards
- if TargetVisibility = tvFBOOnly then
- RootObject.Visible := False;
- end
- else if (Count > 0) then
- RenderChildren(0, Count - 1, ARci);
- FFbo.PostRender(FPostGenerateMipmap);
- RestoreStates(savedStates);
- ARci.gxStates.Viewport := Vector4iMake(0, 0, ARci.viewPortSize.cx, ARci.viewPortSize.cy);
- finally
- FFbo.Unbind;
- FRendering := False;
- DoAfterRender(ARci);
- UnApplyCamera(ARci);
- if Assigned(Camera) then
- Camera.Scene.SetupLights(ARci.gxStates.MaxLights);
- end;
- end;
- procedure TgxFBORenderer.SetBackgroundColor(const Value: TgxColor);
- begin
- FBackgroundColor.Assign(Value);
- end;
- procedure TgxFBORenderer.SetCamera(const Value: TgxCamera);
- begin
- if FCamera <> Value then
- begin
- FCamera := Value;
- StructureChanged;
- end;
- end;
- procedure TgxFBORenderer.SetColorTextureName(const Value: TgxLibMaterialName);
- begin
- if FColorTextureName <> Value then
- begin
- FColorTextureName := Value;
- StructureChanged;
- end;
- end;
- procedure TgxFBORenderer.SetDepthTextureName(const Value: TgxLibMaterialName);
- begin
- if FDepthTextureName <> Value then
- begin
- FDepthTextureName := Value;
- StructureChanged;
- end;
- end;
- procedure TgxFBORenderer.SetEnabledRenderBuffers(const Value: TgxEnabledRenderBuffers);
- begin
- if FEnabledRenderBuffers <> Value then
- begin
- FEnabledRenderBuffers := Value;
- StructureChanged;
- end;
- end;
- procedure TgxFBORenderer.SetForceTextureDimentions(const Value: Boolean);
- begin
- if FForceTextureDimensions <> Value then
- begin
- FForceTextureDimensions := Value;
- StructureChanged;
- end;
- end;
- function TgxFBORenderer.GetMaterialLibrary: TgxAbstractMaterialLibrary;
- begin
- Result := FMaterialLibrary;
- end;
- procedure TgxFBORenderer.SetMaterialLibrary(const Value: TgxAbstractMaterialLibrary);
- begin
- if FMaterialLibrary <> Value then
- begin
- if Value is TgxMaterialLibrary then
- begin
- FMaterialLibrary := TgxMaterialLibrary(Value);
- StructureChanged;
- end;
- end;
- end;
- procedure TgxFBORenderer.SetUseLibraryAsMultiTarget(Value: Boolean);
- begin
- if FUseLibraryAsMultiTarget <> Value then
- begin
- FUseLibraryAsMultiTarget := Value;
- StructureChanged;
- end;
- end;
- procedure TgxFBORenderer.SetPostGenerateMipmap(const Value: Boolean);
- begin
- if FPostGenerateMipmap <> Value then
- FPostGenerateMipmap := Value;
- end;
- procedure TgxFBORenderer.SetRootObject(const Value: TgxBaseSceneObject);
- begin
- if FRootObject <> Value then
- begin
- if Assigned(FRootObject) then
- FRootObject.RemoveFreeNotification(Self);
- FRootObject := Value;
- if Assigned(FRootObject) then
- FRootObject.FreeNotification(Self);
- StructureChanged;
- end;
- end;
- procedure TgxFBORenderer.SetStencilPrecision(const Value: TgxStencilPrecision);
- begin
- if FStencilPrecision <> Value then
- begin
- FStencilPrecision := Value;
- StructureChanged;
- end;
- end;
- procedure TgxFBORenderer.SetTargetVisibility(const Value: TgxFBOTargetVisibility);
- begin
- if FTargetVisibility <> Value then
- begin
- if Assigned(RootObject) then
- begin
- if (TargetVisibility = tvFBOOnly) then
- begin
- // we went from fbo only, restore root's old visibility
- RootObject.Visible := FRootVisible;
- end
- else
- begin
- // we're going to fbo only, save root visibility for later
- FRootVisible := RootObject.Visible;
- end;
- end;
- FTargetVisibility := Value;
- StructureChanged;
- end;
- end;
- function TgxFBORenderer.StoreSceneScaleFactor: Boolean;
- begin
- Result := (FSceneScaleFactor <> 0.0);
- end;
- function TgxFBORenderer.StoreAspect: Boolean;
- begin
- Result := (FAspect <> 1.0);
- end;
- procedure TgxFBORenderer.SetWidth(Value: Integer);
- begin
- if FWidth <> Value then
- begin
- FWidth := Value;
- StructureChanged;
- end;
- end;
- procedure TgxFBORenderer.SetHeight(Value: Integer);
- begin
- if FHeight <> Value then
- begin
- FHeight := Value;
- StructureChanged;
- end;
- end;
- procedure TgxFBORenderer.SetLayer(const Value: Integer);
- begin
- if Value <> FFbo.Layer then
- begin
- if FRendering or (ocStructure in Changes) then
- FFbo.Layer := Value
- else
- begin
- FFbo.Bind;
- FFbo.Layer := Value;
- FFbo.Unbind;
- end;
- end;
- end;
- function TgxFBORenderer.GetLayer: Integer;
- begin
- Result := FFbo.Layer;
- end;
- procedure TgxFBORenderer.SetLevel(const Value: Integer);
- var
- w, h: Integer;
- begin
- if Value <> FFbo.Level then
- begin
- if FRendering or (ocStructure in Changes) then
- begin
- FFbo.Level := Value;
- w := Width;
- h := Height;
- if FFbo.Level > 0 then
- begin
- w := w shr FFbo.Level;
- h := h shr FFbo.Level;
- if w = 0 then
- w := 1;
- if h = 0 then
- h := 1;
- CurrentContext.gxStates.Viewport := Vector4iMake(0, 0, w, h);
- end;
- end
- else
- begin
- FFbo.Bind;
- FFbo.Level := Value;
- FFbo.Unbind;
- end;
- end;
- end;
- function TgxFBORenderer.GetLevel: Integer;
- begin
- Result := FFbo.Level;
- end;
- //-------------------------------------------------------------------
- initialization
- //-------------------------------------------------------------------
- RegisterClasses([TgxFBORenderer]);
- end.
|