Ejemplo n.º 1
0
        //--------------------------------------------------------------
        #region Methods
        //--------------------------------------------------------------

        /// <inheritdoc/>
        public void Reset()
        {
            ReferenceNode      = null;
            _referencePosition = null;

            DirectionalLights.Clear();
            AmbientLights.Clear();
            PointLights.Clear();
            Spotlights.Clear();
            ProjectorLights.Clear();
            ImageBasedLights.Clear();
            OtherLights.Clear();
        }
Ejemplo n.º 2
0
        private void AddNode(LightNode lightNode)
        {
            Debug.Assert(lightNode.ActualIsEnabled, "Scene query contains disabled nodes.");

            // Ignore light if the reference position is not in the clip geometry.
            if (lightNode.Clip != null && _referencePosition.HasValue)
            {
                bool haveContact = HaveContact(lightNode.Clip, _referencePosition.Value);

                if (lightNode.InvertClip == haveContact)
                {
                    return;
                }
            }

            // ----- Sort by estimated light contribution.

            // All lights except IBL will be sorted by contribution.
            // Note: If we have no reference node, it still makes sense to sort the objects
            // by their contribution. We choose to get the light contribution at the position
            // of each light.
            Vector3F position = _referencePosition ?? lightNode.PoseWorld.Position;

            //lightNode.SortTag = lightNode.GetLightContribution(position, 0.7f);

            // Or simpler: Sort light nodes by distance. --> Use for image-based lights.
            // (We use distance², because it is faster.)
            //float distance = (position - lightNode.PoseWorld.Position).LengthSquared;
            //lightNode.SortTag = -distance;   // minus because we use descending sort.

            if (lightNode.Light is AmbientLight)
            {
                AmbientLights.Add(lightNode);
                lightNode.SortTag = lightNode.GetLightContribution(position, 0.7f);
            }
            else if (lightNode.Light is DirectionalLight)
            {
                DirectionalLights.Add(lightNode);
                lightNode.SortTag = lightNode.GetLightContribution(position, 0.7f);
            }
            else if (lightNode.Light is PointLight)
            {
                PointLights.Add(lightNode);
                lightNode.SortTag = lightNode.GetLightContribution(position, 0.7f);
            }
            else if (lightNode.Light is Spotlight)
            {
                Spotlights.Add(lightNode);
                lightNode.SortTag = lightNode.GetLightContribution(position, 0.7f);
            }
            else if (lightNode.Light is ProjectorLight)
            {
                ProjectorLights.Add(lightNode);
                lightNode.SortTag = lightNode.GetLightContribution(position, 0.7f);
            }
            else if (lightNode.Light is ImageBasedLight)
            {
                ImageBasedLights.Add(lightNode);
                float distance = (position - lightNode.PoseWorld.Position).LengthSquared;
                lightNode.SortTag = -distance; // minus because we use descending sort.
            }
            else
            {
                OtherLights.Add(lightNode);
                lightNode.SortTag = lightNode.GetLightContribution(position, 0.7f);
            }
        }
Ejemplo n.º 3
0
        public void Set(SceneNode referenceNode, IList <SceneNode> nodes, RenderContext context)
        {
            Reset();
            ReferenceNode = referenceNode;

            // We use the origin of the reference node as the reference position for determining
            // the light contribution. Alternatively we could use the closest point in/on model AABB,
            // but this requires valid AABBs, is more expensive, etc.
            if (referenceNode != null)
            {
                _referencePosition = referenceNode.PoseWorld.Position;
            }

            int numberOfNodes = nodes.Count;

#if DEBUG
            for (int i = 0; i < numberOfNodes; i++)
            {
                Debug.Assert(nodes[i].ActualIsEnabled, "Scene query contains disabled nodes.");
            }
#endif

            if (context.LodCameraNode == null)
            {
                // ----- No LOD
                for (int i = 0; i < numberOfNodes; i++)
                {
                    var lightNode = nodes[i] as LightNode;
                    if (lightNode != null)
                    {
                        AddNode(lightNode);
                    }
                }
            }
            else
            {
                // ----- LOD
                // Get values for LOD computations.
                var cameraNode = context.LodCameraNode;
                _cameraPosition    = cameraNode.PoseLocal.Position;
                _lodBiasOverYScale = 1 / Math.Abs(cameraNode.Camera.Projection.ToMatrix44F().M11)
                                     * cameraNode.LodBias * context.LodBias;

                // Add nodes and evaluate LOD groups.
                for (int i = 0; i < numberOfNodes; i++)
                {
                    AddNodeWithLod(nodes[i], context);
                }
            }

            // Sort lights.
            if (referenceNode != null)
            {
                AmbientLights.Sort(DescendingLightNodeComparer.Instance);
                DirectionalLights.Sort(DescendingLightNodeComparer.Instance);
                PointLights.Sort(DescendingLightNodeComparer.Instance);
                Spotlights.Sort(DescendingLightNodeComparer.Instance);
                ProjectorLights.Sort(DescendingLightNodeComparer.Instance);
                ImageBasedLights.Sort(DescendingLightNodeComparer.Instance);
                OtherLights.Sort(DescendingLightNodeComparer.Instance);
            }
        }