Beispiel #1
0
            /// <summary>
            /// Creates a new Structured buffer <see cref="GraphicsResourceUsage.Default" /> uasge.
            /// </summary>
            /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
            /// <param name="value">The value to initialize the Structured buffer.</param>
            /// <param name="elementSize">Size of the element.</param>
            /// <param name="isUnorderedAccess">if set to <c>true</c> this buffer supports unordered access (RW in HLSL).</param>
            /// <returns>A Structured buffer</returns>
            public static Buffer New(GraphicsDevice device, DataPointer value, int elementSize, bool isUnorderedAccess = false)
            {
                var bufferFlags = BufferFlags.StructuredBuffer | BufferFlags.ShaderResource;

                if (isUnorderedAccess)
                {
                    bufferFlags |= BufferFlags.UnorderedAccess;
                }

                return(Buffer.New(device, value, elementSize, bufferFlags));
            }
Beispiel #2
0
        /// <summary>
        /// Creates an Entity that contains our dynamic Vertex and Index buffers.
        /// This Entity will be rendered by the model renderer.
        /// </summary>
        /// <param name="verticesCount"></param>
        /// <param name="indicesCount"></param>
        private void CreateTerrainModelEntity(int verticesCount, int indicesCount)
        {
            // Compute sizes
            var vertexDeclaration = VertexNormalTexture.VertexDeclaration;
            var vertexBufferSize  = verticesCount * vertexDeclaration.CalculateSize();
            var indexBufferSize   = indicesCount * sizeof(short);

            // Create Vertex and Index buffers
            terrainVertexBuffer = Buffer.Vertex.New(GraphicsDevice, vertexBufferSize, GraphicsResourceUsage.Dynamic);
            terrainIndexBuffer  = Buffer.New(GraphicsDevice, indexBufferSize, BufferFlags.IndexBuffer, GraphicsResourceUsage.Dynamic);

            // Prepare mesh and entity
            var meshDraw = new MeshDraw
            {
                PrimitiveType = PrimitiveType.TriangleStrip,
                VertexBuffers = new[] { new VertexBufferBinding(terrainVertexBuffer, vertexDeclaration, verticesCount) },
                IndexBuffer   = new IndexBufferBinding(terrainIndexBuffer, false, indicesCount),
            };

            // Load the material and set parameters
            TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MeshTexture0, WaterTexture);
            TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MeshTexture1, GrassTexture);
            TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MeshTexture2, MountainTexture);

            // Set up material regions
            TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MinimumHeight0, -10);
            TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.OptimalHeight0, 40);
            TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MaximumHeight0, 70);

            TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MinimumHeight1, 60);
            TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.OptimalHeight1, 80);
            TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MaximumHeight1, 90);

            TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MinimumHeight2, 85);
            TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.OptimalHeight2, 95);
            TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MaximumHeight2, 125);

            terrainMesh = new Mesh {
                Draw = meshDraw, MaterialIndex = 0
            };
            TerrainEntity.GetOrCreate <ModelComponent>().Model = new Model {
                terrainMesh, TerrainMaterial
            };
        }
Beispiel #3
0
 /// <summary>
 /// Creates a new Typed buffer <see cref="GraphicsResourceUsage.Default" /> uasge.
 /// </summary>
 /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
 /// <param name="count">The number of data with the following viewFormat.</param>
 /// <param name="viewFormat">The view format of the buffer.</param>
 /// <param name="isUnorderedAccess">if set to <c>true</c> this buffer supports unordered access (RW in HLSL).</param>
 /// <param name="usage">The usage.</param>
 /// <returns>A Typed buffer</returns>
 public static Buffer New(GraphicsDevice device, int count, PixelFormat viewFormat, bool isUnorderedAccess = false, GraphicsResourceUsage usage = GraphicsResourceUsage.Default)
 {
     return(Buffer.New(device, count * viewFormat.SizeInBytes(), BufferFlags.ShaderResource | (isUnorderedAccess ? BufferFlags.UnorderedAccess : BufferFlags.None), viewFormat, usage));
 }
Beispiel #4
0
            /// <summary>
            /// Creates a new StructuredCounter buffer <see cref="GraphicsResourceUsage.Default" /> uasge.
            /// </summary>
            /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
            /// <param name="value">The value to initialize the StructuredCounter buffer.</param>
            /// <param name="elementSize">Size of the element.</param>
            /// <returns>A StructuredCounter buffer</returns>
            public static Buffer New(GraphicsDevice device, DataPointer value, int elementSize)
            {
                const BufferFlags BufferFlags = BufferFlags.StructuredCounterBuffer | BufferFlags.ShaderResource | BufferFlags.UnorderedAccess;

                return(Buffer.New(device, value, elementSize, BufferFlags));
            }
Beispiel #5
0
            /// <summary>
            /// Creates a new StructuredCounter buffer <see cref="GraphicsResourceUsage.Default" /> uasge.
            /// </summary>
            /// <typeparam name="T">Type of the StructuredCounter buffer to get the sizeof from</typeparam>
            /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
            /// <param name="value">The value to initialize the StructuredCounter buffer.</param>
            /// <returns>A StructuredCounter buffer</returns>
            public static Buffer New <T>(GraphicsDevice device, T[] value) where T : struct
            {
                const BufferFlags BufferFlags = BufferFlags.StructuredCounterBuffer | BufferFlags.ShaderResource | BufferFlags.UnorderedAccess;

                return(Buffer.New(device, value, BufferFlags));
            }
Beispiel #6
0
 /// <summary>
 /// Creates a new Raw buffer with <see cref="GraphicsResourceUsage.Default"/> uasge by default.
 /// </summary>
 /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
 /// <param name="value">The value to initialize the Raw buffer.</param>
 /// <param name="additionalBindings">The additional bindings (for example, to create a combined raw/index buffer, pass <see cref="BufferFlags.IndexBuffer" />)</param>
 /// <param name="usage">The usage of this resource.</param>
 /// <returns>A Raw buffer</returns>
 public static Buffer New(GraphicsDevice device, DataPointer value, BufferFlags additionalBindings = BufferFlags.None, GraphicsResourceUsage usage = GraphicsResourceUsage.Default)
 {
     return(Buffer.New(device, value, 0, BufferFlags.RawBuffer | additionalBindings, usage));
 }
            public override unsafe void ApplyViewParameters(RenderDrawContext context, int viewIndex, ParameterCollection parameters)
            {
                // Note: no need to fill CurrentLights since we have no shadow maps
                base.ApplyViewParameters(context, viewIndex, parameters);

                var renderView = renderViews[viewIndex];

                var viewSize = renderView.ViewSize;

                // No screen size set?
                if (viewSize.X == 0 || viewSize.Y == 0)
                {
                    return;
                }

                var clusterCountX = ((int)viewSize.X + ClusterSize - 1) / ClusterSize;
                var clusterCountY = ((int)viewSize.Y + ClusterSize - 1) / ClusterSize;

                // TODO: Additional culling on x/y (to remove corner clusters)
                // Prepare planes for culling
                //var viewProjection = renderView.ViewProjection;
                //Array.Resize(ref zPlanes, ClusterSlices + 1);
                //for (int z = 0; z <= ClusterSlices; ++z)
                //{
                //    var zFactor = (float)z / (float)ClusterSlices;
                //
                //    // Build planes between nearplane and -farplane (see BoundingFrustum code)
                //    zPlanes[z] = new Plane(
                //        viewProjection.M13 - zFactor * viewProjection.M14,
                //        viewProjection.M23 - zFactor * viewProjection.M24,
                //        viewProjection.M33 - zFactor * viewProjection.M34,
                //        viewProjection.M43 - zFactor * viewProjection.M44);
                //
                //    zPlanes[z].Normalize();
                //}

                if (pointGroupRenderer.lightClusters == null || lightClustersValues.Length != clusterCountX * clusterCountY * ClusterSlices)
                {
                    // First time?
                    pointGroupRenderer.lightClusters?.Dispose();
                    pointGroupRenderer.lightClusters = Texture.New3D(context.GraphicsDevice, clusterCountX, clusterCountY, 8, PixelFormat.R32G32_UInt);
                    lightClustersValues = new Int2[clusterCountX * clusterCountY * ClusterSlices];
                }

                // Initialize cluster with no light (-1)
                for (int i = 0; i < clusterCountX * clusterCountY * ClusterSlices; ++i)
                {
                    lightNodes.Add(new LightClusterLinkedNode(LightType.Point, -1, -1));
                }

                // List of clusters moved by this light
                var movedClusters = new Dictionary <LightClusterLinkedNode, int>();

                // Try to use SpecialNearPlane to not waste too much slices in very small depth
                // Make sure we don't go to more than 10% of max depth
                var nearPlane = Math.Max(Math.Min(SpecialNearPlane, renderView.FarClipPlane * 0.1f), renderView.NearClipPlane);

                //var sliceBias = ((renderView.NearClipPlane * renderView.Projection.M33) + renderView.Projection.M43) / (renderView.NearClipPlane * renderView.Projection.M34);
                // Compute scale and bias so that near_plane..special_near fits in slice 0, then grow exponentionally
                //   log2(specialNear * scale + bias) == 1.0
                //   log2(far * scale + bias) == ClusterSlices
                // as a result:
                clusterDepthScale = (float)(Math.Pow(2.0f, ClusterSlices) - 2.0f) / (renderView.FarClipPlane - nearPlane);
                clusterDepthBias  = 2.0f - clusterDepthScale * nearPlane;

                //---------------- SPOT LIGHTS -------------------
                var lightRange = pointGroupRenderer.spotGroup.LightRanges[viewIndex];

                for (int i = lightRange.Start; i < lightRange.End; ++i)
                {
                    var light     = pointGroupRenderer.spotGroup.Lights[i].Light;
                    var spotLight = (LightSpot)light.Type;

                    if (spotLight.Shadow != null && spotLight.Shadow.Enabled)
                    {
                        continue;
                    }

                    // Create spot light data
                    var spotLightData = new SpotLightData
                    {
                        PositionWS  = light.Position,
                        DirectionWS = light.Direction,
                        AngleOffsetAndInvSquareRadius = new Vector3(spotLight.LightAngleScale, spotLight.LightAngleOffset, spotLight.InvSquareRange),
                        Color = light.Color,
                    };

                    // Fill list of spot lights
                    spotLights.Add(spotLightData);

                    movedClusters.Clear();

                    var radius = (float)Math.Sqrt(1.0f / spotLightData.AngleOffsetAndInvSquareRadius.Z);

                    Vector3 positionVS;
                    Vector3.TransformCoordinate(ref spotLightData.PositionWS, ref renderView.View, out positionVS);

                    // TODO: culling (first do it on PointLight, then backport it to SpotLight and improve for SpotLight case)
                    // Find x/y ranges
                    Vector2 clipMin, clipMax;
                    ComputeClipRegion(positionVS, radius, ref renderView.Projection, out clipMin, out clipMax);

                    var tileStartX = MathUtil.Clamp((int)((clipMin.X * 0.5f + 0.5f) * viewSize.X / ClusterSize), 0, clusterCountX);
                    var tileEndX   = MathUtil.Clamp((int)((clipMax.X * 0.5f + 0.5f) * viewSize.X / ClusterSize) + 1, 0, clusterCountX);
                    var tileStartY = MathUtil.Clamp((int)((-clipMax.Y * 0.5f + 0.5f) * viewSize.Y / ClusterSize), 0, clusterCountY);
                    var tileEndY   = MathUtil.Clamp((int)((-clipMin.Y * 0.5f + 0.5f) * viewSize.Y / ClusterSize) + 1, 0, clusterCountY);

                    // Find z range (project using Projection matrix)
                    var startZ = -positionVS.Z - radius;
                    var endZ   = -positionVS.Z + radius;

                    var tileStartZ = MathUtil.Clamp((int)Math.Log(startZ * clusterDepthScale + clusterDepthBias, 2.0f), 0, ClusterSlices);
                    var tileEndZ   = MathUtil.Clamp((int)Math.Log(endZ * clusterDepthScale + clusterDepthBias, 2.0f) + 1, 0, ClusterSlices);

                    for (int z = tileStartZ; z < tileEndZ; ++z)
                    {
                        for (int y = tileStartY; y < tileEndY; ++y)
                        {
                            for (int x = tileStartX; x < tileEndX; ++x)
                            {
                                AddLightToCluster(movedClusters, LightType.Spot, i - lightRange.Start, x + (y + z * clusterCountY) * clusterCountX);
                            }
                        }
                    }
                }

                //---------------- POINT LIGHTS -------------------
                lightRange = LightRanges[viewIndex];
                for (int i = lightRange.Start; i < lightRange.End; ++i)
                {
                    var light      = Lights[i].Light;
                    var pointLight = (LightPoint)light.Type;

                    // Create point light data
                    var pointLightData = new PointLightData
                    {
                        PositionWS      = light.Position,
                        InvSquareRadius = pointLight.InvSquareRadius,
                        Color           = light.Color,
                    };

                    // Fill list of point lights
                    pointLights.Add(pointLightData);

                    movedClusters.Clear();

                    var radius = (float)Math.Sqrt(1.0f / pointLightData.InvSquareRadius);

                    Vector3 positionVS;
                    Vector3.TransformCoordinate(ref pointLightData.PositionWS, ref renderView.View, out positionVS);

                    //Vector3 positionScreen;
                    //Vector3.TransformCoordinate(ref pointLightData.PositionWS, ref renderView.ViewProjection, out positionScreen);

                    // Find x/y ranges
                    Vector2 clipMin, clipMax;
                    ComputeClipRegion(positionVS, radius, ref renderView.Projection, out clipMin, out clipMax);

                    var tileStartX = MathUtil.Clamp((int)((clipMin.X * 0.5f + 0.5f) * viewSize.X / ClusterSize), 0, clusterCountX);
                    var tileEndX   = MathUtil.Clamp((int)((clipMax.X * 0.5f + 0.5f) * viewSize.X / ClusterSize) + 1, 0, clusterCountX);
                    var tileStartY = MathUtil.Clamp((int)((-clipMax.Y * 0.5f + 0.5f) * viewSize.Y / ClusterSize), 0, clusterCountY);
                    var tileEndY   = MathUtil.Clamp((int)((-clipMin.Y * 0.5f + 0.5f) * viewSize.Y / ClusterSize) + 1, 0, clusterCountY);

                    // Find z range (project using Projection matrix)
                    var startZ = -positionVS.Z - radius;
                    var endZ   = -positionVS.Z + radius;

                    //var centerZ = (int)(positionVS.Z * ClusterDepthScale + ClusterDepthBias);
                    var tileStartZ = MathUtil.Clamp((int)Math.Log(startZ * clusterDepthScale + clusterDepthBias, 2.0f), 0, ClusterSlices);
                    var tileEndZ   = MathUtil.Clamp((int)Math.Log(endZ * clusterDepthScale + clusterDepthBias, 2.0f) + 1, 0, ClusterSlices);

                    for (int z = tileStartZ; z < tileEndZ; ++z)
                    {
                        // TODO: Additional culling on x/y (to remove corner clusters)
                        // See "Practical Clustered Shading" for details
                        //if (z != centerZ)
                        //{
                        //    var plane = z < centerZ ? zPlanes[z + 1] : -zPlanes[z];
                        //
                        //    positionScreen = Plane.DotCoordinate(ref plane, ref positionScreen, out )
                        //}

                        for (int y = tileStartY; y < tileEndY; ++y)
                        {
                            for (int x = tileStartX; x < tileEndX; ++x)
                            {
                                AddLightToCluster(movedClusters, LightType.Point, i - lightRange.Start, x + (y + z * clusterCountY) * clusterCountX);
                            }
                        }
                    }
                }

                // Finish clusters by making their last element unique and building clusterInfos
                movedClusters.Clear();
                for (int i = 0; i < clusterCountX * clusterCountY * ClusterSlices; ++i)
                {
                    FinishCluster(movedClusters, i);
                }

                // Prepare light clusters
                for (int i = 0; i < clusterCountX * clusterCountY * ClusterSlices; ++i)
                {
                    var clusterId = lightNodes[i].NextNode;
                    lightClustersValues[i] = clusterId != -1 ? clusterInfos[clusterId] : new Int2(0, 0);
                }

                // Upload data to texture
                using (new DefaultCommandListLock(context.CommandList))
                {
                    fixed(Int2 *dataPtr = lightClustersValues)
                    context.CommandList.UpdateSubresource(pointGroupRenderer.lightClusters, 0, new DataBox((IntPtr)dataPtr, sizeof(Int2) * clusterCountX, sizeof(Int2) * clusterCountX * clusterCountY));

                    // PointLights: Ensure size and update
                    if (pointLights.Count > 0)
                    {
                        if (pointGroupRenderer.pointLightsBuffer == null || pointGroupRenderer.pointLightsBuffer.SizeInBytes < pointLights.Count * sizeof(PointLightData))
                        {
                            pointGroupRenderer.pointLightsBuffer?.Dispose();
                            pointGroupRenderer.pointLightsBuffer = Buffer.New(context.GraphicsDevice, MathUtil.NextPowerOfTwo(pointLights.Count * sizeof(PointLightData)), 0, BufferFlags.ShaderResource, PixelFormat.R32G32B32A32_Float);
                        }
                        fixed(PointLightData *pointLightsPtr = pointLights.Items)
                        context.CommandList.UpdateSubresource(pointGroupRenderer.pointLightsBuffer, 0, new DataBox((IntPtr)pointLightsPtr, 0, 0), new ResourceRegion(0, 0, 0, pointLights.Count * sizeof(PointLightData), 1, 1));
                    }
#if SILICONSTUDIO_PLATFORM_MACOS
                    // macOS doesn't like when we provide a null Buffer or if it is not sufficiently allocated.
                    // It would cause an inifite loop. So for now we just create one with one element but not initializing it.
                    else if (pointGroupRenderer.pointLightsBuffer == null || pointGroupRenderer.pointLightsBuffer.SizeInBytes < sizeof(PointLightData))
                    {
                        pointGroupRenderer.pointLightsBuffer?.Dispose();
                        pointGroupRenderer.pointLightsBuffer = Buffer.New(context.GraphicsDevice, MathUtil.NextPowerOfTwo(sizeof(PointLightData)), 0, BufferFlags.ShaderResource, PixelFormat.R32G32B32A32_Float);
                    }
#endif

                    // SpotLights: Ensure size and update
                    if (spotLights.Count > 0)
                    {
                        if (pointGroupRenderer.spotLightsBuffer == null || pointGroupRenderer.spotLightsBuffer.SizeInBytes < spotLights.Count * sizeof(SpotLightData))
                        {
                            pointGroupRenderer.spotLightsBuffer?.Dispose();
                            pointGroupRenderer.spotLightsBuffer = Buffer.New(context.GraphicsDevice, MathUtil.NextPowerOfTwo(spotLights.Count * sizeof(SpotLightData)), 0, BufferFlags.ShaderResource,
                                                                             PixelFormat.R32G32B32A32_Float);
                        }
                        fixed(SpotLightData *spotLightsPtr = spotLights.Items)
                        context.CommandList.UpdateSubresource(pointGroupRenderer.spotLightsBuffer, 0, new DataBox((IntPtr)spotLightsPtr, 0, 0),
                                                              new ResourceRegion(0, 0, 0, spotLights.Count * sizeof(SpotLightData), 1, 1));
                    }
#if SILICONSTUDIO_PLATFORM_MACOS
                    // See previous macOS comment.
                    else if (pointGroupRenderer.spotLightsBuffer == null || pointGroupRenderer.spotLightsBuffer.SizeInBytes < sizeof(SpotLightData))
                    {
                        pointGroupRenderer.spotLightsBuffer?.Dispose();
                        pointGroupRenderer.spotLightsBuffer = Buffer.New(context.GraphicsDevice, MathUtil.NextPowerOfTwo(sizeof(SpotLightData)), 0, BufferFlags.ShaderResource, PixelFormat.R32G32B32A32_Float);
                    }
#endif
                    // LightIndices: Ensure size and update
                    if (lightIndices.Count > 0)
                    {
                        if (pointGroupRenderer.lightIndicesBuffer == null || pointGroupRenderer.lightIndicesBuffer.SizeInBytes < lightIndices.Count * sizeof(int))
                        {
                            pointGroupRenderer.lightIndicesBuffer?.Dispose();
                            pointGroupRenderer.lightIndicesBuffer = Buffer.New(context.GraphicsDevice, MathUtil.NextPowerOfTwo(lightIndices.Count * sizeof(int)), 0, BufferFlags.ShaderResource,
                                                                               PixelFormat.R32_UInt);
                        }
                        fixed(int *lightIndicesPtr = lightIndices.Items)
                        context.CommandList.UpdateSubresource(pointGroupRenderer.lightIndicesBuffer, 0, new DataBox((IntPtr)lightIndicesPtr, 0, 0),
                                                              new ResourceRegion(0, 0, 0, lightIndices.Count * sizeof(int), 1, 1));
                    }
#if SILICONSTUDIO_PLATFORM_MACOS
                    // See previous macOS comment.
                    else if (pointGroupRenderer.lightIndicesBuffer == null || pointGroupRenderer.lightIndicesBuffer.SizeInBytes < sizeof(int))
                    {
                        pointGroupRenderer.lightIndicesBuffer?.Dispose();
                        pointGroupRenderer.lightIndicesBuffer = Buffer.New(context.GraphicsDevice, MathUtil.NextPowerOfTwo(sizeof(int)), 0, BufferFlags.ShaderResource, PixelFormat.R32_UInt);
                    }
#endif
                }

                // Clear data
                pointLights.Clear();
                spotLights.Clear();
                lightIndices.Clear();
                lightNodes.Clear();
                clusterInfos.Clear();

                // Set resources
                parameters.Set(LightClusteredPointGroupKeys.PointLights, pointGroupRenderer.pointLightsBuffer);
                parameters.Set(LightClusteredSpotGroupKeys.SpotLights, pointGroupRenderer.spotLightsBuffer);
                parameters.Set(LightClusteredKeys.LightIndices, pointGroupRenderer.lightIndicesBuffer);
                parameters.Set(LightClusteredKeys.LightClusters, pointGroupRenderer.lightClusters);

                parameters.Set(LightClusteredKeys.ClusterDepthScale, clusterDepthScale);
                parameters.Set(LightClusteredKeys.ClusterDepthBias, clusterDepthBias);
            }
        public void Generate(IServiceRegistry services, Model model)
        {
            if (model == null)
            {
                throw new ArgumentNullException(nameof(model));
            }

            var needsTempDevice = false;
            var graphicsDevice  = services?.GetSafeServiceAs <IGraphicsDeviceService>().GraphicsDevice;

            if (graphicsDevice == null)
            {
                graphicsDevice  = GraphicsDevice.New();
                needsTempDevice = true;
            }

            var data = CreatePrimitiveMeshData();

            if (data.Vertices.Length == 0)
            {
                throw new InvalidOperationException("Invalid GeometricPrimitive [{0}]. Expecting non-zero Vertices array");
            }

            if (LocalOffset != Vector3.Zero)
            {
                for (var index = 0; index < data.Vertices.Length; index++)
                {
                    data.Vertices[index].Position += LocalOffset;
                }
            }

            //Scale if necessary
            if (Scale != Vector3.One)
            {
                var inverseMatrix = Matrix.Scaling(Scale);
                inverseMatrix.Invert();
                for (var index = 0; index < data.Vertices.Length; index++)
                {
                    data.Vertices[index].Position *= Scale;
                    Vector3.TransformCoordinate(ref data.Vertices[index].Normal, ref inverseMatrix, out data.Vertices[index].Normal);
                }
            }

            var boundingBox = BoundingBox.Empty;

            for (int i = 0; i < data.Vertices.Length; i++)
            {
                BoundingBox.Merge(ref boundingBox, ref data.Vertices[i].Position, out boundingBox);
            }

            BoundingSphere boundingSphere;

            unsafe
            {
                fixed(void *verticesPtr = data.Vertices)
                BoundingSphere.FromPoints((IntPtr)verticesPtr, 0, data.Vertices.Length, VertexPositionNormalTexture.Size, out boundingSphere);
            }

            var originalLayout = data.Vertices[0].GetLayout();

            // Generate Tangent/BiNormal vectors
            var resultWithTangentBiNormal = VertexHelper.GenerateTangentBinormal(originalLayout, data.Vertices, data.Indices);

            // Generate Multitexcoords
            var result = VertexHelper.GenerateMultiTextureCoordinates(resultWithTangentBiNormal);

            var meshDraw = new MeshDraw();

            var layout       = result.Layout;
            var vertexBuffer = result.VertexBuffer;
            var indices      = data.Indices;

            if (indices.Length < 0xFFFF)
            {
                var indicesShort = new ushort[indices.Length];
                for (int i = 0; i < indicesShort.Length; i++)
                {
                    indicesShort[i] = (ushort)indices[i];
                }
                meshDraw.IndexBuffer = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indicesShort).RecreateWith(indicesShort), false, indices.Length);
                if (needsTempDevice)
                {
                    var indexData = BufferData.New(BufferFlags.IndexBuffer, indicesShort);
                    meshDraw.IndexBuffer = new IndexBufferBinding(indexData.ToSerializableVersion(), false, indices.Length);
                }
            }
            else
            {
                if (graphicsDevice.Features.CurrentProfile <= GraphicsProfile.Level_9_3)
                {
                    throw new InvalidOperationException("Cannot generate more than 65535 indices on feature level HW <= 9.3");
                }

                meshDraw.IndexBuffer = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indices).RecreateWith(indices), true, indices.Length);
                if (needsTempDevice)
                {
                    var indexData = BufferData.New(BufferFlags.IndexBuffer, indices);
                    meshDraw.IndexBuffer = new IndexBufferBinding(indexData.ToSerializableVersion(), true, indices.Length);
                }
            }

            meshDraw.VertexBuffers = new[] { new VertexBufferBinding(Buffer.New(graphicsDevice, vertexBuffer, BufferFlags.VertexBuffer).RecreateWith(vertexBuffer), layout, data.Vertices.Length) };
            if (needsTempDevice)
            {
                var vertexData = BufferData.New(BufferFlags.VertexBuffer, vertexBuffer);
                meshDraw.VertexBuffers = new[] { new VertexBufferBinding(vertexData.ToSerializableVersion(), layout, data.Vertices.Length) };
            }

            meshDraw.DrawCount     = indices.Length;
            meshDraw.PrimitiveType = PrimitiveType.TriangleList;

            var mesh = new Mesh {
                Draw = meshDraw, BoundingBox = boundingBox, BoundingSphere = boundingSphere
            };

            model.BoundingBox    = boundingBox;
            model.BoundingSphere = boundingSphere;
            model.Add(mesh);

            if (MaterialInstance?.Material != null)
            {
                model.Materials.Add(MaterialInstance);
            }

            if (needsTempDevice)
            {
                graphicsDevice.Dispose();
            }
        }
Beispiel #9
0
 /// <summary>
 /// Creates a new constant buffer with <see cref="GraphicsResourceUsage.Dynamic"/> usage.
 /// </summary>
 /// <typeparam name="T">Type of the constant buffer to get the sizeof from</typeparam>
 /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
 /// <returns>A constant buffer</returns>
 public static Buffer <T> New <T>(GraphicsDevice device) where T : struct
 {
     return(Buffer.New <T>(device, 1, BufferFlags.ConstantBuffer, GraphicsResourceUsage.Dynamic));
 }
Beispiel #10
0
 /// <summary>
 /// Creates a new constant buffer with <see cref="GraphicsResourceUsage.Dynamic"/> usage.
 /// </summary>
 /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
 /// <param name="size">The size in bytes.</param>
 /// <returns>A constant buffer</returns>
 public static Buffer New(GraphicsDevice device, int size)
 {
     return(Buffer.New(device, size, BufferFlags.ConstantBuffer, GraphicsResourceUsage.Dynamic));
 }
Beispiel #11
0
 /// <summary>
 /// Creates a new index buffer with <see cref="GraphicsResourceUsage.Immutable"/> uasge by default.
 /// </summary>
 /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
 /// <param name="value">The value to initialize the index buffer.</param>
 /// <param name="is32BitIndex">Set to true if the buffer is using a 32 bit index or false for 16 bit index.</param>
 /// <param name="usage">The usage of this resource.</param>
 /// <returns>A index buffer</returns>
 public static Buffer New(GraphicsDevice device, byte[] value, bool is32BitIndex, GraphicsResourceUsage usage = GraphicsResourceUsage.Immutable)
 {
     return(Buffer.New(device, value, is32BitIndex ? 4 : 2, BufferFlags.IndexBuffer, PixelFormat.None, usage));
 }
Beispiel #12
0
 /// <summary>
 /// Creates a new index buffer with <see cref="GraphicsResourceUsage.Immutable"/> uasge by default.
 /// </summary>
 /// <typeparam name="T">Type of the index buffer to get the sizeof from</typeparam>
 /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
 /// <param name="value">The value to initialize the index buffer.</param>
 /// <param name="usage">The usage of this resource.</param>
 /// <returns>A index buffer</returns>
 public static Buffer <T> New <T>(GraphicsDevice device, T[] value, GraphicsResourceUsage usage = GraphicsResourceUsage.Immutable) where T : struct
 {
     return(Buffer.New(device, value, BufferFlags.IndexBuffer, usage));
 }
Beispiel #13
0
 /// <summary>
 /// Creates a new index buffer with <see cref="GraphicsResourceUsage.Default"/> uasge by default.
 /// </summary>
 /// <typeparam name="T">Type of the index buffer to get the sizeof from</typeparam>
 /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
 /// <param name="usage">The usage.</param>
 /// <returns>A index buffer</returns>
 public static Buffer <T> New <T>(GraphicsDevice device, GraphicsResourceUsage usage = GraphicsResourceUsage.Default) where T : struct
 {
     return(Buffer.New <T>(device, 1, BufferFlags.IndexBuffer, usage));
 }
Beispiel #14
0
 /// <summary>
 /// Creates a new index buffer with <see cref="GraphicsResourceUsage.Default"/> uasge by default.
 /// </summary>
 /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
 /// <param name="size">The size in bytes.</param>
 /// <param name="usage">The usage.</param>
 /// <returns>A index buffer</returns>
 public static Buffer New(GraphicsDevice device, int size, GraphicsResourceUsage usage = GraphicsResourceUsage.Default)
 {
     return(Buffer.New(device, size, BufferFlags.IndexBuffer, usage));
 }
Beispiel #15
0
 /// <summary>
 /// Creates a new index buffer with <see cref="GraphicsResourceUsage.Immutable"/> uasge by default.
 /// </summary>
 /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
 /// <param name="value">The value to initialize the index buffer.</param>
 /// <param name="usage">The usage of this resource.</param>
 /// <returns>A index buffer</returns>
 public static Buffer New(GraphicsDevice device, DataPointer value, GraphicsResourceUsage usage = GraphicsResourceUsage.Immutable)
 {
     return(Buffer.New(device, value, 0, BufferFlags.IndexBuffer, usage));
 }
Beispiel #16
0
 /// <summary>
 /// Creates a new Typed buffer <see cref="GraphicsResourceUsage.Default" /> uasge.
 /// </summary>
 /// <typeparam name="T">Type of the Typed buffer to get the sizeof from</typeparam>
 /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
 /// <param name="value">The value to initialize the Typed buffer.</param>
 /// <param name="viewFormat">The view format of the buffer.</param>
 /// <param name="isUnorderedAccess">if set to <c>true</c> this buffer supports unordered access (RW in HLSL).</param>
 /// <param name="usage">The usage of this resource.</param>
 /// <returns>A Typed buffer</returns>
 public static Buffer <T> New <T>(GraphicsDevice device, T[] value, PixelFormat viewFormat, bool isUnorderedAccess = false, GraphicsResourceUsage usage = GraphicsResourceUsage.Default) where T : struct
 {
     return(Buffer.New(device, value, BufferFlags.ShaderResource | (isUnorderedAccess ? BufferFlags.UnorderedAccess : BufferFlags.None), viewFormat, usage));
 }
Beispiel #17
0
 /// <summary>
 /// Creates a new Typed buffer <see cref="GraphicsResourceUsage.Default" /> uasge.
 /// </summary>
 /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
 /// <param name="value">The value to initialize the Typed buffer.</param>
 /// <param name="viewFormat">The view format of the buffer.</param>
 /// <param name="isUnorderedAccess">if set to <c>true</c> this buffer supports unordered access (RW in HLSL).</param>
 /// <param name="usage">The usage of this resource.</param>
 /// <returns>A Typed buffer</returns>
 public static Buffer New(GraphicsDevice device, DataPointer value, PixelFormat viewFormat, bool isUnorderedAccess = false, GraphicsResourceUsage usage = GraphicsResourceUsage.Default)
 {
     return(Buffer.New(device, value, 0, BufferFlags.ShaderResource | (isUnorderedAccess?BufferFlags.UnorderedAccess : BufferFlags.None), viewFormat, usage));
 }
Beispiel #18
0
 /// <summary>
 /// Creates a new constant buffer with <see cref="GraphicsResourceUsage.Dynamic"/> usage.
 /// </summary>
 /// <typeparam name="T">Type of the constant buffer to get the sizeof from</typeparam>
 /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
 /// <param name="value">The value to initialize the constant buffer.</param>
 /// <param name="usage">The usage of this resource.</param>
 /// <returns>A constant buffer</returns>
 public static Buffer <T> New <T>(GraphicsDevice device, T[] value, GraphicsResourceUsage usage = GraphicsResourceUsage.Dynamic) where T : struct
 {
     return(Buffer.New(device, value, BufferFlags.ConstantBuffer, usage));
 }
Beispiel #19
0
 /// <summary>
 /// Creates a new constant buffer with <see cref="GraphicsResourceUsage.Dynamic"/> usage.
 /// </summary>
 /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
 /// <param name="value">The value to initialize the constant buffer.</param>
 /// <param name="usage">The usage of this resource.</param>
 /// <returns>A constant buffer</returns>
 public static Buffer New(GraphicsDevice device, DataPointer value, GraphicsResourceUsage usage = GraphicsResourceUsage.Dynamic)
 {
     return(Buffer.New(device, value, 0, BufferFlags.ConstantBuffer, usage));
 }
Beispiel #20
0
            /// <summary>
            /// Creates a new StructuredAppend buffer accessible as a <see cref="ShaderResourceView" /> and as a <see cref="UnorderedAccessView" />.
            /// </summary>
            /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
            /// <param name="count">The number of element in this buffer.</param>
            /// <param name="elementSize">Size of the struct.</param>
            /// <returns>A StructuredAppend buffer</returns>
            public static Buffer New(GraphicsDevice device, int count, int elementSize)
            {
                const BufferFlags BufferFlags = BufferFlags.StructuredAppendBuffer | BufferFlags.ShaderResource | BufferFlags.UnorderedAccess;

                return(Buffer.New(device, count * elementSize, elementSize, BufferFlags));
            }
Beispiel #21
0
 /// <summary>
 /// Creates a new Raw buffer with <see cref="GraphicsResourceUsage.Default"/> uasge by default.
 /// </summary>
 /// <typeparam name="T">Type of the Raw buffer to get the sizeof from</typeparam>
 /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
 /// <param name="value">The value to initialize the Raw buffer.</param>
 /// <param name="additionalBindings">The additional bindings (for example, to create a combined raw/index buffer, pass <see cref="BufferFlags.IndexBuffer" />)</param>
 /// <param name="usage">The usage of this resource.</param>
 /// <returns>A Raw buffer</returns>
 public static Buffer <T> New <T>(GraphicsDevice device, T[] value, BufferFlags additionalBindings = BufferFlags.None, GraphicsResourceUsage usage = GraphicsResourceUsage.Default) where T : struct
 {
     return(Buffer.New(device, value, BufferFlags.RawBuffer | additionalBindings, usage));
 }
Beispiel #22
0
            /// <summary>
            /// Creates a new StructuredCounter buffer accessible as a <see cref="ShaderResourceView" /> and optionaly as a <see cref="UnorderedAccessView" />.
            /// </summary>
            /// <typeparam name="T">Type of the element in the structured buffer</typeparam>
            /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
            /// <param name="count">The number of element in this buffer.</param>
            /// <returns>A Structured buffer</returns>
            public static Buffer <T> New <T>(GraphicsDevice device, int count) where T : struct
            {
                const BufferFlags BufferFlags = BufferFlags.StructuredCounterBuffer | BufferFlags.ShaderResource | BufferFlags.UnorderedAccess;

                return(Buffer.New <T>(device, count, BufferFlags));
            }
 /// <summary>
 /// Creates a temporary buffer.
 /// </summary>
 /// <param name="description">The description.</param>
 /// <param name="viewFormat">The shader view format on the buffer</param>
 /// <returns>Buffer.</returns>
 protected virtual Buffer CreateBuffer(BufferDescription description, PixelFormat viewFormat)
 {
     return(Buffer.New(GraphicsDevice, description, viewFormat));
 }
Beispiel #24
0
 /// <summary>
 /// Creates a new Vertex buffer with <see cref="GraphicsResourceUsage.Default"/> usage by default.
 /// </summary>
 /// <typeparam name="T">Type of the Vertex buffer to get the sizeof from</typeparam>
 /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
 /// <param name="vertexBufferCount">Number of vertex in this buffer with the sizeof(T).</param>
 /// <param name="usage">The usage.</param>
 /// <returns>A Vertex buffer</returns>
 public static Buffer <T> New <T>(GraphicsDevice device, int vertexBufferCount, GraphicsResourceUsage usage = GraphicsResourceUsage.Default) where T : struct
 {
     return(Buffer.New <T>(device, vertexBufferCount, BufferFlags.VertexBuffer, usage));
 }