/// <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)); }
/// <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 }; }
/// <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)); }
/// <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)); }
/// <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)); }
/// <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(); } }
/// <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)); }
/// <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)); }
/// <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)); }
/// <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)); }
/// <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)); }
/// <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)); }
/// <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)); }
/// <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)); }
/// <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)); }
/// <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)); }
/// <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)); }
/// <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)); }
/// <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)); }
/// <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)); }
/// <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)); }