/// <summary>
/// Prompts the class to send its contents to the renderer.
/// </summary>
/// <remarks>
/// This method prompts the scene manager to send the
/// contents of the scene it manages to the rendering
/// pipeline, possibly preceded by some sorting, culling
/// or other scene management tasks. Note that this method is not normally called
/// directly by the user application; it is called automatically
/// by the engine's rendering loop.
/// </remarks>
/// <param name="camera">Pointer to a camera from whose viewpoint the scene is to be rendered.</param>
/// <param name="viewport">The target viewport</param>
/// <param name="showOverlays">Whether or not any overlay objects should be rendered</param>
protected internal void RenderScene( Camera camera, Viewport viewport, bool showOverlays )
{
// let the engine know this is the current scene manager
Root.Instance.SceneManager = this;
if ( this.IsShadowTechniqueInUse )
{
// initialize shadow volume materials
this.InitShadowVolumeMaterials();
}
// Perform a quick pre-check to see whether we should override far distance
// When using stencil volumes we have to use infinite far distance
// to prevent dark caps getting clipped
if ( this.IsShadowTechniqueStencilBased &&
camera.Far != 0 &&
this.targetRenderSystem.Capabilities.HasCapability( Capabilities.InfiniteFarPlane ) &&
this.shadowUseInfiniteFarPlane )
{
// infinite far distance
camera.Far = 0.0f;
}
this.cameraInProgress = camera;
this.hasCameraChanged = true;
// Update the scene, only do this once per frame
ulong thisFrameNumber = Root.Instance.CurrentFrameCount;
if ( thisFrameNumber != this.lastFrameNumber )
{
// Update animations
this.ApplySceneAnimations();
// Update controllers
ControllerManager.Instance.UpdateAll();
this.lastFrameNumber = thisFrameNumber;
}
// Update scene graph for this camera (can happen multiple times per frame)
this.UpdateSceneGraph( camera );
// Auto-track nodes
foreach ( SceneNode sn in autoTrackingSceneNodes.Values )
{
sn.AutoTrack();
}
// ask the camera to auto track if it has a target
camera.AutoTrack();
// Are we using any shadows at all?
if ( this.IsShadowTechniqueInUse && this.illuminationStage != IlluminationRenderStage.RenderToTexture &&
viewport.ShowShadows && this.findVisibleObjects )
{
// Locate any lights which could be affecting the frustum
this.FindLightsAffectingFrustum( camera );
if ( this.IsShadowTechniqueTextureBased )
{
// *******
// WARNING
// *******
// This call will result in re-entrant calls to this method
// therefore anything which comes before this is NOT
// guaranteed persistent. Make sure that anything which
// MUST be specific to this camera / target is done
// AFTER THIS POINT
this.PrepareShadowTextures( camera, viewport );
// reset the cameras because of the re-entrant call
this.cameraInProgress = camera;
this.hasCameraChanged = true;
}
}
// Invert vertex winding?
this.targetRenderSystem.InvertVertexWinding = camera.IsReflected;
// Tell params about viewport
this.autoParamDataSource.Viewport = viewport;
// Set the viewport
this.SetViewport( viewport );
// set the current camera for use in the auto GPU program params
this.autoParamDataSource.Camera = camera;
// Set autoparams for finite dir light extrusion
this.autoParamDataSource.SetShadowDirLightExtrusionDistance( this.shadowDirLightExtrudeDist );
// sets the current ambient light color for use in auto GPU program params
this.autoParamDataSource.AmbientLight = this.ambientColor;
// Tell rendersystem
this.targetRenderSystem.AmbientLight = this.ambientColor;
// Tell params about render target
this.autoParamDataSource.RenderTarget = viewport.Target;
// set fog params
float fogScale = 1f;
if ( this.fogMode == FogMode.None )
{
fogScale = 0f;
}
this.autoParamDataSource.FogParams = new Vector4( this.fogStart, this.fogEnd, fogScale, 0 );
// set the time in the auto param data source
//autoParamDataSource.Time = ((float)Root.Instance.Timer.Milliseconds) / 1000f;
// Set camera window clipping planes (if any)
if ( this.targetRenderSystem.Capabilities.HasCapability( Capabilities.UserClipPlanes ) )
{
// TODO: Add ClipPlanes to RenderSystem.cs
if ( camera.IsWindowSet )
{
targetRenderSystem.ResetClipPlanes();
IList<Plane> planeList = camera.WindowPlanes;
for ( ushort i = 0; i < 4; ++i )
{
targetRenderSystem.AddClipPlane( planeList[ i ] );
//this.targetRenderSystem.EnableClipPlane( i, true );
//this.targetRenderSystem.SetClipPlane( i, planeList[ i ] );
}
}
// this disables any user-set clipplanes... this should be done manually
//else
//{
// for (ushort i = 0; i < 4; ++i)
// {
// targetRenderSystem.EnableClipPlane(i, false);
// }
//}
}
// Prepare render queue for receiving new objects
this.PrepareRenderQueue();
// Parse the scene and tag visibles
if ( this.findVisibleObjects )
{
if ( this.PreFindVisibleObjects != null )
PreFindVisibleObjects( this, this.illuminationStage, viewport );
this.FindVisibleObjects( camera, this.illuminationStage == IlluminationRenderStage.RenderToTexture );
if ( this.PostFindVisibleObjects != null )
PostFindVisibleObjects( this, this.illuminationStage, viewport );
}
// Add overlays, if viewport deems it
if ( viewport.ShowOverlays && this.illuminationStage != IlluminationRenderStage.RenderToTexture )
{
// Queue overlays for rendering
OverlayManager.Instance.QueueOverlaysForRendering( camera, this.GetRenderQueue(), viewport );
}
// queue overlays and skyboxes for rendering
if ( viewport.ShowSkies && this.findVisibleObjects &&
this.illuminationStage != IlluminationRenderStage.RenderToTexture )
{
this.QueueSkiesForRendering( camera );
}
// begin frame geometry count
this.targetRenderSystem.BeginGeometryCount();
// clear the device if need be
if ( viewport.ClearEveryFrame )
{
this.targetRenderSystem.ClearFrameBuffer( viewport.ClearBuffers, viewport.BackgroundColor );
}
// being a frame of animation
this.targetRenderSystem.BeginFrame();
// use the camera's current scene detail level
this.targetRenderSystem.PolygonMode = camera.PolygonMode;
// Set initial camera state
this.targetRenderSystem.ProjectionMatrix = camera.ProjectionMatrixRS;
this.targetRenderSystem.ViewMatrix = camera.ViewMatrix;
// render all visible objects
this.RenderVisibleObjects();
// end the current frame
this.targetRenderSystem.EndFrame();
// Notify camera of the number of rendered faces
camera.NotifyRenderedFaces( this.targetRenderSystem.FaceCount );
// Notify camera of the number of rendered batches
camera.NotifyRenderedBatches( this.targetRenderSystem.BatchCount );
}