| Description | Hierarchy | Fields | Methods | Properties |
type TVRMLFlatSceneGL = class(TVRMLFLatScene)
This is a descendant of TVRMLFlatScene that makes it easy to render VRML scene into OpenGL. The point is that this class is the final, comfortable utility to deal with VRML files when you want to be able to render them using OpenGL.
This class uses internal TVRMLOpenGLRenderer instance, thus hiding some "cumbersomness" (is it English?) of the interface of TVRMLOpenGLRenderer class. Also this class provides some functionality (like transparency using OpenGL blending) and some optimizations (like using OpenGL's display lists) that couldn't be achieved inside TVRMLOpenGLRenderer class (because they require looking at rendered VRML model as a whole, not only as a separate ShapeNode+State parts). See Render method for more details.
Also this class can provide comfortable management for TBackgroundGL instance associated with this VRML model, that may be used to render VRML's background. See Background function.
Connection with particular OpenGL context: from the 1st call of [Prepare]Render or Background methods to the next call of CloseGL method or the destructor. Everything between must be called within the same OpenGL context active. In particular: remember that if you called Render method at least once, you must destroy this object or at least call it's CloseGL method before releasing OpenGL context (that was active during Render).
![]() |
constructor Create(ARootNode: TVRMLNode; AOwnsRootNode: boolean; AOptimization: TGLRendererOptimization; ACache: TVRMLOpenGLRendererContextCache = nil); |
![]() |
constructor CreateProvidedRenderer( ARootNode: TVRMLNode; AOwnsRootNode: boolean; AOptimization: TGLRendererOptimization; AProvidedRenderer: TVRMLOpenGLRenderer); |
![]() |
destructor Destroy; override; |
![]() |
procedure CloseGL; |
![]() |
procedure PrepareRender( TransparentGroups: TTransparentGroups; Options: TPrepareRenderOptions); |
![]() |
procedure Render(TestShapeStateVisibility: TTestShapeStateVisibility; TransparentGroup: TTransparentGroup); |
![]() |
procedure RenderFrustum(const Frustum: TFrustum; TransparentGroup: TTransparentGroup); |
![]() |
procedure RenderFrustumOctree(const Frustum: TFrustum; Octree: TVRMLShapeStateOctree; TransparentGroup: TTransparentGroup); overload; |
![]() |
procedure RenderFrustumOctree(const Frustum: TFrustum; TransparentGroup: TTransparentGroup); overload; |
![]() |
procedure ChangedAll; override; |
![]() |
procedure ChangedShapeStateFields(ShapeStateNum: integer); override; |
![]() |
procedure RenderShadowVolume( const LightPos: TVector4Single; const TransformIsIdentity: boolean; const Transform: TMatrix4Single; const LightCap: boolean; const DarkCap: boolean; const AllowSilhouetteOptimization: boolean = true); |
![]() |
procedure RenderShadowVolume( ShadowVolumesHelper: TShadowVolumesHelper; const TransformIsIdentity: boolean; const Transform: TMatrix4Single; const AllowSilhouetteOptimization: boolean = true); |
![]() |
procedure InitAndRenderShadowVolume( ShadowVolumesHelper: TShadowVolumesHelper; const TransformIsIdentity: boolean; const Transform: TMatrix4Single; const AllowSilhouetteOptimization: boolean = true); |
![]() |
procedure PrepareBackground; |
![]() |
function Background: TBackgroundGL; |
![]() |
function Attributes: TVRMLSceneRenderingAttributes; |
![]() |
function CreateHeadLight: TVRMLGLHeadLight; |
![]() |
function BumpMappingMethod: TBumpMappingMethod; |
![]() |
property LastRender_RenderedShapeStatesCount: Cardinal
read FLastRender_RenderedShapeStatesCount; |
![]() |
property LastRender_AllShapeStatesCount: Cardinal
read FLastRender_AllShapeStatesCount; |
![]() |
property Optimization: TGLRendererOptimization read FOptimization; |
![]() |
property BackgroundSkySphereRadius: Single
read FBackgroundSkySphereRadius write SetBackgroundSkySphereRadius; |
![]() |
property BumpMappingLightPosition: TVector3Single
read GetBumpMappingLightPosition write SetBumpMappingLightPosition; |
![]() |
property BumpMappingLightAmbientColor: TVector4Single
read GetBumpMappingLightAmbientColor write SetBumpMappingLightAmbientColor; |
![]() |
property BumpMappingLightDiffuseColor: TVector4Single
read GetBumpMappingLightDiffuseColor write SetBumpMappingLightDiffuseColor; |
![]() |
constructor Create(ARootNode: TVRMLNode; AOwnsRootNode: boolean; AOptimization: TGLRendererOptimization; ACache: TVRMLOpenGLRendererContextCache = nil); |
![]() |
constructor CreateProvidedRenderer( ARootNode: TVRMLNode; AOwnsRootNode: boolean; AOptimization: TGLRendererOptimization; AProvidedRenderer: TVRMLOpenGLRenderer); |
|
A very special constructor, that forces this class to use provided AProvidedRenderer. Note that this renderer must be created with AttributesClass = TVRMLSceneRenderingAttributes. Don't use this unless you really know what you're doing! In all normal circumstances you should use normal Create constructor, that will internally create and use internal renderer object. If you use this constructor you will have to understand how internally this class synchronizes itself with underlying Renderer object. Once again, if you're not sure, then simply don't use this constructor. It's for internal use — namely it's internally used by TVRMLGLAnimation, this way all scenes of the animation share the same renderer which means that they also share the same information about textures and images loaded into OpenGL. And this is crucial for TVRMLGLAnimation, otherwise animation with 100 scenes would load the same texture to OpenGL 100 times. | |
![]() |
destructor Destroy; override; |
![]() |
procedure CloseGL; |
|
Destroy any associations of this object with current OpenGL context. For example, releaseany allocated texture or display list names. Generally speaking, destroys everything that is allocated by PrepareRender([...], []) call. It's harmless to call this method when there are already no associations with current OpenGL context. This is called automatically from the destructor. | |
![]() |
procedure PrepareRender( TransparentGroups: TTransparentGroups; Options: TPrepareRenderOptions); |
|
This prepares some internal things in this class, making sure that appropriate methods execute as fast as possible. In most cases, it's not strictly required to call this method — most things will be prepared "as needed" anyway. But this means that some calls may sometimes take a long time, e.g. the first Render call will take a long time because it may have to prepare display lists that will be reused in next Render calls. This may cause a strange behavior of the program: rendering of the first frame takes unusually long time (which confuses user, and also makes things like TGLWindow.FpsCompSpeed strange for a short time). So calling this procedure may be desirable. You may want to show to user that "now we're preparing the VRML scene — please wait". This method ties this object to current OpenGL context. But it doesn't change any OpenGL state or buffers contents (at most, it allocates some texture and display list names).
Parameters
| |
![]() |
procedure Render(TestShapeStateVisibility: TTestShapeStateVisibility; TransparentGroup: TTransparentGroup); |
|
Renders this VRML scene for OpenGL. This is probably the most important function in this class, usually it is the very reason why this class is used. It uses internal TVRMLOpenGLRenderer instance. Although this internal object is not accessible to your code, you can get some detailed info about how rendering into OpenGL works by looking at comments in VRMLOpenGLRenderer unit. Each call to Render renders the scene, roughly executing the same OpenGL commands as would be done by calling following methods of TVRMLOpenGLRenderer instance:
If Optimization = roSceneAsAWhole, TestShapeStateVisibility is ignored (because then rendering call almost always does not have such detailed control over which shapestates are actually rendered). So generally you should think of TestShapeStateVisibility as a way to optimize rendering, by quickly eliminating whole shapestates that you know are not visible (e.g. you know that their BoundingBox is outside current camera frustum). Don't try to put Render inside OpenGL's display-list, the point is that Render can internally create such display-list and manage it itself. So you don't have to worry about such things. This also means that code using this class doesn't care about complexity of using VRMLOpenGLRenderer (and care only about complexity of using this class, TVRMLFlatSceneGL :) ). Some additional notes (specific to
| |
![]() |
procedure RenderFrustum(const Frustum: TFrustum; TransparentGroup: TTransparentGroup); |
|
This calls Render passing TestShapeStateVisibility that tries to quickly eliminate ShapeStates that are entirely not within Frustum. In other words, this does so-called "frustum culling". | |
![]() |
procedure RenderFrustumOctree(const Frustum: TFrustum; Octree: TVRMLShapeStateOctree; TransparentGroup: TTransparentGroup); overload; |
|
This is like RenderFrustum but it tries to enumerate visible ShapeStates using given Octree (instead of just testing each ShapeState separately). This way it may work much faster when you have many ShapeStates. Note that if Optimization = roSceneAsAWhole this doesn't use Octree, but simply calls Render(nil). That's because when Optimization = roSceneAsAWhole Render always renders the whole scene, ignores TestShapeStateVisibility function, so it's useless (and would waste some time) to analyze the scene with Octree. | |
![]() |
procedure RenderFrustumOctree(const Frustum: TFrustum; TransparentGroup: TTransparentGroup); overload; |
|
This simply calls | |
![]() |
procedure ChangedAll; override; |
![]() |
procedure ChangedShapeStateFields(ShapeStateNum: integer); override; |
![]() |
procedure RenderShadowVolume( const LightPos: TVector4Single; const TransformIsIdentity: boolean; const Transform: TMatrix4Single; const LightCap: boolean; const DarkCap: boolean; const AllowSilhouetteOptimization: boolean = true); |
|
Render shadow volume (sides and caps) of this scene, for shadow volume algorithm. There are two underlying algorithms here, and their speed difference is very noticeable:
All shadow quads are generated from scene triangles transformed by Transform. This must be able to correctly detect front and back facing triangles with respect to LightPos, so "LightPos" and "scene transformed by Transform" must be in the same coordinate system. (That's why explicit Transform parameter is needed, you can't get away with simply doing glPush/PopMatrix and glMustMatrix around RenderShadowVolume call.) If TransformIsIdentity then Transform value is ignored and everything works like Transform = identity matrix (and is a little faster in this special case). This uses TrianglesList(false) and ManifoldEdges and BorderEdges (so you may prefer to prepare it before, e.g. by calling PrepareRender with prShadowVolume included). LightPos is the light position. LightPos[3] must be 1 (to indicate positional light) or 0 (a directional light). LightCap and DarkCap say whether you want to cap your shadow volume. LightCap is the cap at the caster position, DarkCap is the cap in infinity. This is needed by z-fail method, you should set them both to For ShadowVolumesHelper version, LightPos, LightCap and DarkCap are already available in ShadowVolumesHelper properties (set by ShadowVolumesHelper.InitFrustumAndLight and ShadowVolumesHelper.InitScene calls). Faces (both shadow quads and caps) are rendered such that CCW <=> you're looking at it from outside (i.e. it's considered front face of this shadow volume). All the commands passed to OpenGL by this methods are: glBegin, sequence of glVertex, then glEnd. | |
![]() |
procedure RenderShadowVolume( ShadowVolumesHelper: TShadowVolumesHelper; const TransformIsIdentity: boolean; const Transform: TMatrix4Single; const AllowSilhouetteOptimization: boolean = true); |
![]() |
procedure InitAndRenderShadowVolume( ShadowVolumesHelper: TShadowVolumesHelper; const TransformIsIdentity: boolean; const Transform: TMatrix4Single; const AllowSilhouetteOptimization: boolean = true); |
|
A shortcut for ShadowVolumesHelper.InitScene and then RenderShadowVolume. It will calculate current bounding box using Transform, TransformIsIdentity and BoundingBox method. | |
![]() |
procedure PrepareBackground; |
|
= 1 | |
![]() |
function Background: TBackgroundGL; |
|
Returns TBackgroundGL instance for this scene. Background's properties are based on the attributes of first "Background" VRML node in the RootNode scene (and on his place in scene transformations). They are also based on current value of BackgroundSkySphereRadius. And on the values of Attributes.ColorModulatorSingle/Byte. If there is no "Background" node in VRML scene this function returns nil. Note: this Background object is managed (automatically created/freed etc.) by this TVRMLFlatSceneGL object but it is NOT used anywhere in this class, e.g. Render does not call Background.Render. If you want to use this Background somehow, you have to do this yourself. The results of this function are internally cached. Cache is invalidated on such situations as change in RootNode scene, changes to BackgroundSkySphereRadius, CloseGL, Attributes.ColorModulatorSingle/Byte. PrepareBackground (and PrepareRender(true, ...)) automatically validate this cache. Remember that this cache is connected with the current OpenGL context. So you HAVE to call CloseGL to disconnent this object from current OpenGL context after you used this function. | |
![]() |
function Attributes: TVRMLSceneRenderingAttributes; |
|
Rendering attributes. You are free to change them all at any time. Although note that changing some attributes (the ones defined in base TVRMLRenderingAttributes class) may be a costly operation (next PrepareRender or Render call may need to recalculate some things, some display lists need to be rebuild etc.). So don't change them e.g. every frame. You should use Optimization = roNone if you really have to change attributes every frame. Note for ColorModulatorSingle/Byte properties: In addition to effects described at TVRMLOpenGLRenderer, they also affect what the TVRMLFlatSceneGL.Background function returns. | |
![]() |
function CreateHeadLight: TVRMLGLHeadLight; |
|
Creates a headlight, using (if present) KambiHeadLight node defined in this VRML file. You're responsible for freeing this node. Note that this is not concerned whether you actually should use this headlight (this information usually comes from NavigationInfo.headlight value). | |
![]() |
function BumpMappingMethod: TBumpMappingMethod; |
|
Which bump mapping method will be used ?
This is decided and controlled internally, based on Attributes.BumpMappingMaximum, Attributes.EnableTextures, and current OpenGL capabilities. So the only use of this function is when you want to report this to user, or for debug purposes etc. Note that calling this ties us to current OpenGL context. See also
| |
![]() |
property LastRender_RenderedShapeStatesCount: Cardinal
read FLastRender_RenderedShapeStatesCount; |
|
LastRender_ properties provide you read-only statistics about what happened during last render. For now you can see how many ShapeStates were rendered (i.e. send to OpenGL pipeline) versus all ShapeStates that were available (this is simply copied from ShapeStates.Count). This way you can see how effective was frustum culling (for RenderFrustum or RenderFrustumOctree) or how effective was your function TestShapeStateVisibility (if you used directly Render). "Effective" in the meaning "effective at eliminating invisible ShapeStates from rendering pipeline". These are initially equal to zeros. Then they are updated each time you called RenderFrustumOctree or RenderFrustum or Render. | |
![]() |
property LastRender_AllShapeStatesCount: Cardinal
read FLastRender_AllShapeStatesCount; |
![]() |
property Optimization: TGLRendererOptimization read FOptimization; |
|
This is the only way how you can control internal behavior of this class with regards to OpenGL display lists. You have to decide which method is best, based on expected usage of this model: Are you going to (often) change the model structure at runtime ? Is user going to see the scene usually as a whole, or only small part of it (more precisely, is frustum culling sensible in this case) ? See VRMLRendererOptimization.TGLRendererOptimization for discussion about various values you can set here. Currently this is read-only after you created | |
![]() |
property BackgroundSkySphereRadius: Single
read FBackgroundSkySphereRadius write SetBackgroundSkySphereRadius; |
![]() |
property BumpMappingLightPosition: TVector3Single
read GetBumpMappingLightPosition write SetBumpMappingLightPosition; |
|
Light position used for bump mapping. This is meaningful only if you enabled bump mapping and we are actually able to use bump mapping ( You can change this at any time, and we will automatically do everything needed to properly update this on next render. But note that when BumpMappingMethod = one of bmMultiTexAll values, changing In other words: if you plan to change
But roNone means that you lose some other optimizations, so it may be not desirable... in pratice, it's usually best decision to not update | |
![]() |
property BumpMappingLightAmbientColor: TVector4Single
read GetBumpMappingLightAmbientColor write SetBumpMappingLightAmbientColor; |
|
Ambient color of light used for bump mapping. This property simply controls corresponding property of underlying Renderer instance, see TVRMLOpenGLRenderer.BumpMappingLightAmbientColor. | |
![]() |
property BumpMappingLightDiffuseColor: TVector4Single
read GetBumpMappingLightDiffuseColor write SetBumpMappingLightDiffuseColor; |
|
Diffuse color of light used for bump mapping. This property simply controls corresponding property of underlying Renderer instance, see TVRMLOpenGLRenderer.BumpMappingLightDiffuseColor. | |