Ejemplo n.º 1
0
        private static void CalculateMinMaxDistance(ref Plane plane, ref BoundingBoxExt boundingBox, ref float minDistance, ref float maxDistance)
        {
            var nearCorner = boundingBox.Minimum;
            var farCorner  = boundingBox.Maximum;

            if (plane.Normal.X < 0)
            {
                Utilities.Swap(ref nearCorner.X, ref farCorner.X);
            }

            if (plane.Normal.Y < 0)
            {
                Utilities.Swap(ref nearCorner.Y, ref farCorner.Y);
            }

            if (plane.Normal.Z < 0)
            {
                Utilities.Swap(ref nearCorner.Z, ref farCorner.Z);
            }

            float oldDistance;

            // Interlocked exchange if lower
            var distance = CollisionHelper.DistancePlanePoint(ref plane, ref nearCorner);

            while ((oldDistance = minDistance) > distance && Interlocked.CompareExchange(ref minDistance, distance, oldDistance) != oldDistance)
            {
            }

            // Interlocked exchange if greater
            distance = CollisionHelper.DistancePlanePoint(ref plane, ref farCorner);
            while ((oldDistance = maxDistance) < distance && Interlocked.CompareExchange(ref maxDistance, distance, oldDistance) != oldDistance)
            {
            }
        }
Ejemplo n.º 2
0
        private static bool FrustumContainsBox(ref BoundingFrustum frustum, ref BoundingBoxExt boundingBoxExt, bool ignoreDepthPlanes)
        {
            unsafe
            {
                fixed(Plane *planeStart = &frustum.LeftPlane)
                {
                    var plane = planeStart;

                    for (int i = 0; i < 6; ++i)
                    {
                        if (ignoreDepthPlanes && i > 3)
                        {
                            continue;
                        }

                        // Previous code:
                        if (Vector3.Dot(boundingBoxExt.Center, plane->Normal)
                            + boundingBoxExt.Extent.X * Math.Abs(plane->Normal.X)
                            + boundingBoxExt.Extent.Y * Math.Abs(plane->Normal.Y)
                            + boundingBoxExt.Extent.Z * Math.Abs(plane->Normal.Z)
                            <= -plane->D)
                        {
                            return(false);
                        }
                        plane++;
                    }
                }

                return(true);
            }
        }
Ejemplo n.º 3
0
        // TODO: Find a way to replug this

        /// <summary>
        /// Adds a default frustum culling for rendering only meshes that are only inside the frustum/
        /// </summary>
        /// <param name="modelRenderer">The model renderer.</param>
        /// <returns>ModelRenderer.</returns>
        //public static ModelComponentRenderer AddDefaultFrustumCulling(this ModelComponentRenderer modelRenderer)
        //{
        //    modelRenderer.UpdateMeshes = FrustumCulling;
        //    return modelRenderer;
        //}

        private static void FrustumCulling(RenderContext context, FastList <RenderMesh> meshes)
        {
            Matrix viewProjection, mat1, mat2;

            // Compute view * projection
            context.Parameters.Get(TransformationKeys.View, out mat1);
            context.Parameters.Get(TransformationKeys.Projection, out mat2);
            Matrix.Multiply(ref mat1, ref mat2, out viewProjection);

            var frustum = new BoundingFrustum(ref viewProjection);

            for (var i = 0; i < meshes.Count; ++i)
            {
                var renderMesh = meshes[i];

                // Fast AABB transform: http://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/
                // Get world matrix
                renderMesh.Mesh.Parameters.Get(TransformationKeys.World, out mat1);

                // Compute transformed AABB (by world)
                var boundingBoxExt = new BoundingBoxExt(renderMesh.Mesh.BoundingBox);
                boundingBoxExt.Transform(mat1);

                // Perform frustum culling
                if (!frustum.Contains(ref boundingBoxExt))
                {
                    meshes.SwapRemoveAt(i--);
                }
            }
        }
Ejemplo n.º 4
0
        internal void CalculateBoundingBox()
        {
            // update the sprite bounding box
            var halfSpriteSize = Sprite?.Size / 2 ?? Vector2.Zero;

            // Only calculate if we've changed...
            if (lastWorldMatrix != WorldMatrix || lastHalfSpriteSize != halfSpriteSize || lastSpriteType != SpriteType)
            {
                Vector3 halfBoxSize;
                var     boxWorldPosition = WorldMatrix.TranslationVector;

                if (SpriteType == SpriteType.Billboard)
                {
                    // Make a gross estimation here as we don't have access to the camera view matrix
                    // TODO: move this code or grant camera view matrix access to this processor
                    var maxScale = Math.Max(WorldMatrix.Row1.Length(), Math.Max(WorldMatrix.Row2.Length(), WorldMatrix.Row3.Length()));
                    halfBoxSize = maxScale * halfSpriteSize.Length() * Vector3.One;
                }
                else
                {
                    halfBoxSize = new Vector3(
                        Math.Abs(WorldMatrix.M11 * halfSpriteSize.X) + Math.Abs(WorldMatrix.M21 * halfSpriteSize.Y),
                        Math.Abs(WorldMatrix.M12 * halfSpriteSize.X) + Math.Abs(WorldMatrix.M22 * halfSpriteSize.Y),
                        Math.Abs(WorldMatrix.M13 * halfSpriteSize.X) + Math.Abs(WorldMatrix.M23 * halfSpriteSize.Y));
                }

                // Update bounding box
                BoundingBox = new BoundingBoxExt(boxWorldPosition - halfBoxSize, boxWorldPosition + halfBoxSize);

                // Save current state for next check
                lastWorldMatrix    = WorldMatrix;
                lastHalfSpriteSize = halfSpriteSize;
                lastSpriteType     = SpriteType;
            }
        }
        public void Build(RenderDrawContext context)
        {
            if (Mesh == null && TryGetHeightMapImageData(context.CommandList, out var data))
            {
                Data               = new GeometryBuilder(data).BuildTerrainData(Size, MaxHeight, UvScale);
                MeshBoundingBox    = Utils.FromPoints(Data.Vertices);
                MeshBoundingSphere = BoundingSphere.FromBox(MeshBoundingBox);
                BoundingBox        = new BoundingBoxExt(MeshBoundingBox);

                var vertexBuffer        = Buffer.Vertex.New(context.GraphicsDevice, Data.Vertices, GraphicsResourceUsage.Dynamic);
                var indexBuffer         = Buffer.Index.New(context.GraphicsDevice, Data.Indices);
                var vertexBufferBinding = new VertexBufferBinding(vertexBuffer, VertexPositionNormalTexture.Layout, vertexBuffer.ElementCount);
                var indexBufferBinding  = new IndexBufferBinding(indexBuffer, true, indexBuffer.ElementCount);

                MeshDraw = new MeshDraw
                {
                    StartLocation = 0,
                    PrimitiveType = PrimitiveType.TriangleList,
                    VertexBuffers = new[] { vertexBufferBinding },
                    IndexBuffer   = indexBufferBinding,
                    DrawCount     = indexBuffer.ElementCount
                };

                Mesh = new Mesh(MeshDraw, new ParameterCollection());
            }
        }
Ejemplo n.º 6
0
        // TODO: Find a way to replug this

        /// <summary>
        /// Adds a default frustum culling for rendering only meshes that are only inside the frustum/
        /// </summary>
        /// <param name="modelRenderer">The model renderer.</param>
        /// <returns>ModelRenderer.</returns>
        //public static ModelComponentRenderer AddDefaultFrustumCulling(this ModelComponentRenderer modelRenderer)
        //{
        //    modelRenderer.UpdateMeshes = FrustumCulling;
        //    return modelRenderer;
        //}

        private static void FrustumCulling(RenderContext context, FastList<RenderMesh> meshes)
        {
            Matrix viewProjection, mat1, mat2;

            // Compute view * projection
            context.Parameters.Get(TransformationKeys.View, out mat1);
            context.Parameters.Get(TransformationKeys.Projection, out mat2);
            Matrix.Multiply(ref mat1, ref mat2, out viewProjection);

            var frustum = new BoundingFrustum(ref viewProjection);

            for (var i = 0; i < meshes.Count; ++i)
            {
                var renderMesh = meshes[i];

                // Fast AABB transform: http://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/
                // Get world matrix
                renderMesh.Mesh.Parameters.Get(TransformationKeys.World, out mat1);

                // Compute transformed AABB (by world)
                var boundingBoxExt = new BoundingBoxExt(renderMesh.Mesh.BoundingBox);
                boundingBoxExt.Transform(mat1);

                // Perform frustum culling
                if (!frustum.Contains(ref boundingBoxExt))
                {
                    meshes.SwapRemoveAt(i--);
                }
            }
        }
Ejemplo n.º 7
0
        private static void CalculateMinMaxDistance(ref Plane plane, ref BoundingBoxExt boundingBox, ref float minDistance, ref float maxDistance)
        {
            var nearCorner = boundingBox.Minimum;
            var farCorner  = boundingBox.Maximum;

            if (plane.Normal.X < 0)
            {
                Utilities.Swap(ref nearCorner.X, ref farCorner.X);
            }

            if (plane.Normal.Y < 0)
            {
                Utilities.Swap(ref nearCorner.Y, ref farCorner.Y);
            }

            if (plane.Normal.Z < 0)
            {
                Utilities.Swap(ref nearCorner.Z, ref farCorner.Z);
            }

            var distance = CollisionHelper.DistancePlanePoint(ref plane, ref nearCorner);

            if (minDistance > distance)
            {
                minDistance = distance;
            }

            distance = CollisionHelper.DistancePlanePoint(ref plane, ref farCorner);
            if (maxDistance < distance)
            {
                maxDistance = distance;
            }
        }
Ejemplo n.º 8
0
        public static void Update(ModelViewHierarchyUpdater hierarchy, RenderModel renderModel, int slot)
        {
            var boneMatrices = staticBoneMatrices;

            var meshes = renderModel.RenderMeshesList[slot];
            {
                if (meshes == null)
                {
                    return;
                }

                foreach (var renderMesh in meshes)
                {
                    var mesh     = renderMesh.Mesh;
                    var skinning = mesh.Skinning;

                    if (skinning == null)
                    {
                        // For unskinned meshes, use the original bounding box
                        var boundingBoxExt = (BoundingBoxExt)mesh.BoundingBox;
                        boundingBoxExt.Transform(renderMesh.WorldMatrix);
                        renderMesh.BoundingBox = boundingBoxExt;

                        continue;
                    }

                    var bones = skinning.Bones;

                    // Make sure there is enough spaces in boneMatrices
                    if (boneMatrices == null || bones.Length > boneMatrices.Length)
                    {
                        staticBoneMatrices = boneMatrices = new Matrix[bones.Length];
                    }

                    var bindPoseBoundingBox = new BoundingBoxExt(renderMesh.Mesh.BoundingBox);
                    renderMesh.BoundingBox = BoundingBoxExt.Empty;

                    for (int index = 0; index < bones.Length; index++)
                    {
                        var nodeIndex = bones[index].NodeIndex;

                        // Compute bone matrix
                        Matrix.Multiply(ref bones[index].LinkToMeshMatrix, ref hierarchy.NodeTransformations[nodeIndex].WorldMatrix, out boneMatrices[index]);

                        // Calculate and extend bounding box for each bone
                        // TODO: Move runtime bounding box into ModelViewHierarchyUpdater?

                        // Fast AABB transform: http://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/
                        // Compute transformed AABB (by world)
                        var boundingBoxExt = bindPoseBoundingBox;
                        boundingBoxExt.Transform(boneMatrices[index]);
                        BoundingBoxExt.Merge(ref renderMesh.BoundingBox, ref boundingBoxExt, out renderMesh.BoundingBox);
                    }

                    // Upload bones
                    renderMesh.Parameters.Set(TransformationSkinningKeys.BlendMatrixArray, boneMatrices, 0, bones.Length);
                }
            }
        }
Ejemplo n.º 9
0
        internal void Update(TransformComponent transformComponent, ref Matrix worldMatrix)
        {
            if (!Enabled || ModelViewHierarchy == null || model == null)
            {
                return;
            }

            // Check if scaling is negative
            bool isScalingNegative = false;

            {
                Vector3 scale, translation;
                Matrix  rotation;
                if (worldMatrix.Decompose(out scale, out rotation, out translation))
                {
                    isScalingNegative = scale.X * scale.Y * scale.Z < 0.0f;
                }
            }

            // Update model view hierarchy node matrices
            modelViewHierarchy.NodeTransformations[0].LocalMatrix       = worldMatrix;
            modelViewHierarchy.NodeTransformations[0].IsScalingNegative = isScalingNegative;
            modelViewHierarchy.UpdateMatrices();

            // Update the bounding sphere / bounding box in world space
            var    meshes = Model.Meshes;
            var    modelBoundingSphere = BoundingSphere.Empty;
            var    modelBoundingBox    = BoundingBox.Empty;
            bool   hasBoundingBox      = false;
            Matrix world;

            foreach (var mesh in meshes)
            {
                var meshBoundingSphere = mesh.BoundingSphere;

                modelViewHierarchy.GetWorldMatrix(mesh.NodeIndex, out world);
                Vector3.TransformCoordinate(ref meshBoundingSphere.Center, ref world, out meshBoundingSphere.Center);
                BoundingSphere.Merge(ref modelBoundingSphere, ref meshBoundingSphere, out modelBoundingSphere);

                var boxExt = new BoundingBoxExt(mesh.BoundingBox);
                boxExt.Transform(world);
                var meshBox = (BoundingBox)boxExt;

                if (hasBoundingBox)
                {
                    BoundingBox.Merge(ref modelBoundingBox, ref meshBox, out modelBoundingBox);
                }
                else
                {
                    modelBoundingBox = meshBox;
                }

                hasBoundingBox = true;
            }

            // Update the bounds
            BoundingBox    = modelBoundingBox;
            BoundingSphere = modelBoundingSphere;
        }
Ejemplo n.º 10
0
        private static void BoundingBoxIgnoreWorld(InstancingData instancingData, IInstancing instancing, ModelComponent.MeshInfo meshInfo, Mesh mesh)
        {
            // We need to remove the world transformation component
            if (instancingData.ModelComponent.Skeleton != null)
            {
                var ibb = instancing.BoundingBox;
                var mbb = new BoundingBoxExt(meshInfo.BoundingBox);

                Matrix.Invert(ref instancingData.ModelComponent.Skeleton.NodeTransformations[0].LocalMatrix, out var invWorld);
Ejemplo n.º 11
0
        public static void Update(ModelViewHierarchyUpdater hierarchy, RenderModel renderModel, int slot)
        {
            var boneMatrices = staticBoneMatrices;

            var meshes = renderModel.RenderMeshesList[slot];
            {
                if (meshes == null)
                {
                    return;
                }

                foreach (var renderMesh in meshes)
                {
                    var mesh = renderMesh.Mesh;
                    var skinning = mesh.Skinning;

                    if (skinning == null)
                    {
                        // For unskinned meshes, use the original bounding box
                        var boundingBoxExt = (BoundingBoxExt)mesh.BoundingBox;
                        boundingBoxExt.Transform(renderMesh.WorldMatrix);
                        renderMesh.BoundingBox = boundingBoxExt;

                        continue;
                    }

                    var bones = skinning.Bones;

                    // Make sure there is enough spaces in boneMatrices
                    if (boneMatrices == null || bones.Length > boneMatrices.Length)
                        staticBoneMatrices = boneMatrices = new Matrix[bones.Length];

                    var bindPoseBoundingBox = new BoundingBoxExt(renderMesh.Mesh.BoundingBox);
                    renderMesh.BoundingBox = BoundingBoxExt.Empty;

                    for (int index = 0; index < bones.Length; index++)
                    {
                        var nodeIndex = bones[index].NodeIndex;

                        // Compute bone matrix
                        Matrix.Multiply(ref bones[index].LinkToMeshMatrix, ref hierarchy.NodeTransformations[nodeIndex].WorldMatrix, out boneMatrices[index]);

                        // Calculate and extend bounding box for each bone
                        // TODO: Move runtime bounding box into ModelViewHierarchyUpdater?

                        // Fast AABB transform: http://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/
                        // Compute transformed AABB (by world)
                        var boundingBoxExt = bindPoseBoundingBox;
                        boundingBoxExt.Transform(boneMatrices[index]);
                        BoundingBoxExt.Merge(ref renderMesh.BoundingBox, ref boundingBoxExt, out renderMesh.BoundingBox);
                    }

                    // Upload bones
                    renderMesh.Parameters.Set(TransformationSkinningKeys.BlendMatrixArray, boneMatrices, 0, bones.Length);
                }
            }
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Updates this instance( <see cref="Position"/>, <see cref="Direction"/>, <see cref="HasBoundingBox"/>, <see cref="BoundingBox"/>, <see cref="BoundingBoxExt"/>
        /// </summary>
        /// <param name="colorSpace"></param>
        internal void UpdateBoundingBox()
        {
            // Compute bounding boxes
            HasBoundingBox = false;
            BoundingBox    = new BoundingBox();
            BoundingBoxExt = new BoundingBoxExt();

            var directLight = Type as IDirectLight;

            if (directLight != null && directLight.HasBoundingBox)
            {
                // Computes the bounding boxes
                BoundingBox    = directLight.ComputeBounds(Position, Direction);
                BoundingBoxExt = new BoundingBoxExt(BoundingBox);
            }
        }
Ejemplo n.º 13
0
        protected virtual void CalculateBounds(ref ShortPoint location, out BoundingBoxExt bounds, out Vector2 origin)
        {
            var blockSize = BlockSize;
            int left, top, right, bottom;

            GridBlock.CalculateEdges(ref blockSize, ref location, out left, out top, out right, out bottom);

            var     size = CellSize;
            var     topLeft = new Vector3(left * size.X, top * size.Y, 0);
            var     bottomRight = new Vector3(right * size.X, bottom * size.Y, 0);
            Vector3 min, max;

            Vector3.Min(ref topLeft, ref bottomRight, out min);
            Vector3.Max(ref topLeft, ref bottomRight, out max);

            bounds = new BoundingBoxExt(min, max);
            origin = topLeft.XY();
        }
Ejemplo n.º 14
0
        private void SetupLight(RenderDrawContext context, RenderLightShaft lightShaft, LightShadowMapTexture shadowMapTexture, ParameterCollection lightParameterCollection)
        {
            BoundingBoxExt box = new BoundingBoxExt(new Vector3(-float.MaxValue), new Vector3(float.MaxValue)); // TODO

            LightShaftRenderData data;

            if (!renderData.TryGetValue(lightShaft.Light2, out data))
            {
                data = new LightShaftRenderData();
                renderData.Add(lightShaft.Light2, data);
                UpdateRenderData(context, data, lightShaft, shadowMapTexture);
            }

            if (shadowMapTexture != null && data.ShadowMapRenderer != null)
            {
                // Detect changed shadow map renderer or type
                if (data.ShadowMapRenderer != shadowMapTexture.Renderer || data.ShadowType != shadowMapTexture.ShadowType)
                {
                    UpdateRenderData(context, data, lightShaft, shadowMapTexture);
                }
            }
            else if (shadowMapTexture?.Renderer != data.ShadowMapRenderer) // Change from no shadows to shadows
            {
                UpdateRenderData(context, data, lightShaft, shadowMapTexture);
            }

            data.RenderViews[0] = context.RenderContext.RenderView;
            data.ShaderGroup.Reset();
            data.ShaderGroup.SetViews(data.RenderViews);
            data.ShaderGroup.AddView(0, context.RenderContext.RenderView, 1);

            data.ShaderGroup.AddLight(lightShaft.Light, shadowMapTexture);
            data.ShaderGroup.UpdateLayout("lightGroup");

            lightParameterCollection.Set(LightShaftsEffectKeys.LightGroup, data.ShaderGroup.ShaderSource);

            // Update the effect here so the layout is correct
            lightShaftsEffectShader.EffectInstance.UpdateEffect(GraphicsDevice);

            data.ShaderGroup.ApplyViewParameters(context, 0, lightParameterCollection);
            data.ShaderGroup.ApplyDrawParameters(context, 0, lightParameterCollection, ref box);

            data.UsageCounter = usageCounter;
        }
Ejemplo n.º 15
0
        internal void Update(ref Matrix worldMatrix, bool isScalingNegative)
        {
            // Update model view hierarchy node matrices
            modelViewHierarchy.NodeTransformations[0].LocalMatrix       = worldMatrix;
            modelViewHierarchy.NodeTransformations[0].IsScalingNegative = isScalingNegative;
            modelViewHierarchy.UpdateMatrices();

            // Update the bounding sphere / bounding box in world space
            var    meshes = Model.Meshes;
            var    modelBoundingSphere = BoundingSphere.Empty;
            var    modelBoundingBox    = BoundingBox.Empty;
            bool   hasBoundingBox      = false;
            Matrix world;

            foreach (var mesh in meshes)
            {
                var meshBoundingSphere = mesh.BoundingSphere;

                modelViewHierarchy.GetWorldMatrix(mesh.NodeIndex, out world);
                Vector3.TransformCoordinate(ref meshBoundingSphere.Center, ref world, out meshBoundingSphere.Center);
                BoundingSphere.Merge(ref modelBoundingSphere, ref meshBoundingSphere, out modelBoundingSphere);

                var boxExt = new BoundingBoxExt(mesh.BoundingBox);
                boxExt.Transform(world);
                var meshBox = (BoundingBox)boxExt;

                if (hasBoundingBox)
                {
                    BoundingBox.Merge(ref modelBoundingBox, ref meshBox, out modelBoundingBox);
                }
                else
                {
                    modelBoundingBox = meshBox;
                }

                hasBoundingBox = true;
            }

            // Update the bounds
            BoundingBox    = modelBoundingBox;
            BoundingSphere = modelBoundingSphere;
        }
            public override void ApplyDrawParameters(RenderDrawContext context, int viewIndex, ParameterCollection parameters, ref BoundingBoxExt boundingBox)
            {
                // TODO THREADING: Make CurrentLights and lightData (thread-) local
                lock (applyLock)
                {
                    CurrentLights.Clear();
                    var lightRange = LightRanges[viewIndex];
                    for (int i = lightRange.Start; i < lightRange.End; ++i)
                        CurrentLights.Add(Lights[i]);

                    base.ApplyDrawParameters(context, viewIndex, parameters, ref boundingBox);

                    // TODO: Octree structure to select best lights quicker
                    var boundingBox2 = (BoundingBox)boundingBox;
                    for (int i = 0; i < CurrentLights.Count; i++)
                    {
                        var light = CurrentLights[i].Light;

                        if (light.BoundingBox.Intersects(ref boundingBox2))
                        {
                            var spotLight = (LightSpot)light.Type;
                            lightsData.Add(new SpotLightData
                            {
                                PositionWS = light.Position,
                                DirectionWS = light.Direction,
                                AngleOffsetAndInvSquareRadius = new Vector3(spotLight.LightAngleScale, spotLight.LightAngleOffset, spotLight.InvSquareRange),
                                Color = light.Color,
                            });

                            // Did we reach max number of simultaneous lights?
                            // TODO: Still collect everything but sort by importance and remove the rest?
                            if (lightsData.Count >= LightCurrentCount)
                                break;
                        }
                    }

                    parameters.Set(countKey, lightsData.Count);
                    parameters.Set(lightsKey, lightsData.Count, ref lightsData.Items[0]);
                    lightsData.Clear();
                }
            }
Ejemplo n.º 17
0
        /// <summary>
        /// Updates this instance( <see cref="Position"/>, <see cref="Direction"/>, <see cref="HasBoundingBox"/>, <see cref="BoundingBox"/>, <see cref="BoundingBoxExt"/>
        /// </summary>
        public bool Update()
        {
            if (Type == null || !Enabled || !Type.Update(this))
            {
                return(false);
            }

            // Compute light direction and position
            Vector3 lightDirection;
            var     lightDir = DefaultDirection;

            Vector3.TransformNormal(ref lightDir, ref Entity.Transform.WorldMatrix, out lightDirection);
            lightDirection.Normalize();

            Position  = Entity.Transform.WorldMatrix.TranslationVector;
            Direction = lightDirection;

            // Color
            var colorLight = Type as IColorLight;

            Color = (colorLight != null) ? colorLight.ComputeColor(Intensity) : new Color3();

            // Compute bounding boxes
            HasBoundingBox = false;
            BoundingBox    = new BoundingBox();
            BoundingBoxExt = new BoundingBoxExt();

            var directLight = Type as IDirectLight;

            if (directLight != null && directLight.HasBoundingBox)
            {
                // Computes the bounding boxes
                BoundingBox    = directLight.ComputeBounds(Position, Direction);
                BoundingBoxExt = new BoundingBoxExt(BoundingBox);
            }

            return(true);
        }
Ejemplo n.º 18
0
        private void UpdateRenderModel(RenderModel renderModel)
        {
            if (renderModel.ModelComponent.Model == null)
            {
                return;
            }

            var modelComponent      = renderModel.ModelComponent;
            var modelViewHierarchy  = modelComponent.Skeleton;
            var nodeTransformations = modelViewHierarchy.NodeTransformations;

            // TODO GRAPHICS REFACTOR compute bounding box either by Mesh, or switch to future VisibilityObject system to deal with complete models)
            var boundingBox             = new BoundingBoxExt(modelComponent.BoundingBox);
            var modelComponentMaterials = modelComponent.Materials;
            var modelMaterials          = renderModel.ModelComponent.Model.Materials;

            foreach (var renderMesh in renderModel.Meshes)
            {
                var mesh = renderMesh.Mesh;

                renderMesh.Enabled = modelComponent.Enabled;

                if (renderMesh.Enabled)
                {
                    // Update material
                    var materialIndex         = mesh.MaterialIndex;
                    var materialOverride      = modelComponentMaterials.GetItemOrNull(materialIndex);
                    var modelMaterialInstance = modelMaterials.GetItemOrNull(materialIndex);
                    UpdateMaterial(renderMesh, materialOverride, modelMaterialInstance, modelComponent);

                    // Copy world matrix
                    var nodeIndex = mesh.NodeIndex;
                    renderMesh.World       = nodeTransformations[nodeIndex].WorldMatrix;
                    renderMesh.BoundingBox = boundingBox;
                    renderMesh.RenderGroup = modelComponent.Entity.Group;
                }
            }
        }
Ejemplo n.º 19
0
            public override void ApplyDrawParameters(RenderDrawContext context, int viewIndex, ParameterCollection parameters, ref BoundingBoxExt boundingBox)
            {
                CurrentLights.Clear();
                var lightRange = LightRanges[viewIndex];
                for (int i = lightRange.Start; i < lightRange.End; ++i)
                    CurrentLights.Add(Lights[i]);

                base.ApplyDrawParameters(context, viewIndex, parameters, ref boundingBox);

                // TODO: Since we cull per object, we could maintain a higher number of allowed light than the shader support (i.e. 4 lights active per object even though the scene has many more of them)
                // TODO: Octree structure to select best lights quicker
                var boundingBox2 = (BoundingBox)boundingBox;
                foreach (var lightEntry in CurrentLights)
                {
                    var light = lightEntry.Light;

                    if (light.BoundingBox.Intersects(ref boundingBox2))
                    {
                        var pointLight = (LightPoint)light.Type;
                        lightsData.Add(new PointLightData
                        {
                            PositionWS = light.Position,
                            InvSquareRadius = pointLight.InvSquareRadius,
                            Color = light.Color,
                        });

                        // Did we reach max number of simultaneous lights?
                        // TODO: Still collect everything but sort by importance and remove the rest?
                        if (lightsData.Count >= LightCurrentCount)
                            break;
                    }
                }

                parameters.Set(countKey, lightsData.Count);
                parameters.Set(lightsKey, lightsData.Count, ref lightsData.Items[0]);
                lightsData.Clear();
            }
Ejemplo n.º 20
0
 /// <summary>
 /// Applies PerDraw lighting parameters.
 /// </summary>
 /// <param name="context"></param>
 /// <param name="viewIndex"></param>
 /// <param name="parameters"></param>
 /// <param name="boundingBox"></param>
 public virtual void ApplyDrawParameters(FastListStruct <LightDynamicEntry>?lightList, RenderDrawContext context, int viewIndex, ParameterCollection parameters, ref BoundingBoxExt boundingBox)
 {
 }
 /// <inheritdoc/>
 public override void ApplyDrawParameters(RenderDrawContext context, int viewIndex, ParameterCollection parameters, ref BoundingBoxExt boundingBox)
 {
     base.ApplyDrawParameters(context, viewIndex, parameters, ref boundingBox);
     ShadowGroup?.ApplyDrawParameters(context, parameters, CurrentLights, ref boundingBox);
 }
            public override void ApplyDrawParameters(RenderDrawContext context, ParameterCollection parameters, FastListStruct <LightDynamicEntry> currentLights, ref BoundingBoxExt boundingBox)
            {
                var  boundingBox2     = (BoundingBox)boundingBox;
                bool shadowMapCreated = false;
                int  lightIndex       = 0;

                for (int i = 0; i < currentLights.Count; ++i)
                {
                    var lightEntry = currentLights[i];
                    if (lightEntry.Light.BoundingBox.Intersects(ref boundingBox2))
                    {
                        var shaderData = (ShaderData)lightEntry.ShadowMapTexture.ShaderData;

                        // Copy per-face data
                        for (int j = 0; j < 6; j++)
                        {
                            worldToShadow[lightIndex * 6 + j]        = shaderData.WorldToShadow[j];
                            inverseWorldToShadow[lightIndex * 6 + j] = Matrix.Invert(shaderData.WorldToShadow[j]);
                        }

                        depthBiases[lightIndex]     = shaderData.DepthBias;
                        offsetScales[lightIndex]    = shaderData.OffsetScale;
                        depthParameters[lightIndex] = shaderData.DepthParameters;
                        lightIndex++;

                        // TODO: should be setup just once at creation time
                        if (!shadowMapCreated)
                        {
                            shadowMapTexture = shaderData.Texture;
                            if (shadowMapTexture != null)
                            {
                                shadowMapTextureSize      = new Vector2(shadowMapTexture.Width, shadowMapTexture.Height);
                                shadowMapTextureTexelSize = 1.0f / shadowMapTextureSize;
                            }
                            shadowMapCreated = true;
                        }
                    }
                }

                parameters.Set(shadowMapTextureKey, shadowMapTexture);
                parameters.Set(shadowMapTextureSizeKey, shadowMapTextureSize);
                parameters.Set(shadowMapTextureTexelSizeKey, shadowMapTextureTexelSize);

                parameters.Set(worldToShadowKey, worldToShadow);
                parameters.Set(inverseWorldToShadowKey, inverseWorldToShadow);
                parameters.Set(depthParametersKey, depthParameters);
                parameters.Set(depthBiasesKey, depthBiases);
                parameters.Set(offsetScalesKey, offsetScales);
            }
Ejemplo n.º 23
0
        private static bool FrustumContainsBox(ref BoundingFrustum frustum, ref BoundingBoxExt boundingBoxExt, bool ignoreDepthPlanes)
        {
            unsafe
            {
                fixed (Plane* planeStart = &frustum.LeftPlane)
                {
                    var plane = planeStart;
                    for (int i = 0; i < 6; ++i)
                    {
                        if (ignoreDepthPlanes && i > 3)
                            continue;

                        // Previous code:
                        if (Vector3.Dot(boundingBoxExt.Center, plane->Normal)
                            + boundingBoxExt.Extent.X * Math.Abs(plane->Normal.X)
                            + boundingBoxExt.Extent.Y * Math.Abs(plane->Normal.Y)
                            + boundingBoxExt.Extent.Z * Math.Abs(plane->Normal.Z)
                            <= -plane->D)
                            return false;
                        plane++;
                    }
                }

                return true;
            }
        }
Ejemplo n.º 24
0
 /// <inheritdoc/>
 public override void ApplyDrawParameters(RenderDrawContext context, int viewIndex, ParameterCollection parameters, ref BoundingBoxExt boundingBox)
 {
     base.ApplyDrawParameters(context, viewIndex, parameters, ref boundingBox);
     ShadowGroup?.ApplyDrawParameters(context, parameters, CurrentLights, ref boundingBox);
 }
Ejemplo n.º 25
0
        private static void CalculateMinMaxDistance(RenderView view, ref Plane plane, ref BoundingBoxExt boundingBox)
        {
            // TODO GRAPHICS REFACTOR: Optimize per-view: Only two corners need checking, depending on view direction. Also, currently unnecessary for shadow views.
            var minimum = boundingBox.Minimum;
            var maximum = boundingBox.Maximum;

            var point    = minimum;
            var distance = CollisionHelper.DistancePlanePoint(ref plane, ref point);

            MinMax(distance, ref view.MinimumDistance, ref view.MaximumDistance);

            point.X  = maximum.X;
            distance = CollisionHelper.DistancePlanePoint(ref plane, ref point);
            MinMax(distance, ref view.MinimumDistance, ref view.MaximumDistance);

            point.Y  = maximum.Y;
            distance = CollisionHelper.DistancePlanePoint(ref plane, ref point);
            MinMax(distance, ref view.MinimumDistance, ref view.MaximumDistance);

            point.X  = minimum.X;
            distance = CollisionHelper.DistancePlanePoint(ref plane, ref point);
            MinMax(distance, ref view.MinimumDistance, ref view.MaximumDistance);

            point.Z  = maximum.Z;
            distance = CollisionHelper.DistancePlanePoint(ref plane, ref point);
            MinMax(distance, ref view.MinimumDistance, ref view.MaximumDistance);

            point.Y  = minimum.Y;
            distance = CollisionHelper.DistancePlanePoint(ref plane, ref point);
            MinMax(distance, ref view.MinimumDistance, ref view.MaximumDistance);

            point.X  = maximum.X;
            distance = CollisionHelper.DistancePlanePoint(ref plane, ref point);
            MinMax(distance, ref view.MinimumDistance, ref view.MaximumDistance);

            point.Y  = maximum.Y;
            distance = CollisionHelper.DistancePlanePoint(ref plane, ref point);
            MinMax(distance, ref view.MinimumDistance, ref view.MaximumDistance);
        }
Ejemplo n.º 26
0
            public override void ApplyDrawParameters(RenderDrawContext context, ParameterCollection parameters, FastListStruct <LightDynamicEntry> currentLights, ref BoundingBoxExt boundingBox)
            {
                var  boundingBox2     = (BoundingBox)boundingBox;
                bool shadowMapCreated = false;
                int  lightIndex       = 0;

                for (int i = 0; i < currentLights.Count; ++i)
                {
                    var lightEntry = currentLights[i];

                    var light = lightEntry.Light;

                    if (light.BoundingBox.Intersects(ref boundingBox2))
                    {
                        var singleLightData = (LightSpotShadowMapShaderData)lightEntry.ShadowMapTexture.ShaderData;
                        worldToShadowCascadeUV[lightIndex] = singleLightData.WorldToShadowCascadeUV;

                        depthBiases[lightIndex]  = singleLightData.DepthBias;
                        offsetScales[lightIndex] = singleLightData.OffsetScale;
                        lightIndex++;

                        if (!shadowMapCreated)
                        {
                            shadowMapTexture = singleLightData.Texture;
                            if (shadowMapTexture != null)
                            {
                                shadowMapTextureSize      = new Vector2(shadowMapTexture.Width, shadowMapTexture.Height);
                                shadowMapTextureTexelSize = 1.0f / shadowMapTextureSize;
                            }
                            shadowMapCreated = true;
                        }
                    }
                }

                parameters.Set(shadowMapTextureKey, shadowMapTexture);
                parameters.Set(shadowMapTextureSizeKey, shadowMapTextureSize);
                parameters.Set(shadowMapTextureTexelSizeKey, shadowMapTextureTexelSize);
                parameters.Set(worldToShadowCascadeUVsKey, worldToShadowCascadeUV);
                parameters.Set(depthBiasesKey, depthBiases);
                parameters.Set(offsetScalesKey, offsetScales);
            }
Ejemplo n.º 27
0
        internal void Update(ref Matrix worldMatrix)
        {
            // Update model view hierarchy node matrices
            modelViewHierarchy.NodeTransformations[0].LocalMatrix = worldMatrix;
            modelViewHierarchy.UpdateMatrices();

            // Update the bounding sphere / bounding box in world space
            var meshes = Model.Meshes;
            var modelBoundingSphere = BoundingSphere.Empty;
            var modelBoundingBox = BoundingBox.Empty;
            bool hasBoundingBox = false;
            Matrix world;
            foreach (var mesh in meshes)
            {
                var meshBoundingSphere = mesh.BoundingSphere;

                modelViewHierarchy.GetWorldMatrix(mesh.NodeIndex, out world);
                Vector3.TransformCoordinate(ref meshBoundingSphere.Center, ref world, out meshBoundingSphere.Center);
                BoundingSphere.Merge(ref modelBoundingSphere, ref meshBoundingSphere, out modelBoundingSphere);

                var boxExt = new BoundingBoxExt(mesh.BoundingBox);
                boxExt.Transform(world);
                var meshBox = (BoundingBox)boxExt;

                if (hasBoundingBox)
                {
                    BoundingBox.Merge(ref modelBoundingBox, ref meshBox, out modelBoundingBox);
                }
                else
                {
                    modelBoundingBox = meshBox;
                }

                hasBoundingBox = true;
            }

            // Update the bounds
            BoundingBox = modelBoundingBox;
            BoundingSphere = modelBoundingSphere;
        }
Ejemplo n.º 28
0
        /// <summary>
        /// Determines whether a <see cref="BoundingFrustum" /> intersects or contains an AABB determined by its center and extent.
        /// Faster variant specific for frustum culling.
        /// </summary>
        /// <param name="frustum">The frustum.</param>
        /// <param name="boundingBoxExt">The bounding box ext.</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        public static bool FrustumContainsBox(ref BoundingFrustum frustum, ref BoundingBoxExt boundingBoxExt)
        {
            unsafe
            {
                fixed (Plane* planeStart = &frustum.LeftPlane)
                {
                    var plane = planeStart;
                    for (int i = 0; i < 6; ++i)
                    {
                        // Previous code:
                        if (Vector3.Dot(boundingBoxExt.Center, plane->Normal)
                            + boundingBoxExt.Extent.X * Math.Abs(plane->Normal.X)
                            + boundingBoxExt.Extent.Y * Math.Abs(plane->Normal.Y)
                            + boundingBoxExt.Extent.Z * Math.Abs(plane->Normal.Z)
                            <= -plane->D)
                            return false;
                        plane++;
                    }
                }

                return true;
            }
/*
            unsafe
            {
                fixed (Plane* planeStart = &frustum.LeftPlane)
                fixed (Vector3* pExtent = &boundingBoxExt.Extent)
                {
                    var plane = planeStart;
                    for (int i = 0; i < 6; ++i)
                    {
                        // Previous code:
                        //if (Vector3.Dot(boundingBoxExt.Center, plane->Normal)
                        //    + boundingBoxExt.Extent.X * Math.Abs(plane->Normal.X)
                        //    + boundingBoxExt.Extent.Y * Math.Abs(plane->Normal.Y)
                        //    + boundingBoxExt.Extent.Z * Math.Abs(plane->Normal.Z)
                        //    <= -plane->D)

                        // Optimized version (only 1 dot and cheaper Math.Abs)
                        // https://fgiesen.wordpress.com/2010/10/17/view-frustum-culling/
                        // return dot3(center, plane) + dot3(extent, absPlane) <= -plane.w;
                        // or
                        // vector4 signFlip = componentwise_and(plane, 0x80000000);
                        // vector3 centerOffset = xor(extent, signFlip)
                        // dot3(center + centerOffset, plane) <= -plane.w;

                        uint val = (((uint*)&plane->Normal)[0] & 0x80000000) ^ ((uint*)pExtent)[0];
                        var dist = plane->Normal.X * ((*(float*)(&val)) + boundingBoxExt.Center.X);

                        val = (((uint*)&plane->Normal)[1] & 0x80000000) ^ ((uint*)pExtent)[1];
                        dist += plane->Normal.Y * ((*(float*)(&val)) + boundingBoxExt.Center.Y);

                        val = (((uint*)&plane->Normal)[2] & 0x80000000) ^ ((uint*)pExtent)[2];
                        dist += plane->Normal.Z * ((*(float*)(&val)) + boundingBoxExt.Center.Z);

                        if (dist <= -plane->D)
                            return false;

                        plane++;
                    }
                }

                return true;
            }
 */
        }
Ejemplo n.º 29
0
        /// <summary>
        /// Calculate the bounding sphere of the entity's models.
        /// </summary>
        /// <param name="entity">The entity to measure</param>
        /// <param name="isRecursive">Indicate the child entities bounding spheres should be merged</param>
        /// <param name="meshSelector">Selects which meshes are considered for bounding box calculation.</param>
        /// <returns>The bounding sphere (world matrix included)</returns>
        public static BoundingSphere CalculateBoundSphere(this Entity entity, bool isRecursive = true, Func <Model, IEnumerable <Mesh> > meshSelector = null)
        {
            entity.Transform.UpdateWorldMatrix();
            var worldMatrix = entity.Transform.WorldMatrix;

            var boundingSphere = BoundingSphere.Empty;

            // calculate the bounding sphere of the model if any
            var modelComponent = entity.Get <ModelComponent>();
            var hasModel       = modelComponent?.Model != null;

            if (hasModel)
            {
                var hierarchy      = modelComponent.Skeleton;
                var nodeTransforms = new Matrix[hierarchy.Nodes.Length];

                // Calculate node transforms here, since there might not be a ModelProcessor running
                for (int i = 0; i < nodeTransforms.Length; i++)
                {
                    if (hierarchy.Nodes[i].ParentIndex == -1)
                    {
                        nodeTransforms[i] = worldMatrix;
                    }
                    else
                    {
                        Matrix localMatrix;

                        Matrix.Transformation(
                            ref hierarchy.Nodes[i].Transform.Scale,
                            ref hierarchy.Nodes[i].Transform.Rotation,
                            ref hierarchy.Nodes[i].Transform.Position, out localMatrix);

                        Matrix.Multiply(ref localMatrix, ref nodeTransforms[hierarchy.Nodes[i].ParentIndex], out nodeTransforms[i]);
                    }
                }

                // calculate the bounding sphere
                var boundingBox = BoundingBoxExt.Empty;

                var meshes         = modelComponent.Model.Meshes;
                var filteredMeshes = meshSelector == null ? meshes : meshSelector(modelComponent.Model);

                // Calculate skinned bounding boxes.
                // TODO: Cloned from ModelSkinningUpdater. Consolidate.
                foreach (var mesh in filteredMeshes)
                {
                    var skinning = mesh.Skinning;

                    if (skinning == null)
                    {
                        // For unskinned meshes, use the original bounding box
                        var boundingBoxExt = (BoundingBoxExt)mesh.BoundingBox;
                        boundingBoxExt.Transform(nodeTransforms[mesh.NodeIndex]);
                        BoundingBoxExt.Merge(ref boundingBox, ref boundingBoxExt, out boundingBox);
                    }
                    else
                    {
                        var bones = skinning.Bones;
                        var bindPoseBoundingBox = new BoundingBoxExt(mesh.BoundingBox);

                        for (var index = 0; index < bones.Length; index++)
                        {
                            var    nodeIndex = bones[index].NodeIndex;
                            Matrix boneMatrix;

                            // Compute bone matrix
                            Matrix.Multiply(ref bones[index].LinkToMeshMatrix, ref nodeTransforms[nodeIndex], out boneMatrix);

                            // Fast AABB transform: http://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/
                            // Compute transformed AABB (by world)
                            var boundingBoxExt = bindPoseBoundingBox;
                            boundingBoxExt.Transform(boneMatrix);
                            BoundingBoxExt.Merge(ref boundingBox, ref boundingBoxExt, out boundingBox);
                        }
                    }
                }
                var halfSize    = boundingBox.Extent;
                var maxHalfSize = Math.Max(halfSize.X, Math.Max(halfSize.Y, halfSize.Z));
                boundingSphere = BoundingSphere.Merge(boundingSphere, new BoundingSphere(boundingBox.Center, maxHalfSize));
            }

            // Calculate the bounding sphere for the sprite component if any and merge the result
            var spriteComponent = entity.Get <SpriteComponent>();
            var hasSprite       = spriteComponent?.CurrentSprite != null;

            if (hasSprite && !(hasModel && meshSelector != null))
            {
                var spriteSize         = spriteComponent.CurrentSprite.Size;
                var spriteDiagonalSize = (float)Math.Sqrt(spriteSize.X * spriteSize.X + spriteSize.Y * spriteSize.Y);

                // Note: this is probably wrong, need to unify with SpriteComponentRenderer
                var center   = worldMatrix.TranslationVector;
                var scales   = new Vector3(worldMatrix.Row1.Length(), worldMatrix.Row2.Length(), worldMatrix.Row3.Length());
                var maxScale = Math.Max(scales.X, Math.Max(scales.Y, scales.Z));

                boundingSphere = BoundingSphere.Merge(boundingSphere, new BoundingSphere(center, maxScale * spriteDiagonalSize / 2f));
            }

            var spriteStudioComponent = entity.Get <SpriteStudioComponent>();

            if (spriteStudioComponent != null)
            {
                // Make sure nodes are prepared
                if (!SpriteStudioProcessor.PrepareNodes(spriteStudioComponent))
                {
                    return(new BoundingSphere());
                }

                // Update root nodes
                foreach (var node in spriteStudioComponent.Nodes)
                {
                    node.UpdateTransformation();
                }

                // Compute bounding sphere for each node
                foreach (var node in spriteStudioComponent.Nodes.SelectDeep(x => x.ChildrenNodes))
                {
                    if (node.Sprite == null || node.Hide != 0)
                    {
                        continue;
                    }

                    var nodeMatrix = node.ModelTransform * worldMatrix;

                    var spriteSize         = node.Sprite.Size;
                    var spriteDiagonalSize = (float)Math.Sqrt(spriteSize.X * spriteSize.X + spriteSize.Y * spriteSize.Y);

                    Vector3 pos, scale;
                    nodeMatrix.Decompose(out scale, out pos);

                    var center   = pos;
                    var maxScale = Math.Max(scale.X, scale.Y); //2d ignore Z

                    boundingSphere = BoundingSphere.Merge(boundingSphere, new BoundingSphere(center, maxScale * (spriteDiagonalSize / 2f)));
                }
            }

            var particleComponent = entity.Get <ParticleSystemComponent>();

            if (particleComponent != null)
            {
                var center = worldMatrix.TranslationVector;
                var sphere = particleComponent.ParticleSystem?.BoundingShape != null?BoundingSphere.FromBox(particleComponent.ParticleSystem.BoundingShape.GetAABB(center, Quaternion.Identity, 1.0f)) : new BoundingSphere(center, 2.0f);

                boundingSphere = BoundingSphere.Merge(boundingSphere, sphere);
            }

            var boundingBoxComponent = entity.Get <NavigationBoundingBoxComponent>();

            if (boundingBoxComponent != null)
            {
                var center = worldMatrix.TranslationVector;
                var scales = new Vector3(worldMatrix.Row1.Length(), worldMatrix.Row2.Length(), worldMatrix.Row3.Length()) * boundingBoxComponent.Size;
                boundingSphere = BoundingSphere.FromBox(new BoundingBox(-scales + center, scales + center));
            }

            // Extend the bounding sphere to include the children
            if (isRecursive)
            {
                foreach (var child in entity.GetChildren())
                {
                    boundingSphere = BoundingSphere.Merge(boundingSphere, child.CalculateBoundSphere(true, meshSelector));
                }
            }

            // If the entity does not contain any components having an impact on the bounding sphere, create an empty bounding sphere centered on the entity position.
            if (boundingSphere == BoundingSphere.Empty)
            {
                boundingSphere = new BoundingSphere(worldMatrix.TranslationVector, 0);
            }

            return(boundingSphere);
        }
Ejemplo n.º 30
0
            public void ApplyDrawParameters(RenderDrawContext context, ParameterCollection parameters, FastListStruct <LightDynamicEntry> currentLights, ref BoundingBoxExt boundingBox)
            {
                var boundingBoxCasted = (BoundingBox)boundingBox;
                int lightIndex        = 0;

                for (int i = 0; i < currentLights.Count; ++i)
                {
                    var lightEntry = currentLights[i];
                    var light      = lightEntry.Light;

                    if (light.BoundingBox.Intersects(ref boundingBoxCasted))
                    {
                        var spotLight = (LightSpot)light.Type;

                        /*
                         * // TODO: Just save the shaderdata struct directly within "LightDynamicEntry"?
                         * var singleLightData = (LightSpotTextureProjectionShaderData)lightEntry.ShadowMapTexture.ShaderData;   // TODO: This must not depend on the shadow map texture!
                         *
                         * worldToTextureUV[lightIndex] = singleLightData.WorldToTextureUV;
                         * projectionTextureMipMapLevels[lightIndex] = singleLightData.ProjectiveTextureMipMapLevel;
                         * projectiveTexture = singleLightData.ProjectiveTexture;
                         */

                        // TODO: Move this to "Collect()" and use "LightSpotTextureProjectionShaderData", but IDK how!
                        worldToTextureUV[lightIndex]       = ComputeWorldToTextureUVMatrix(light);
                        projectorPlaneMatrices[lightIndex] = ComputeProjectorPlaneMatrix(light);

                        // We use the maximum number of mips instead of the actual number,
                        // so things like video textures behave more consistently when changing the number of mip maps to generate.
                        int   maxMipMapCount = Texture.CountMips(lightParameters.ProjectionTexture.Width, lightParameters.ProjectionTexture.Height);
                        float projectiveTextureMipMapLevel = (float)(maxMipMapCount - 1) * spotLight.MipMapScale; // "- 1" because the lowest mip level is 0, not 1.
                        projectionTextureMipMapLevels[lightIndex] = projectiveTextureMipMapLevel;
                        transitionAreas[lightIndex] = Math.Max(spotLight.TransitionArea, 0.001f);                 // Keep the value just above zero. This is to prevent some issues with the "smoothstep()" function on OpenGL and OpenGL ES.

                        ++lightIndex;
                    }
                }

                // TODO: Why is this set if it's already in the collection?
                // TODO: Does this get set once per group or something?
                parameters.Set(projectiveTextureKey, lightParameters.ProjectionTexture);
                parameters.Set(uvScale, lightParameters.UVScale);
                parameters.Set(uvOffset, lightParameters.UVOffset);
                parameters.Set(worldToProjectiveTextureUVsKey, worldToTextureUV);
                parameters.Set(projectorPlaneMatricesKey, projectorPlaneMatrices);
                parameters.Set(projectionTextureMipMapLevelsKey, projectionTextureMipMapLevels);
                parameters.Set(transitionAreasKey, transitionAreas);
            }
Ejemplo n.º 31
0
            public override void ApplyDrawParameters(FastListStruct <LightDynamicEntry>?lightList, RenderDrawContext context, int viewIndex, ParameterCollection parameters, ref BoundingBoxExt boundingBox)
            {
                FastListStruct <SpotLightData> lightsData = new FastListStruct <SpotLightData>(8);

                if (lightList == null)
                {
                    lightList = new FastListStruct <LightDynamicEntry>(8);
                }
                FastListStruct <LightDynamicEntry> currentLights = lightList.Value;
                var lightRange = lightRanges[viewIndex];

                for (int i = lightRange.Start; i < lightRange.End; ++i)
                {
                    currentLights.Add(lights[i]);
                }

                base.ApplyDrawParameters(currentLights, context, viewIndex, parameters, ref boundingBox);

                // TODO: Octree structure to select best lights quicker
                var boundingBox2 = (BoundingBox)boundingBox;

                for (int i = 0; i < currentLights.Count; i++)
                {
                    var light = currentLights[i].Light;

                    if (light.BoundingBox.Intersects(ref boundingBox2))
                    {
                        var spotLight = (LightSpot)light.Type;
                        lightsData.Add(new SpotLightData
                        {
                            PositionWS  = light.Position,
                            DirectionWS = light.Direction,
                            AngleOffsetAndInvSquareRadius = new Vector3(spotLight.LightAngleScale, spotLight.LightAngleOffset, spotLight.InvSquareRange),
                            Color = light.Color,
                        });

                        // Did we reach max number of simultaneous lights?
                        // TODO: Still collect everything but sort by importance and remove the rest?
                        if (lightsData.Count >= LightCurrentCount)
                        {
                            break;
                        }
                    }
                }

                parameters.Set(countKey, lightsData.Count);
                parameters.Set(lightsKey, lightsData.Count, ref lightsData.Items[0]);

                TextureProjectionShaderGroupData?.ApplyDrawParameters(context, parameters, currentLights, ref boundingBox);
            }
Ejemplo n.º 32
0
        private bool DrawBoundingVolumes(RenderDrawContext context, IReadOnlyList <RenderLightShaftBoundingVolume> boundingVolumes, Matrix viewProjection)
        {
            var commandList = context.CommandList;

            bool effectUpdated = minmaxVolumeEffectShader.UpdateEffect(GraphicsDevice);

            if (minmaxVolumeEffectShader.Effect == null)
            {
                return(false);
            }

            var  needEffectUpdate = effectUpdated || previousMinmaxEffectBytecode != minmaxVolumeEffectShader.Effect.Bytecode;
            bool visibleMeshes    = false;

            for (int pass = 0; pass < 2; ++pass)
            {
                var minmaxPipelineState = minmaxPipelineStates[pass];

                bool pipelineDirty = false;
                if (needEffectUpdate)
                {
                    // The EffectInstance might have been updated from outside
                    previousMinmaxEffectBytecode = minmaxVolumeEffectShader.Effect.Bytecode;

                    minmaxPipelineState.State.RootSignature  = minmaxVolumeEffectShader.RootSignature;
                    minmaxPipelineState.State.EffectBytecode = minmaxVolumeEffectShader.Effect.Bytecode;

                    minmaxPipelineState.State.Output.RenderTargetCount   = 1;
                    minmaxPipelineState.State.Output.RenderTargetFormat0 = commandList.RenderTarget.Format;
                    pipelineDirty = true;
                }

                MeshDraw currentDraw = null;
                var      frustum     = new BoundingFrustum(ref viewProjection);
                foreach (var volume in boundingVolumes)
                {
                    if (volume.Model == null)
                    {
                        continue;
                    }

                    // Update parameters for the minmax shader
                    Matrix worldViewProjection = Matrix.Multiply(volume.World, viewProjection);
                    minmaxVolumeEffectShader.Parameters.Set(VolumeMinMaxShaderKeys.WorldViewProjection, worldViewProjection);

                    foreach (var mesh in volume.Model.Meshes)
                    {
                        // Frustum culling
                        BoundingBox meshBoundingBox;
                        Matrix      world = volume.World;
                        BoundingBox.Transform(ref mesh.BoundingBox, ref world, out meshBoundingBox);
                        var boundingBoxExt = new BoundingBoxExt(meshBoundingBox);
                        if (boundingBoxExt.Extent != Vector3.Zero &&
                            !VisibilityGroup.FrustumContainsBox(ref frustum, ref boundingBoxExt, true))
                        {
                            continue;
                        }

                        visibleMeshes = true;

                        var draw = mesh.Draw;

                        if (currentDraw != draw)
                        {
                            if (minmaxPipelineState.State.PrimitiveType != draw.PrimitiveType)
                            {
                                minmaxPipelineState.State.PrimitiveType = draw.PrimitiveType;
                                pipelineDirty = true;
                            }

                            var inputElements = draw.VertexBuffers.CreateInputElements();
                            if (inputElements.ComputeHash() != minmaxPipelineState.State.InputElements.ComputeHash())
                            {
                                minmaxPipelineState.State.InputElements = inputElements;
                                pipelineDirty = true;
                            }

                            // Update mesh
                            for (int i = 0; i < draw.VertexBuffers.Length; i++)
                            {
                                var vertexBuffer = draw.VertexBuffers[i];
                                commandList.SetVertexBuffer(i, vertexBuffer.Buffer, vertexBuffer.Offset, vertexBuffer.Stride);
                            }
                            if (draw.IndexBuffer != null)
                            {
                                commandList.SetIndexBuffer(draw.IndexBuffer.Buffer, draw.IndexBuffer.Offset, draw.IndexBuffer.Is32Bit);
                            }
                            currentDraw = draw;
                        }

                        if (pipelineDirty)
                        {
                            minmaxPipelineState.Update();
                            pipelineDirty = false;
                        }

                        context.CommandList.SetPipelineState(minmaxPipelineState.CurrentState);

                        minmaxVolumeEffectShader.Apply(context.GraphicsContext);

                        // Draw
                        if (currentDraw.IndexBuffer == null)
                        {
                            commandList.Draw(currentDraw.DrawCount, currentDraw.StartLocation);
                        }
                        else
                        {
                            commandList.DrawIndexed(currentDraw.DrawCount, currentDraw.StartLocation);
                        }
                    }
                }
            }

            return(visibleMeshes);
        }
Ejemplo n.º 33
0
        internal void Update(TransformComponent transformComponent, ref Matrix worldMatrix)
        {
            if (!Enabled || model == null)
                return;

            // Check if scaling is negative
            bool isScalingNegative = false;
            {
                Vector3 scale, translation;
                Matrix rotation;
                if (worldMatrix.Decompose(out scale, out rotation, out translation))
                    isScalingNegative = scale.X*scale.Y*scale.Z < 0.0f;
            }

            // Make sure skeleton is up to date
            CheckSkeleton();

            if (skeleton != null)
            {
                // Update model view hierarchy node matrices
                skeleton.NodeTransformations[0].LocalMatrix = worldMatrix;
                skeleton.NodeTransformations[0].IsScalingNegative = isScalingNegative;
                skeleton.UpdateMatrices();
            }

            // Update the bounding sphere / bounding box in world space
            var meshes = Model.Meshes;
            var modelBoundingSphere = BoundingSphere.Empty;
            var modelBoundingBox = BoundingBox.Empty;
            bool hasBoundingBox = false;
            Matrix world;
            foreach (var mesh in meshes)
            {
                var meshBoundingSphere = mesh.BoundingSphere;

                if (skeleton != null)
                    skeleton.GetWorldMatrix(mesh.NodeIndex, out world);
                else
                    world = worldMatrix;
                Vector3.TransformCoordinate(ref meshBoundingSphere.Center, ref world, out meshBoundingSphere.Center);
                BoundingSphere.Merge(ref modelBoundingSphere, ref meshBoundingSphere, out modelBoundingSphere);

                var boxExt = new BoundingBoxExt(mesh.BoundingBox);
                boxExt.Transform(world);
                var meshBox = (BoundingBox)boxExt;

                if (hasBoundingBox)
                {
                    BoundingBox.Merge(ref modelBoundingBox, ref meshBox, out modelBoundingBox);
                }
                else
                {
                    modelBoundingBox = meshBox;
                }

                hasBoundingBox = true;
            }

            // Update the bounds
            BoundingBox = modelBoundingBox;
            BoundingSphere = modelBoundingSphere;
        }
Ejemplo n.º 34
0
        /// <summary>
        /// Updates this instance( <see cref="Position"/>, <see cref="Direction"/>, <see cref="HasBoundingBox"/>, <see cref="BoundingBox"/>, <see cref="BoundingBoxExt"/>
        /// </summary>
        public bool Update()
        {
            if (Type == null || !Enabled || !Type.Update(this))
            {
                return false;
            }

            // Compute light direction and position
            Vector3 lightDirection;
            var lightDir = DefaultDirection;
            Vector3.TransformNormal(ref lightDir, ref Entity.Transform.WorldMatrix, out lightDirection);
            lightDirection.Normalize();

            Position = Entity.Transform.Position;
            Direction = lightDirection;

            // Color
            var colorLight = Type as IColorLight;
            Color = (colorLight != null) ? colorLight.ComputeColor(Intensity) : new Color3();

            // Compute bounding boxes
            HasBoundingBox = false;
            BoundingBox = new BoundingBox();
            BoundingBoxExt = new BoundingBoxExt();

            var directLight = Type as IDirectLight;
            if (directLight != null && directLight.HasBoundingBox)
            {
                // Computes the bounding boxes
                BoundingBox = directLight.ComputeBounds(Position, Direction);
                BoundingBoxExt = new BoundingBoxExt(BoundingBox);
            }

            return true;
        }
 public void ApplyDrawParameters(RenderDrawContext context, ParameterCollection parameters, FastListStruct<LightDynamicEntry> currentLights, ref BoundingBoxExt boundingBox)
 {
 }
Ejemplo n.º 36
0
 /// <summary>
 /// Applies PerDraw lighting parameters.
 /// </summary>
 /// <param name="context"></param>
 /// <param name="viewIndex"></param>
 /// <param name="parameters"></param>
 /// <param name="boundingBox"></param>
 public virtual void ApplyDrawParameters(RenderDrawContext context, int viewIndex, ParameterCollection parameters, ref BoundingBoxExt boundingBox)
 {
 }
            public void ApplyDrawParameters(RenderDrawContext context, ParameterCollection parameters, FastListStruct<LightDynamicEntry> currentLights, ref BoundingBoxExt boundingBox)
            {
                var boundingBox2 = (BoundingBox)boundingBox;
                bool shadowMapCreated = false;
                int lightIndex = 0;

                for (int i = 0; i < currentLights.Count; ++i)
                {
                    var lightEntry = currentLights[i];

                    var light = lightEntry.Light;

                    if (light.BoundingBox.Intersects(ref boundingBox2))
                    {
                        var singleLightData = (LightSpotShadowMapShaderData)lightEntry.ShadowMapTexture.ShaderData;
                        worldToShadowCascadeUV[lightIndex] = singleLightData.WorldToShadowCascadeUV;

                        depthBiases[lightIndex] = singleLightData.DepthBias;
                        offsetScales[lightIndex] = singleLightData.OffsetScale;
                        lightIndex++;

                        if (!shadowMapCreated)
                        {
                            shadowMapTexture = singleLightData.Texture;
                            if (shadowMapTexture != null)
                            {
                                shadowMapTextureSize = new Vector2(shadowMapTexture.Width, shadowMapTexture.Height);
                                shadowMapTextureTexelSize = 1.0f / shadowMapTextureSize;
                            }
                            shadowMapCreated = true;
                        }
                    }
                }

                parameters.Set(shadowMapTextureKey, shadowMapTexture);
                parameters.Set(shadowMapTextureSizeKey, shadowMapTextureSize);
                parameters.Set(shadowMapTextureTexelSizeKey, shadowMapTextureTexelSize);
                parameters.Set(worldToShadowCascadeUVsKey, worldToShadowCascadeUV);
                parameters.Set(depthBiasesKey, depthBiases);
                parameters.Set(offsetScalesKey, offsetScales);
            }
Ejemplo n.º 38
0
        private static void CalculateMinMaxDistance(RenderView view, ref Plane plane, ref BoundingBoxExt boundingBox)
        {
            // TODO GRAPHICS REFACTOR: Optimize per-view: Only two corners need checking, depending on view direction. Also, currently unnecessary for shadow views.
            var minimum = boundingBox.Minimum;
            var maximum = boundingBox.Maximum;

            var point = minimum;
            var distance = CollisionHelper.DistancePlanePoint(ref plane, ref point);
            MinMax(distance, ref view.MinimumDistance, ref view.MaximumDistance);

            point.X = maximum.X;
            distance = CollisionHelper.DistancePlanePoint(ref plane, ref point);
            MinMax(distance, ref view.MinimumDistance, ref view.MaximumDistance);

            point.Y = maximum.Y;
            distance = CollisionHelper.DistancePlanePoint(ref plane, ref point);
            MinMax(distance, ref view.MinimumDistance, ref view.MaximumDistance);

            point.X = minimum.X;
            distance = CollisionHelper.DistancePlanePoint(ref plane, ref point);
            MinMax(distance, ref view.MinimumDistance, ref view.MaximumDistance);

            point.Z = maximum.Z;
            distance = CollisionHelper.DistancePlanePoint(ref plane, ref point);
            MinMax(distance, ref view.MinimumDistance, ref view.MaximumDistance);

            point.Y = minimum.Y;
            distance = CollisionHelper.DistancePlanePoint(ref plane, ref point);
            MinMax(distance, ref view.MinimumDistance, ref view.MaximumDistance);

            point.X = maximum.X;
            distance = CollisionHelper.DistancePlanePoint(ref plane, ref point);
            MinMax(distance, ref view.MinimumDistance, ref view.MaximumDistance);

            point.Y = maximum.Y;
            distance = CollisionHelper.DistancePlanePoint(ref plane, ref point);
            MinMax(distance, ref view.MinimumDistance, ref view.MaximumDistance);
        }
Ejemplo n.º 39
0
 public bool Contains(ref BoundingBoxExt boundingBoxExt)
 {
     return Collision.FrustumContainsBox(ref this, ref boundingBoxExt);
 }
Ejemplo n.º 40
0
 public void ApplyDrawParameters(RenderDrawContext context, ParameterCollection parameters, FastListStruct <LightDynamicEntry> currentLights, ref BoundingBoxExt boundingBox)
 {
 }
Ejemplo n.º 41
0
        private void PrepareModels(RenderContext context, List <RenderModel> renderModels, RenderItemCollection opaqueList, RenderItemCollection transparentList)
        {
            // If no camera, early exit
            var camera = context.GetCurrentCamera();

            if (camera == null)
            {
                return;
            }

            var viewProjectionMatrix = camera.ViewProjectionMatrix;
            var preRenderModel       = Callbacks.PreRenderModel;

            var sceneCameraRenderer = context.Tags.Get(SceneCameraRenderer.Current);
            var cullingMode         = sceneCameraRenderer != null ? sceneCameraRenderer.CullingMode : CullingMode.None;
            var frustum             = new BoundingFrustum(ref viewProjectionMatrix);

            var cameraRenderMode = sceneCameraRenderer != null ? sceneCameraRenderer.Mode : null;

            foreach (var renderModel in renderModels)
            {
                // If Model is null, then skip it
                if (renderModel.Model == null)
                {
                    continue;
                }

                if (preRenderModel != null)
                {
                    if (!preRenderModel(context, renderModel))
                    {
                        continue;
                    }
                }

                // Always prepare the slot for the render meshes even if they are not used.
                EnsureRenderMeshes(renderModel);

                var meshes = PrepareModelForRendering(context, renderModel);

                foreach (var renderMesh in meshes)
                {
                    if (!renderMesh.Enabled)
                    {
                        continue;
                    }

                    var worldMatrix = renderMesh.WorldMatrix;

                    // Perform frustum culling
                    if (cullingMode == CullingMode.Frustum)
                    {
                        // Always render meshes with unspecified bounds
                        // TODO: This should not be necessary. Add proper bounding boxes to gizmos etc.
                        var boundingBox = renderMesh.Mesh.BoundingBox;
                        if (boundingBox.Extent != Vector3.Zero)
                        {
                            // Fast AABB transform: http://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/
                            // Compute transformed AABB (by world)
                            var boundingBoxExt = new BoundingBoxExt(boundingBox);
                            boundingBoxExt.Transform(worldMatrix);

                            if (!frustum.Contains(ref boundingBoxExt))
                            {
                                continue;
                            }
                        }
                    }

                    // Project the position
                    // TODO: This could be done in a SIMD batch, but we need to figure-out how to plugin in with RenderMesh object
                    var     worldPosition = new Vector4(worldMatrix.TranslationVector, 1.0f);
                    Vector4 projectedPosition;
                    Vector4.Transform(ref worldPosition, ref viewProjectionMatrix, out projectedPosition);
                    var projectedZ = projectedPosition.Z / projectedPosition.W;

                    // TODO: Should this be set somewhere else?
                    var rasterizerState = cameraRenderMode != null?cameraRenderMode.GetDefaultRasterizerState(renderMesh.RenderModel.IsGeometryInverted) : null;

                    renderMesh.RasterizerState = RasterizerState ?? rasterizerState;

                    renderMesh.UpdateMaterial();
                    var list = renderMesh.HasTransparency ? transparentList : opaqueList;
                    list.Add(new RenderItem(this, renderMesh, projectedZ));
                }
            }
        }
Ejemplo n.º 42
0
 /// <summary>
 /// Applies PerDraw lighting parameters.
 /// </summary>
 /// <param name="context"></param>
 /// <param name="viewIndex"></param>
 /// <param name="parameters"></param>
 /// <param name="boundingBox"></param>
 public virtual void ApplyDrawParameters(RenderDrawContext context, int viewIndex, ParameterCollection parameters, ref BoundingBoxExt boundingBox)
 {
 }
Ejemplo n.º 43
0
            public override void ApplyDrawParameters(RenderDrawContext context, int viewIndex, ParameterCollection parameters, ref BoundingBoxExt boundingBox)
            {
                CurrentLights.Clear();
                var lightRange = LightRanges[viewIndex];

                for (int i = lightRange.Start; i < lightRange.End; ++i)
                {
                    CurrentLights.Add(Lights[i]);
                }

                base.ApplyDrawParameters(context, viewIndex, parameters, ref boundingBox);

                // TODO: Since we cull per object, we could maintain a higher number of allowed light than the shader support (i.e. 4 lights active per object even though the scene has many more of them)
                // TODO: Octree structure to select best lights quicker
                var boundingBox2 = (BoundingBox)boundingBox;

                foreach (var lightEntry in CurrentLights)
                {
                    var light = lightEntry.Light;

                    if (light.BoundingBox.Intersects(ref boundingBox2))
                    {
                        var pointLight = (LightPoint)light.Type;
                        lightsData.Add(new PointLightData
                        {
                            PositionWS      = light.Position,
                            InvSquareRadius = pointLight.InvSquareRadius,
                            Color           = light.Color,
                        });

                        // Did we reach max number of simultaneous lights?
                        // TODO: Still collect everything but sort by importance and remove the rest?
                        if (lightsData.Count >= LightCurrentCount)
                        {
                            break;
                        }
                    }
                }

                parameters.Set(countKey, lightsData.Count);
                parameters.Set(lightsKey, lightsData.Count, ref lightsData.Items[0]);
                lightsData.Clear();
            }
Ejemplo n.º 44
0
            public override void ApplyDrawParameters(RenderDrawContext context, int viewIndex, ParameterCollection parameters, ref BoundingBoxExt boundingBox)
            {
                CurrentLights.Clear();
                var lightRange = LightRanges[viewIndex];

                for (int i = lightRange.Start; i < lightRange.End; ++i)
                {
                    CurrentLights.Add(Lights[i]);
                }

                base.ApplyDrawParameters(context, viewIndex, parameters, ref boundingBox);

                // TODO: Octree structure to select best lights quicker
                var boundingBox2 = (BoundingBox)boundingBox;

                foreach (var lightEntry in CurrentLights)
                {
                    var light = lightEntry.Light;

                    if (light.BoundingBox.Intersects(ref boundingBox2))
                    {
                        var spotLight = (LightSpot)light.Type;
                        lightsData.Add(new SpotLightData
                        {
                            PositionWS  = light.Position,
                            DirectionWS = light.Direction,
                            AngleOffsetAndInvSquareRadius = new Vector3(spotLight.LightAngleScale, spotLight.LightAngleOffset, spotLight.InvSquareRange),
                            Color = light.Color,
                        });

                        // Did we reach max number of simultaneous lights?
                        // TODO: Still collect everything but sort by importance and remove the rest?
                        if (lightsData.Count >= LightCurrentCount)
                        {
                            break;
                        }
                    }
                }

                parameters.Set(countKey, lightsData.Count);
                parameters.Set(lightsKey, lightsData.Count, ref lightsData.Items[0]);
                lightsData.Clear();
            }
Ejemplo n.º 45
0
            public void ApplyDrawParameters(RenderDrawContext context, ParameterCollection parameters, FastListStruct<LightDynamicEntry> currentLights, ref BoundingBoxExt boundingBox)
            {
                for (int lightIndex = 0; lightIndex < currentLights.Count; ++lightIndex)
                {
                    var lightEntry = currentLights[lightIndex];

                    var singleLightData = (LightSpotShadowMapShaderData)lightEntry.ShadowMapTexture.ShaderData;
                    worldToShadowCascadeUV[lightIndex] = singleLightData.WorldToShadowCascadeUV;

                    depthBiases[lightIndex] = singleLightData.DepthBias;
                    offsetScales[lightIndex] = singleLightData.OffsetScale;

                    // TODO: should be setup just once at creation time
                    if (lightIndex == 0)
                    {
                        shadowMapTexture = singleLightData.Texture;
                        if (shadowMapTexture != null)
                        {
                            shadowMapTextureSize = new Vector2(shadowMapTexture.Width, shadowMapTexture.Height);
                            shadowMapTextureTexelSize = 1.0f / shadowMapTextureSize;
                        }
                    }
                }

                parameters.Set(shadowMapTextureKey, shadowMapTexture);
                parameters.Set(shadowMapTextureSizeKey, shadowMapTextureSize);
                parameters.Set(shadowMapTextureTexelSizeKey, shadowMapTextureTexelSize);
                parameters.Set(worldToShadowCascadeUVsKey, worldToShadowCascadeUV);
                parameters.Set(depthBiasesKey, depthBiases);
                parameters.Set(offsetScalesKey, offsetScales);
            }
            public override void ApplyDrawParameters(RenderDrawContext context, ParameterCollection parameters, FastListStruct <LightDynamicEntry> currentLights, ref BoundingBoxExt boundingBox)
            {
                var  boundingBox2     = (BoundingBox)boundingBox;
                bool shadowMapCreated = false;
                int  lightIndex       = 0;

                lock (locker)
                {
                    for (int i = 0; i < currentLights.Count; ++i)
                    {
                        var lightEntry = currentLights[i];
                        if (lightEntry.Light.BoundingBox.Intersects(ref boundingBox2))
                        {
                            var shaderData = (ShaderData)lightEntry.ShadowMapTexture.ShaderData;
                            offsets[lightIndex]         = shaderData.Offset;
                            backfaceOffsets[lightIndex] = shaderData.BackfaceOffset;
                            faceSizes[lightIndex]       = shaderData.FaceSize;
                            depthParameters[lightIndex] = shaderData.DepthParameters;
                            depthBiases[lightIndex]     = shaderData.DepthBias;
                            viewMatrices[lightIndex]    = shaderData.View;
                            lightIndex++;

                            // TODO: should be setup just once at creation time
                            if (!shadowMapCreated)
                            {
                                shadowMapTexture = shaderData.Texture;
                                if (shadowMapTexture != null)
                                {
                                    shadowMapTextureSize      = new Vector2(shadowMapTexture.Width, shadowMapTexture.Height);
                                    shadowMapTextureTexelSize = 1.0f / shadowMapTextureSize;
                                }
                                shadowMapCreated = true;
                            }
                        }
                    }

                    parameters.Set(shadowMapTextureKey, shadowMapTexture);
                    parameters.Set(shadowMapTextureSizeKey, shadowMapTextureSize);
                    parameters.Set(shadowMapTextureTexelSizeKey, shadowMapTextureTexelSize);

                    parameters.Set(viewKey, viewMatrices);
                    parameters.Set(offsetsKey, offsets);
                    parameters.Set(backfaceOffsetsKey, backfaceOffsets);
                    parameters.Set(faceSizesKey, faceSizes);
                    parameters.Set(depthParametersKey, depthParameters);

                    parameters.Set(depthBiasesKey, depthBiases);
                }
            }
Ejemplo n.º 47
0
        private static void CalculateMinMaxDistance(ref Plane plane, ref BoundingBoxExt boundingBox, ref float minDistance, ref float maxDistance)
        {
            var nearCorner = boundingBox.Minimum;
            var farCorner = boundingBox.Maximum;
            
            if (plane.Normal.X < 0)
                Utilities.Swap(ref nearCorner.X, ref farCorner.X);

            if (plane.Normal.Y < 0)
                Utilities.Swap(ref nearCorner.Y, ref farCorner.Y);

            if (plane.Normal.Z < 0)
                Utilities.Swap(ref nearCorner.Z, ref farCorner.Z);

            float oldDistance;

            // Interlocked exchange if lower
            var distance = CollisionHelper.DistancePlanePoint(ref plane, ref nearCorner);
            while ((oldDistance = minDistance) > distance && Interlocked.CompareExchange(ref minDistance, distance, oldDistance) != oldDistance) { }

            // Interlocked exchange if greater
            distance = CollisionHelper.DistancePlanePoint(ref plane, ref farCorner);
            while ((oldDistance = maxDistance) < distance && Interlocked.CompareExchange(ref maxDistance, distance, oldDistance) != oldDistance) { }
        }