void CreateDeviceDependentResources()
        {
            #region Compile Vertex/Pixel shaders
            // Compile and create the vertex shader
            using (var vsBytecode = ShaderBytecode.CompileFromFile("ParticleVS.hlsl",
                                                                   "VSMain",
                                                                   "vs_5_0",
                                                                   ShaderFlags.None,
                                                                   EffectFlags.None,
                                                                   null,
                                                                   new HLSLFileIncludeHandler(Environment.CurrentDirectory)))
                using (var psBytecode = ShaderBytecode.CompileFromFile("ParticlePS.hlsl",
                                                                       "PSMain",
                                                                       "ps_5_0",
                                                                       ShaderFlags.None,
                                                                       EffectFlags.None,
                                                                       null,
                                                                       new HLSLFileIncludeHandler(Environment.CurrentDirectory)))
                {
                    vertexShader = new VertexShader(device, vsBytecode);
                    pixelShader  = new PixelShader(device, psBytecode);
                }
            #endregion

            #region Blend 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
            };
            blendState = new BlendState(device, blendDesc);
            // Additive blend state that lightens when overlapped
            // (needs a dark background)
            blendDesc.RenderTarget[0].DestinationBlend = BlendOption.One;
            blendStateLight = new BlendState(device, blendDesc);
            #endregion

            // depth stencil state to disable Z-buffer write
            disableDepthWrite = new DepthStencilState(device,
                                                      new DepthStencilStateDescription
            {
                DepthComparison  = Comparison.Less,
                DepthWriteMask   = SharpDX.Direct3D11.DepthWriteMask.Zero,
                IsDepthEnabled   = true,
                IsStencilEnabled = false
            });

            // Create the per compute shader constant buffer
            perComputeBuffer = new Buffer(device,
                                          Utilities.SizeOf <ParticleConstants>(),
                                          ResourceUsage.Default,
                                          BindFlags.ConstantBuffer,
                                          CpuAccessFlags.None,
                                          ResourceOptionFlags.None,
                                          0);

            // Create the particle frame buffer
            perFrame = new Buffer(device,
                                  Utilities.SizeOf <ParticleFrame>(),
                                  ResourceUsage.Default,
                                  BindFlags.ConstantBuffer,
                                  CpuAccessFlags.None,
                                  ResourceOptionFlags.None,
                                  0);
            perObject = new Buffer(device,
                                   Utilities.SizeOf <PerObject>(),
                                   ResourceUsage.Default,
                                   BindFlags.ConstantBuffer,
                                   CpuAccessFlags.None,
                                   ResourceOptionFlags.None,
                                   0);

            particleTextureSRV = StaticMetods.LoadTextureFromFile(context, "Particle.png");

            // Create a linear sampler
            linearSampler = new SamplerState(device, new SamplerStateDescription
            {
                AddressU   = TextureAddressMode.Wrap,
                AddressV   = TextureAddressMode.Wrap,
                AddressW   = TextureAddressMode.Wrap,
                Filter     = Filter.MinMagMipLinear, // Bilinear
                MaximumLod = float.MaxValue,
                MinimumLod = 0,
            });
        }
예제 #2
0
        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;
        }