/// <summary> /// Renders a solar system /// </summary> /// <param name="solarSystem">The scene</param> /// <param name="camera">Scene camera</param> /// <param name="context">Rendering context</param> public virtual void Render( ISolarSystem solarSystem, IUniCamera camera, IRenderContext context ) { Arguments.CheckNotNull( solarSystem, "solarSystem" ); Arguments.CheckNotNull( camera, "camera" ); UniRenderContext uniContext = new UniRenderContext( camera, context ); uniContext.Camera = camera; // Render far objects uniContext.CurrentPass = UniRenderPass.FarObjects; solarSystem.Render( uniContext ); Graphics.Renderer.ClearDepth( 1.0f ); // Render close objects uniContext.CurrentPass = UniRenderPass.CloseObjects; solarSystem.Render( uniContext ); }
/// <summary> /// Renders the scene /// </summary> /// <param name="solarSystem">The scene</param> /// <param name="camera">Scene camera</param> /// <param name="context">Rendering context</param> public override void Render( ISolarSystem solarSystem, IUniCamera camera, IRenderContext context ) { Arguments.CheckNotNull( solarSystem, "solarSystem" ); Arguments.CheckNotNull( camera, "camera" ); PreRender( ); UniRenderContext uniContext = new UniRenderContext( camera, context ); uniContext.SetRenderTarget( UniRenderTargets.OceanReflections, m_OceanReflections ); uniContext.Camera = camera; // TODO: Render close geometry into stencil buffer or Z buffer to early-out far object rendering) // (careful with alpha blending) // Useful only really for very expensive atmosphere rendering - we only want to calculate // scattering equations for visible pixels. // Have separate far/close methods for rendering atmospheres? // Render far away objects into the back buffer uniContext.CurrentPass = UniRenderPass.FarObjects; solarSystem.Render( uniContext ); // Clear the depth buffer before rendering close objects RbGraphics.Renderer.ClearDepth( 1.0f ); // Render close object reflection geometry into a render target if ( EnableReflections ) { RenderReflections( uniContext, solarSystem ); } // Render close object shadow geometry into a render target // TODO: ... uniContext.Camera.Begin( ); // Render close objects uniContext.CurrentPass = UniRenderPass.CloseObjects; solarSystem.Render( uniContext ); uniContext.Camera.End( ); // TODO: Render fullscreen quad over back buffer, for post-process effects }
/// <summary> /// Renders reflections /// </summary> private void RenderReflections( UniRenderContext uniContext, ISolarSystem solarSystem ) { IPlanet planet = FindClosestPlanet( uniContext.Camera, solarSystem, double.MaxValue ); if ( planet == null ) { // No close planets == no reflections to render return; } IPlanetReflectiveOceanRenderer reflectionRenderer = planet.Renderer.GetRenderer<IPlanetReflectiveOceanRenderer>( ); if ( reflectionRenderer == null ) { // Planet doesn't have a reflective ocean return; } IUniCamera currentCamera = uniContext.Camera; Point3 pointOnPlane; Plane3 plane = reflectionRenderer.GetTangentPlaneUnderPoint( uniContext.Camera.Position, out pointOnPlane ); Point3 localCameraPosition = ( uniContext.Camera.Position - planet.Transform.Position ).ToRenderUnits( ); Point3 rCamPos = pointOnPlane + plane.Normal * ( pointOnPlane.DistanceTo( localCameraPosition ) ); InvariantMatrix44 reflectionMatrix = Matrix44.MakeReflectionMatrix( Point3.Origin, plane.Normal ); long x = planet.Transform.Position.X + ( long )( rCamPos.X * Units.Convert.MulRenderToUni ); long y = planet.Transform.Position.Y + ( long )( rCamPos.Y * Units.Convert.MulRenderToUni ); long z = planet.Transform.Position.Z + ( long )( rCamPos.Z * Units.Convert.MulRenderToUni ); UniCamera reflectedCamera = new UniCamera( ); reflectedCamera.Frame = reflectionMatrix * currentCamera.Frame; reflectedCamera.Position = new UniPoint3( x, y, z ); reflectedCamera.PerspectiveZNear = currentCamera.PerspectiveZNear; reflectedCamera.PerspectiveZFar = currentCamera.PerspectiveZFar; uniContext.Camera = reflectedCamera; // Get the tangent space //Matrix44 tangentSpaceMatrix = new Matrix44( ); //reflectionRenderer.Setup( tangentSpaceMatrix ); // TODO: Invert camera around reflection plane m_OceanReflections.Begin( ); RbGraphics.Renderer.ClearDepth( 1.0f ); RbGraphics.Renderer.ClearColour( Color.Black ); reflectedCamera.Begin( ); // RbGraphics.Renderer.PushTransformPostModifier( TransformType.LocalToWorld, reflectionMatrix ); uniContext.CurrentPass = UniRenderPass.CloseReflectedObjects; solarSystem.Render( uniContext ); m_OceanReflections.End( ); // RbGraphics.Renderer.PopTransformPostModifier( TransformType.LocalToWorld ); reflectedCamera.End( ); uniContext.Camera = currentCamera; }