/// <summary> /// Setup constructor /// </summary> public UniRenderer( ISolarSystem scene, IUniCamera camera, ISolarSystemRenderer sceneRenderer ) { Arguments.CheckNotNull( scene, "scene" ); Arguments.CheckNotNull( camera, "camera" ); Arguments.CheckNotNull( sceneRenderer, "sceneRenderer" ); m_Scene = scene; m_Camera = camera; m_Renderer = sceneRenderer; }
/// <summary> /// Sets the default camera position above a planet /// </summary> /// <param name="camera"></param> protected override void SetDefaultCameraPosition( IUniCamera camera ) { // Move the camera up to the surface of the planet Units.Metres cameraHeight; IPlanetTerrainModel terrain = Planet.Model.GetModel<IPlanetTerrainModel>( ); if ( terrain != null ) { cameraHeight = terrain.MaximumHeight; } else { cameraHeight = new Units.Metres( 1000 ); } cameraHeight += m_Planet.Model.Radius; camera.Position.Set( cameraHeight.ToUniUnits, 0, 0 ); }
/// <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> /// Handles loading this control. Creates a viewer that can render the terrain model /// </summary> private void UniCameraViewControl_Load( object sender, EventArgs e ) { m_Camera = CreateCamera( ); Viewer viewer = new Viewer( ); display.AddViewer( viewer ); display.AllowArrowKeyInputs = true; viewer.Camera = m_Camera; CommandControlInputSource.StartMonitoring( CommandUser.Default, display, FirstPersonCameraCommands.DefaultBindings ); CommandUser.Default.CommandTriggered += OnCommandTriggered; // If planet was already assigned prior to Load, add it to all views AddRenderableToViewers( ); // TODO: AP: Horrible bodge to work around InteractionUpdateTimer not working properly without manual intervention display.OnBeginRender += delegate { InteractionUpdateTimer.Instance.OnUpdate( ); }; if ( InitializeRendering != null ) { InitializeRendering( this, EventArgs.Empty ); } }
/// <summary> /// Updates patches prior to rendering /// </summary> /// <param name="camera">Camera that LOD is calculated relative to</param> private void UpdatePatches( IUniCamera camera ) { Point3 localPos = Units.RenderUnits.MakeRelativePoint( Planet.Transform.Position, camera.Position ); ITerrainPatchGenerator generator = ( ITerrainPatchGenerator )Planet.PlanetModel.TerrainModel; foreach ( TerrainPatch patch in m_RootPatches ) { patch.UpdateLod( localPos, generator, camera ); } foreach ( TerrainPatch patch in m_RootPatches ) { patch.Update( camera, generator ); } }
private void SetupRenderUnitAtmosphereEffectParameters( IUniCamera camera, IEffect effect ) { Point3 localPos = Units.RenderUnits.MakeRelativePoint( Planet.Transform.Position, camera.Position ); float planetRadius = SpherePlanet.PlanetModel.Radius.ToRenderUnits; float atmosphereRadius = SpherePlanet.PlanetModel.AtmosphereModel.AtmosphereThickness.ToRenderUnits; float height = localPos.DistanceTo( Point3.Origin ) - planetRadius; float clampedHeight = Utils.Clamp( height, 0, atmosphereRadius ); float normHeight = clampedHeight / atmosphereRadius; float clampedLength = planetRadius + clampedHeight; Vector3 groundVec = localPos.ToVector3( ).MakeLength( clampedLength ); Point3 atmPos = Point3.Origin + groundVec; Vector3 viewDir = UniCamera.Current.Frame.ZAxis; effect.Parameters[ "AtmViewPosLength" ].Set( atmPos.DistanceTo( Point3.Origin ) ); effect.Parameters[ "AtmViewPos" ].Set( atmPos.X, atmPos.Y, atmPos.Z ); effect.Parameters[ "AtmViewDir" ].Set( viewDir.X, viewDir.Y, viewDir.Z ); effect.Parameters[ "AtmViewHeight" ].Set( normHeight ); effect.Parameters[ "AtmInnerRadius" ].Set( planetRadius ); effect.Parameters[ "AtmThickness" ].Set( atmosphereRadius ); effect.Parameters[ "AtmOuterRadius" ].Set( planetRadius + atmosphereRadius ); }
/// <summary> /// Finds the closest planet in the solar system /// </summary> private static IPlanet FindClosestPlanet( IUniCamera camera, ISolarSystem solarSystem, double maxDistance ) { IPlanet closestPlanet = null; double closestDistance = maxDistance; foreach ( IUniObject uniObject in solarSystem.Components ) { IPlanet planet = uniObject as IPlanet; if ( planet != null ) { double distanceToCamera = planet.Transform.Position.DistanceTo( camera.Position ); if ( distanceToCamera < closestDistance ) { closestPlanet = planet; closestDistance = distanceToCamera; } } } return closestPlanet; }
/// <summary> /// Sets up an effect used to render objects as seen through this atmosphere /// </summary> /// <param name="camera">Current camera</param> /// <param name="effect">Effect to set up</param> /// <param name="farObject">Effect is set up for a far away object</param> /// <remarks> /// Will expect certain variables to be available in the effect /// </remarks> public void SetupObjectEffect( IUniCamera camera, IEffect effect, bool farObject ) { SetupAtmosphereEffectParameters( camera, effect, true, farObject ); }
private void SetupRenderUnitAtmosphereEffectParameters( IPlanetAtmosphereScatteringModel model, IUniCamera camera, IEffect effect ) { Point3 localPos = Units.RenderUnits.MakeRelativePoint( Planet.Transform.Position, camera.Position ); float planetRadius = Planet.Model.Radius.ToRenderUnits; float atmosphereRadius = model.Thickness.ToRenderUnits; float height = localPos.DistanceTo( Point3.Origin ) - planetRadius; float normHeight = height > atmosphereRadius ? 1 : ( height / atmosphereRadius ); Vector3 viewDir = camera.Frame.ZAxis; effect.Parameters[ "AtmViewVec" ].Set( localPos.ToVector3( ).MakeNormal( ) ); // effect.Parameters[ "AtmViewPos" ].Set( atmPos ); effect.Parameters[ "AtmViewPos" ].Set( localPos ); effect.Parameters[ "AtmViewDir" ].Set( viewDir ); effect.Parameters[ "AtmViewHeight" ].Set( normHeight ); effect.Parameters[ "AtmInnerRadius" ].Set( planetRadius ); effect.Parameters[ "AtmThickness" ].Set( atmosphereRadius ); effect.Parameters[ "AtmOuterRadius" ].Set( planetRadius + atmosphereRadius ); }
/// <summary> /// Sets up parameters for effects that use atmospheric rendering /// </summary> /// <param name="camera">Current camera</param> /// <param name="effect">Effect to set up</param> /// <param name="objectRendering">True if the effect is being used to render an object in the atmosphere</param> /// <param name="farObject">If true, distances are passed to the effect in astro render units. Otherwise, render units are used.</param> private void SetupAtmosphereEffectParameters( IUniCamera camera, IEffect effect, bool objectRendering, bool farObject ) { IPlanetAtmosphereScatteringModel model = GetModel<IPlanetAtmosphereScatteringModel>( ); if ( model == null ) { return; } if ( farObject ) { SetupAstroRenderUnitAtmosphereEffectParameters( model, camera, effect ); } else { SetupRenderUnitAtmosphereEffectParameters( model, camera, effect ); } // Set up parameters shared between astro and close atmosphere rendering effect.Parameters[ "AtmObjectColourOutput" ].Set( ( int )model.ObjectColourOutput ); effect.Parameters[ "AtmHgCoeff" ].Set( model.PhaseCoefficient ); effect.Parameters[ "AtmPhaseWeight" ].Set( model.PhaseWeight ); effect.Parameters[ "ScatteringTexture" ].Set( model.ScatteringTexture ); effect.Parameters[ "AtmMiePhaseWeight" ].Set( model.MiePhaseWeight ); if ( objectRendering ) { effect.Parameters[ "OpticalDepthTexture" ].Set( model.OpticalDepthTexture ); } }
/// <summary> /// Setup constructor /// </summary> public UniRenderContext( IUniCamera camera, IRenderContext originalContext ) { m_Camera = camera; RenderTime = originalContext.RenderTime; RenderFrameCounter = originalContext.RenderFrameCounter; }
/// <summary> /// Pushes a rendering transform suitable for astronomical distances /// </summary> public static void PushAstroRenderTransform( IUniCamera camera, TransformType transformType, UniTransform transform ) { Graphics.Renderer.PushTransform( transformType ); SetAstroRenderTransform( camera, transformType, transform ); }
/// <summary> /// Sets the rendering transform (<see cref="IRenderer.SetTransform(TransformType,InvariantMatrix44)"/>) /// </summary> public static void SetRenderTransform( IUniCamera camera, TransformType transformType, UniTransform transform ) { float x = ( float )Units.Convert.UniToRender( transform.Position.X - camera.Position.X ); float y = ( float )Units.Convert.UniToRender( transform.Position.Y - camera.Position.Y ); float z = ( float )Units.Convert.UniToRender( transform.Position.Z - camera.Position.Z ); Graphics.Renderer.SetTransform( transformType, new Point3( x, y, z ), transform.XAxis, transform.YAxis, transform.ZAxis ); }