public override void OnSceneManagementGetLightsForCamera( Camera camera, List<RenderingLowLevelMethods.LightItem> outLights ) { Frustum frustum = FrustumUtils.GetFrustumByCamera( camera ); if( EngineDebugSettings.FrustumTest && camera.AllowFrustumTestMode ) { frustum.HalfWidth *= .5f; frustum.HalfHeight *= .5f; } ConvexPolyhedron frustumPolyhedron = GetConvexPolyhedronFromFrustum( ref frustum ); ICollection<RenderLight> lightsToCheck; if( SceneManager.Instance.OverrideVisibleObjects != null ) { lightsToCheck = SceneManager.Instance.OverrideVisibleObjects.Lights; } else { List<RenderLight> list = new List<RenderLight>( 64 ); lightsToCheck = list; bool usePortalSystem = EngineApp.Instance.ApplicationType != EngineApp.ApplicationTypes.ResourceEditor && Map.Instance != null && Map.Instance.Zones.Count != 0 && camera.AllowZonesAndPortalsSceneManagement && EngineDebugSettings.AllowPortalSystem && camera.ProjectionType == ProjectionTypes.Perspective; if( usePortalSystem ) { //use portal system Map.Instance.WalkUsePortalSystem( camera, false, null, null, list ); } else { //use frustum culling //add directional lights foreach( RenderLight light in SceneManager.Instance.RenderLights ) { if( light.Type == RenderLightType.Directional && light.Visible ) list.Add( light ); } uint groupMask = 0; groupMask |= 1 << (int)SceneManager.SceneGraphGroups.Light; int[] sceneGraphIndexes = SceneManager.Instance.SceneGraph.GetObjects( frustum, groupMask ); foreach( int sceneGraphIndex in sceneGraphIndexes ) { SceneManager.SceneGraphObjectData data = SceneManager.Instance.SceneGraphObjects[ sceneGraphIndex ]; //Light RenderLight light = data.Light; if( light != null && light.Visible ) { //clip volumes if( !IsTotalClipVolumesContainsBounds( light.GetWorldBounds() ) ) list.Add( light ); } } } //add objects never culled by the frustum if( SceneManager.Instance.OverrideVisibleObjects == null && Map.Instance != null ) Map.Instance.Walk_AddObjectsWithDisabled_AllowSceneManagementCulling_Property( false, null, null, list ); } foreach( RenderLight light in lightsToCheck ) { if( !light.Visible ) continue; bool allowCastShadows = light.CastShadows; if( light.Type == RenderLightType.Point || light.Type == RenderLightType.Spot ) { if( light.AttenuationFar <= .01f ) continue; Sphere lightSphere = new Sphere( light.Position, light.AttenuationFar ); //fast culling. not cull everything. if( !frustum.IsIntersectsFast( lightSphere ) ) continue; //generate convex polyhedron for light volume //and check intersection with camera frustum. ConvexPolyhedron lightPolyhedron = light.GetInclusiveVolumeForCulling(); //draw light bounds //RendererWorld.Instance.DefaultCamera.DebugGeometry.Color = new ColorValue( 1, 0, 1, .5f ); //RendererWorld.Instance.DefaultCamera.DebugGeometry.AddBounds( light.GetWorldBounds() ); //visualize light volumes //{ // int[] i = new int[ lightPolyhedron.Faces.Length * 3 ]; // for( int n = 0; n < lightPolyhedron.Faces.Length; n++ ) // { // i[ n * 3 + 0 ] = lightPolyhedron.Faces[ n ].Vertex0; // i[ n * 3 + 1 ] = lightPolyhedron.Faces[ n ].Vertex1; // i[ n * 3 + 2 ] = lightPolyhedron.Faces[ n ].Vertex2; // } // RendererWorld.Instance.DefaultCamera.DebugGeometry.Color = new ColorValue( 1, 1, 0, .3f ); // RendererWorld.Instance.DefaultCamera.DebugGeometry.AddVertexIndexBuffer( // lightPolyhedron.Vertices, i, Mat4.Identity, false, true ); //} if( !ConvexPolyhedron.IsIntersects( frustumPolyhedron, lightPolyhedron ) ) continue; //allowCastShadows if( allowCastShadows ) { Sphere frustumShadowSphere = new Sphere( camera.DerivedPosition, SceneManager.Instance.ShadowFarDistance ); if( frustumShadowSphere.IsIntersectsSphere( lightSphere ) ) { if( light.Type == RenderLightType.Spot ) { Cone cone = new Cone( light.Position, light.Direction, light.SpotlightOuterAngle / 2 ); if( !cone.IsIntersectsSphere( frustumShadowSphere ) ) allowCastShadows = false; } } else allowCastShadows = false; } } outLights.Add( new RenderingLowLevelMethods.LightItem( light, allowCastShadows ) ); } }
public override void OnSceneManagementGetLightsForCamera( Camera camera, List<RenderingLowLevelMethods.LightItem> outLights ) { Frustum frustum = FrustumUtils.GetFrustumByCamera( camera ); if( EngineDebugSettings.FrustumTest && camera.AllowFrustumTestMode ) { frustum.HalfWidth *= .5f; frustum.HalfHeight *= .5f; } ConvexPolyhedron frustumPolyhedron = GetConvexPolyhedronFromFrustum( ref frustum ); ICollection<RenderLight> list; if( SceneManager.Instance.OverrideVisibleObjects != null ) list = SceneManager.Instance.OverrideVisibleObjects.Lights; else list = SceneManager.Instance.RenderLights; foreach( RenderLight light in list ) { if( !light.Visible ) continue; bool allowCastShadows = true; if( light.Type == RenderLightType.Point || light.Type == RenderLightType.Spot ) { if( light.AttenuationFar <= .01f ) continue; Sphere lightSphere = new Sphere( light.Position, light.AttenuationFar ); //fast culling. not cull everything. if( !frustum.IsIntersectsFast( lightSphere ) ) continue; //generate convex polyhedron for light volume //and check intersection with camera frustum. ConvexPolyhedron lightPolyhedron = null; if( light.Type == RenderLightType.Point ) lightPolyhedron = MakeConvexPolyhedronForPointLight( light ); else if( light.Type == RenderLightType.Spot ) lightPolyhedron = MakeConvexPolyhedronForSpotLight( light ); if( !ConvexPolyhedron.IsIntersects( frustumPolyhedron, lightPolyhedron ) ) continue; //allowCastShadows if( light.CastShadows ) { Sphere frustumShadowSphere = new Sphere( camera.DerivedPosition, SceneManager.Instance.ShadowFarDistance ); if( frustumShadowSphere.IsIntersectsSphere( lightSphere ) ) { if( light.Type == RenderLightType.Spot ) { Cone cone = new Cone( light.Position, light.Direction, light.SpotlightOuterAngle / 2 ); if( !cone.IsIntersectsSphere( frustumShadowSphere ) ) allowCastShadows = false; } } else allowCastShadows = false; } } outLights.Add( new RenderingLowLevelMethods.LightItem( light, allowCastShadows ) ); } }