public ParticleDeviceBufferesUpdater(ParticleShaderSpecification shader) : base(shader) { particles = new Particle[PARTICLES_COUNT]; var random = new System.Random(); for (int i = 0; i < PARTICLES_COUNT; i++) { particles[i].Position = random.NextVector3(new Vector3(-30f, -30f, -30f), new Vector3(30f, 30f, 30f)); } }
public Logic(Game game) : base(game) { int numGroups = (PARTICLES_COUNT % 768 != 0) ? ((PARTICLES_COUNT / 768) + 1) : (PARTICLES_COUNT / 768); double secondRoot = System.Math.Pow((double)numGroups, (double)(1.0 / 2.0)); secondRoot = System.Math.Ceiling(secondRoot); _groupSizeX = _groupSizeY = (int)secondRoot; game.Color = Color.Black; System.Random random = new System.Random(); GPUParticleData[] initialParticles = new GPUParticleData[PARTICLES_COUNT]; Vector3 min = new Vector3(-30f, -30f, -30f); Vector3 max = new Vector3(30f, 30f, 30f); for (int i = 0; i < PARTICLES_COUNT; i++) { initialParticles[i].Position = random.NextVector3(min, max); float angle = -(float)System.Math.Atan2(initialParticles[i].Position.X, initialParticles[i].Position.Z); initialParticles[i].Velocity = new Vector3((float)System.Math.Cos(angle), 0f, (float)System.Math.Sin(angle)) * 5f; } _particlesBuffer = new Buffer(game.DeviceContext.Device, Utilities.SizeOf <GPUParticleData>() * PARTICLES_COUNT, ResourceUsage.Default, BindFlags.ShaderResource | BindFlags.UnorderedAccess, CpuAccessFlags.None, ResourceOptionFlags.BufferStructured, Utilities.SizeOf <GPUParticleData>()); game.DeviceContext.UpdateSubresource(initialParticles, _particlesBuffer); #region Blend and Depth States var blendDesc = new BlendStateDescription() { IndependentBlendEnable = false, AlphaToCoverageEnable = false, }; // Additive blend state that darkens when overlapped blendDesc.RenderTarget[0] = new RenderTargetBlendDescription { IsBlendEnabled = true, BlendOperation = BlendOperation.Add, AlphaBlendOperation = BlendOperation.Add, SourceBlend = BlendOption.SourceAlpha, DestinationBlend = BlendOption.InverseSourceAlpha, SourceAlphaBlend = BlendOption.One, DestinationAlphaBlend = BlendOption.Zero, RenderTargetWriteMask = ColorWriteMaskFlags.All }; blendDesc.RenderTarget[0].DestinationBlend = BlendOption.One; BlendStateDescription blendDescription = BlendStateDescription.Default(); blendDescription.RenderTarget[0].IsBlendEnabled = true; blendDescription.RenderTarget[0].SourceBlend = BlendOption.One; blendDescription.RenderTarget[0].DestinationBlend = BlendOption.One; blendDescription.RenderTarget[0].BlendOperation = BlendOperation.Add; var depthDesc = new DepthStencilStateDescription { DepthComparison = Comparison.Less, DepthWriteMask = DepthWriteMask.Zero, IsDepthEnabled = true, IsStencilEnabled = false }; _DState = new DepthStencilState(game.DeviceContext.Device, depthDesc); _blendState = new BlendState(game.DeviceContext.Device, blendDescription); #endregion worldMatrix = Matrix.Identity; viewMatrix = Matrix.LookAtLH(new Vector3(0, 0, 100), Vector3.Zero, Vector3.Up); projectionMatrix = Matrix.PerspectiveFovLH(MathUtil.PiOverFour, game.ViewRatio, 1f, 1000); m = new Matrixes(); m.World = worldMatrix; m.View = viewMatrix; m.Proj = projectionMatrix; m.Size = 1f; m.Trans(); _perFrame = new Buffer(game.DeviceContext.Device, Utilities.SizeOf <Matrixes>(), ResourceUsage.Default, BindFlags.ConstantBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0); game.DeviceContext.UpdateSubresource(ref m, _perFrame); _c = new Constants(); _c.GroupDim = _groupSizeX; _c.MaxParticles = PARTICLES_COUNT; _csConstants = new Buffer(game.DeviceContext.Device, Utilities.SizeOf <Constants>(), ResourceUsage.Default, BindFlags.ConstantBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0); ShaderFlags shaderFlags = ShaderFlags.None; #if DEBUG shaderFlags = ShaderFlags.Debug; #endif using (var shaderByteCode = ShaderBytecode.CompileFromFile(@"Shaders\VS.hlsl", "VS", "vs_5_0", shaderFlags)) _vs = new VertexShader(game.DeviceContext.Device, shaderByteCode); using (var shaderByteCode = ShaderBytecode.CompileFromFile(@"Shaders\GS.hlsl", "GS", "gs_5_0", shaderFlags)) _gs = new GeometryShader(game.DeviceContext.Device, shaderByteCode); using (var shaderByteCode = ShaderBytecode.CompileFromFile(@"Shaders\PS.hlsl", "PS", "ps_5_0", shaderFlags)) _ps = new PixelShader(game.DeviceContext.Device, shaderByteCode); using (var shaderByteCode = ShaderBytecode.CompileFromFile(@"Shaders\CS.hlsl", "CS", "cs_5_0", shaderFlags)) _cs = new ComputeShader(game.DeviceContext.Device, shaderByteCode); _SRV = new ShaderResourceView(game.DeviceContext.Device, _particlesBuffer); UnorderedAccessViewDescription uavDesc = new UnorderedAccessViewDescription { Dimension = UnorderedAccessViewDimension.Buffer, Buffer = new UnorderedAccessViewDescription.BufferResource { FirstElement = 0 } }; uavDesc.Format = Format.Unknown; uavDesc.Buffer.Flags = UnorderedAccessViewBufferFlags.None; uavDesc.Buffer.ElementCount = _particlesBuffer.Description.SizeInBytes / _particlesBuffer.Description.StructureByteStride; _UAV = new UnorderedAccessView(game.DeviceContext.Device, _particlesBuffer, uavDesc); SamplerStateDescription samplerDecription = SamplerStateDescription.Default(); { samplerDecription.AddressU = TextureAddressMode.Clamp; samplerDecription.AddressV = TextureAddressMode.Clamp; samplerDecription.Filter = Filter.MinMagMipLinear; }; _particleSampler = new SamplerState(game.DeviceContext.Device, samplerDecription); _texture = StaticMetods.LoadTextureFromFile(game.DeviceContext, "smoke5.png"); game.DeviceContext.OutputMerger.DepthStencilState = _DState; }