/// <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 ); }