/// <summary> /// Called when [render]. /// </summary> /// <param name="context">The context.</param> /// <param name="deviceContext">The device context.</param> protected override void OnRender(IRenderContext context, DeviceContextProxy deviceContext) { perFrameCB.UploadDataToBuffer(deviceContext, ref FrameVariables); // Clear binding updatePass.GetShader(ShaderStage.Compute).BindUAV(deviceContext, currentStateSlot, null); updatePass.GetShader(ShaderStage.Compute).BindUAV(deviceContext, newStateSlot, null); OnTextureChanged(); OnBlendStateChanged(); // Render existing particles renderPass.BindShader(deviceContext); renderPass.BindStates(deviceContext, StateType.RasterState | StateType.DepthStencilState); renderPass.GetShader(ShaderStage.Vertex).BindTexture(deviceContext, renderStateSlot, BufferProxies[0].SRV); renderPass.GetShader(ShaderStage.Pixel).BindTexture(deviceContext, textureSlot, textureView); renderPass.GetShader(ShaderStage.Pixel).BindSampler(deviceContext, samplerSlot, textureSampler); deviceContext.DeviceContext.InputAssembler.InputLayout = VertexLayout; deviceContext.DeviceContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.PointList; int firstSlot = 0; InstanceBuffer?.AttachBuffer(deviceContext, ref firstSlot); deviceContext.DeviceContext.OutputMerger.SetBlendState(blendState, null, 0xFFFFFFFF); deviceContext.DeviceContext.DrawInstancedIndirect(particleCountGSIABuffer.Buffer, 0); InvalidateRenderer();//Since particle is running all the time. Invalidate once finished rendering }
/// <summary> /// Runs the specified device context. /// </summary> /// <param name="deviceContext">The device context.</param> /// <param name="iteration">The iteration.</param> /// <param name="initVerticalIter">The initialize vertical iter.</param> /// <param name="initHorizontalIter">The initialize horizontal iter.</param> public virtual void Run(DeviceContextProxy deviceContext, int iteration, int initVerticalIter = 0, int initHorizontalIter = 0) { deviceContext.DeviceContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleStrip; deviceContext.DeviceContext.PixelShader.SetSampler(samplerSlot, sampler); if (!screenBlurPassVertical.IsNULL) { screenBlurPassVertical.BindShader(deviceContext); screenBlurPassVertical.BindStates(deviceContext, StateType.BlendState | StateType.RasterState | StateType.DepthStencilState); for (int i = initVerticalIter; i < iteration; ++i) { SwapTargets(); BindTarget(null, renderTargetBlur[0], deviceContext, texture2DDesc.Width, texture2DDesc.Height); screenBlurPassVertical.GetShader(ShaderStage.Pixel).BindTexture(deviceContext, textureSlot, renderTargetBlur[1].TextureView); deviceContext.DeviceContext.Draw(4, 0); } } if (!screenBlurPassHorizontal.IsNULL) { screenBlurPassHorizontal.BindShader(deviceContext); screenBlurPassHorizontal.BindStates(deviceContext, StateType.BlendState | StateType.RasterState | StateType.DepthStencilState); for (int i = initHorizontalIter; i < iteration; ++i) { SwapTargets(); BindTarget(null, renderTargetBlur[0], deviceContext, texture2DDesc.Width, texture2DDesc.Height); screenBlurPassHorizontal.GetShader(ShaderStage.Pixel).BindTexture(deviceContext, textureSlot, renderTargetBlur[1].TextureView); deviceContext.DeviceContext.Draw(4, 0); } } deviceContext.DeviceContext.PixelShader.SetShaderResource(textureSlot, null); }
protected override void OnRender(IRenderContext renderContext, DeviceContextProxy deviceContext) { base.OnRender(renderContext, deviceContext); // Draw backface into stencil buffer DepthStencilView dsView; var renderTargets = deviceContext.DeviceContext.OutputMerger.GetRenderTargets(1, out dsView); if (dsView == null) { return; } deviceContext.DeviceContext.ClearDepthStencilView(dsView, DepthStencilClearFlags.Stencil, 0, 0); deviceContext.DeviceContext.OutputMerger.SetRenderTargets(dsView, new RenderTargetView[0]);//Remove render target deviceContext.SetRasterState(backfaceRasterState); drawBackfacePass.BindShader(deviceContext); drawBackfacePass.BindStates(deviceContext, StateType.BlendState); deviceContext.SetDepthStencilState(drawBackfacePass.DepthStencilState, 1); //Draw backface onto stencil buffer, set value to 1 OnDraw(deviceContext, InstanceBuffer); //Draw full screen quad to fill cross section deviceContext.DeviceContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleStrip; deviceContext.SetRasterState(RasterState); drawScreenQuadPass.BindShader(deviceContext); drawScreenQuadPass.BindStates(deviceContext, StateType.BlendState); deviceContext.DeviceContext.OutputMerger.SetRenderTargets(dsView, renderTargets); //Rebind render target deviceContext.SetDepthStencilState(drawScreenQuadPass.DepthStencilState, 1); //Only pass stencil buffer test if value is 1 deviceContext.DeviceContext.Draw(4, 0); //Decrement ref count. See OutputMerger.GetRenderTargets remarks dsView.Dispose(); foreach (var t in renderTargets) { t.Dispose(); } }
/// <summary> /// /// </summary> /// <param name="context"></param> /// <param name="deviceContext"></param> protected override void OnUpdate(IRenderContext context, DeviceContextProxy deviceContext) { UpdateTime(context, ref totalElapsed); //Set correct instance count from instance buffer drawArgument.InstanceCount = InstanceBuffer == null || !InstanceBuffer.HasElements ? 1 : (uint)InstanceBuffer.Buffer.ElementCount; //Upload the draw argument particleCountGSIABuffer.UploadDataToBuffer(deviceContext, ref drawArgument); updatePass.BindShader(deviceContext); updatePass.GetShader(ShaderStage.Compute).BindUAV(deviceContext, currentStateSlot, BufferProxies[0].UAV); updatePass.GetShader(ShaderStage.Compute).BindUAV(deviceContext, newStateSlot, BufferProxies[1].UAV); if (isRestart) { FrameVariables.NumParticles = 0; perFrameCB.UploadDataToBuffer(deviceContext, ref FrameVariables); // Call ComputeShader to add initial particles deviceContext.DeviceContext.Dispatch(1, 1, 1); isRestart = false; } else { #region Get consume buffer count // Get consume buffer count. //Due to some intel integrated graphic card having issue copy structure count directly into constant buffer. //Has to use staging buffer to read and pass into constant buffer FrameVariables.NumParticles = (uint)ReadCount("", deviceContext, BufferProxies[0]); perFrameCB.UploadDataToBuffer(deviceContext, ref FrameVariables); #endregion deviceContext.DeviceContext.Dispatch(Math.Max(1, (int)Math.Ceiling((double)FrameVariables.NumParticles / 512)), 1, 1); // Get append buffer count BufferProxies[1].CopyCount(deviceContext, particleCountGSIABuffer.Buffer, 0); } #if OUTPUTDEBUGGING ReadCount("UAV 0", deviceContext, BufferProxies[0].UAV); #endif if (totalElapsed > InsertElapseThrottle) { insertCB.UploadDataToBuffer(deviceContext, ref InsertVariables); // Add more particles insertPass.BindShader(deviceContext); insertPass.GetShader(ShaderStage.Compute).BindUAV(deviceContext, newStateSlot, BufferProxies[1].UAV); deviceContext.DeviceContext.Dispatch(1, 1, 1); totalElapsed = 0; #if OUTPUTDEBUGGING ReadCount("UAV 1", deviceContext, BufferProxies[1].UAV); #endif } // Swap UAV buffers for next frame var bproxy = BufferProxies[0]; BufferProxies[0] = BufferProxies[1]; BufferProxies[1] = bproxy; }
protected override void OnRender(IRenderContext context, DeviceContextProxy deviceContext) { #region Initialize textures if (offScreenRenderTargets.Count == 0 || width != (int)(context.ActualWidth) || height != (int)(context.ActualHeight)) { width = (int)(context.ActualWidth); height = (int)(context.ActualHeight); for (int i = 0; i < offScreenRenderTargets.Count; ++i) { var target = offScreenRenderTargets[i]; RemoveAndDispose(ref target); } offScreenRenderTargets.Clear(); int w = width; int h = height; int count = 0; while (w > 1 && h > 1 && count < Math.Max(0, MaximumDownSamplingStep) + 1) { var target = Collect(new PostEffectBlurCore(global::SharpDX.DXGI.Format.B8G8R8A8_UNorm, blurPassVertical, blurPassHorizontal, textureSlot, samplerSlot, DefaultSamplers.LinearSamplerClampAni4, EffectTechnique.EffectsManager)); target.Resize(Device, w, h); offScreenRenderTargets.Add(target); w >>= 2; h >>= 2; ++count; } } #endregion #region Render objects onto offscreen texture var renderTargets = deviceContext.DeviceContext.OutputMerger.GetRenderTargets(1); using (var resource1 = renderTargets[0].Resource) { using (var resource2 = offScreenRenderTargets[0].CurrentRTV.Resource) { deviceContext.DeviceContext.ResolveSubresource(resource1, 0, resource2, 0, global::SharpDX.DXGI.Format.B8G8R8A8_UNorm); } } //Decrement ref count. See OutputMerger.GetRenderTargets remarks foreach (var t in renderTargets) { t.Dispose(); } #endregion deviceContext.DeviceContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleStrip; #region Do Bloom Pass deviceContext.DeviceContext.PixelShader.SetSampler(samplerSlot, sampler); //Extract bloom samples BindTarget(null, offScreenRenderTargets[0].NextRTV, deviceContext, offScreenRenderTargets[0].Width, offScreenRenderTargets[0].Height, false); screenQuadPass.GetShader(ShaderStage.Pixel).BindTexture(deviceContext, textureSlot, offScreenRenderTargets[0].CurrentSRV); screenQuadPass.BindShader(deviceContext); screenQuadPass.BindStates(deviceContext, StateType.BlendState | StateType.RasterState | StateType.DepthStencilState); deviceContext.DeviceContext.Draw(4, 0); offScreenRenderTargets[0].SwapTargets(); // Down sampling screenQuadCopy.BindShader(deviceContext); screenQuadCopy.BindStates(deviceContext, StateType.BlendState | StateType.RasterState | StateType.DepthStencilState); for (int i = 1; i < offScreenRenderTargets.Count; ++i) { BindTarget(null, offScreenRenderTargets[i].CurrentRTV, deviceContext, offScreenRenderTargets[i].Width, offScreenRenderTargets[i].Height, false); screenQuadCopy.GetShader(ShaderStage.Pixel).BindTexture(deviceContext, textureSlot, offScreenRenderTargets[i - 1].CurrentSRV); deviceContext.DeviceContext.Draw(4, 0); } for (int i = offScreenRenderTargets.Count - 1; i >= 1; --i) { //Run blur pass offScreenRenderTargets[i].Run(deviceContext, NumberOfBlurPass); //Up sampling screenOutlinePass.BindShader(deviceContext); screenOutlinePass.BindStates(deviceContext, StateType.BlendState | StateType.RasterState | StateType.DepthStencilState); BindTarget(null, offScreenRenderTargets[i - 1].CurrentRTV, deviceContext, offScreenRenderTargets[i - 1].Width, offScreenRenderTargets[i - 1].Height, false); screenOutlinePass.GetShader(ShaderStage.Pixel).BindTexture(deviceContext, textureSlot, offScreenRenderTargets[i].CurrentSRV); deviceContext.DeviceContext.Draw(4, 0); } offScreenRenderTargets[0].Run(deviceContext, NumberOfBlurPass); #endregion #region Draw outline onto original target context.RenderHost.SetDefaultRenderTargets(false); screenOutlinePass.GetShader(ShaderStage.Pixel).BindTexture(deviceContext, textureSlot, offScreenRenderTargets[0].CurrentSRV); screenOutlinePass.BindShader(deviceContext); screenOutlinePass.BindStates(deviceContext, StateType.BlendState | StateType.RasterState | StateType.DepthStencilState); deviceContext.DeviceContext.Draw(4, 0); screenOutlinePass.GetShader(ShaderStage.Pixel).BindTexture(deviceContext, textureSlot, null); #endregion }
protected override void OnRender(IRenderContext context, DeviceContextProxy deviceContext) { #region Initialize textures if (renderTargetFull == null || renderTargetDesc.Width != (int)(context.ActualWidth) || renderTargetDesc.Height != (int)(context.ActualHeight)) { depthdesc.Width = renderTargetDesc.Width = (int)(context.ActualWidth); depthdesc.Height = renderTargetDesc.Height = (int)(context.ActualHeight); RemoveAndDispose(ref renderTargetFull); RemoveAndDispose(ref depthStencilBuffer); renderTargetFull = Collect(new ShaderResourceViewProxy(deviceContext.DeviceContext.Device, renderTargetDesc)); renderTargetFull.CreateView(renderTargetViewDesc); renderTargetFull.CreateView(targetResourceViewDesc); depthStencilBuffer = Collect(new ShaderResourceViewProxy(deviceContext.DeviceContext.Device, depthdesc)); depthStencilBuffer.CreateView(depthStencilViewDesc); blurCore.Resize(deviceContext.DeviceContext.Device, renderTargetDesc.Width / downSamplingScale, renderTargetDesc.Height / downSamplingScale); } #endregion #region Render objects onto offscreen texture deviceContext.DeviceContext.ClearDepthStencilView(depthStencilBuffer, DepthStencilClearFlags.Stencil, 0, 0); BindTarget(depthStencilBuffer, renderTargetFull, deviceContext, renderTargetDesc.Width, renderTargetDesc.Height); context.IsCustomPass = true; bool hasMesh = false; for (int i = 0; i < context.RenderHost.PerFrameGeneralCoresWithPostEffect.Count; ++i) { IEffectAttributes effect; var mesh = context.RenderHost.PerFrameGeneralCoresWithPostEffect[i]; if (mesh.TryGetPostEffect(EffectName, out effect)) { object attribute; var color = Color; if (effect.TryGetAttribute(EffectAttributeNames.ColorAttributeName, out attribute) && attribute is string colorStr) { color = colorStr.ToColor4(); } if (modelStruct.Color != color) { modelStruct.Color = color; OnUploadPerModelConstantBuffers(deviceContext); } context.CustomPassName = DefaultPassNames.EffectOutlineP1; var pass = mesh.EffectTechnique[DefaultPassNames.EffectOutlineP1]; if (pass.IsNULL) { continue; } pass.BindShader(deviceContext); pass.BindStates(deviceContext, StateType.BlendState); deviceContext.SetDepthStencilState(pass.DepthStencilState, 1); mesh.Render(context, deviceContext); hasMesh = true; } } context.IsCustomPass = false; #endregion if (hasMesh) { deviceContext.DeviceContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleStrip; deviceContext.DeviceContext.PixelShader.SetSampler(samplerSlot, sampler); #region Do Blur Pass BindTarget(null, blurCore.CurrentRTV, deviceContext, blurCore.Width, blurCore.Height, true); blurPassVertical.GetShader(ShaderStage.Pixel).BindTexture(deviceContext, textureSlot, renderTargetFull); blurPassVertical.BindShader(deviceContext); blurPassVertical.BindStates(deviceContext, StateType.BlendState | StateType.RasterState | StateType.DepthStencilState); deviceContext.DeviceContext.Draw(4, 0); blurCore.Run(deviceContext, NumberOfBlurPass, 1, 0);//Already blur once on vertical, pass 1 as initial index. #endregion #region Draw back with stencil test BindTarget(depthStencilBuffer, renderTargetFull, deviceContext, renderTargetDesc.Width, renderTargetDesc.Height); screenQuadPass.GetShader(ShaderStage.Pixel).BindTexture(deviceContext, textureSlot, blurCore.CurrentSRV); screenQuadPass.BindShader(deviceContext); deviceContext.SetDepthStencilState(screenQuadPass.DepthStencilState, 0); screenQuadPass.BindStates(deviceContext, StateType.BlendState | StateType.RasterState); deviceContext.DeviceContext.Draw(4, 0); #endregion #region Draw outline onto original target context.RenderHost.SetDefaultRenderTargets(false); screenOutlinePass.GetShader(ShaderStage.Pixel).BindTexture(deviceContext, textureSlot, renderTargetFull); screenOutlinePass.BindShader(deviceContext); screenOutlinePass.BindStates(deviceContext, StateType.BlendState | StateType.RasterState | StateType.DepthStencilState); deviceContext.DeviceContext.Draw(4, 0); screenOutlinePass.GetShader(ShaderStage.Pixel).BindTexture(deviceContext, textureSlot, null); #endregion } else { context.RenderHost.SetDefaultRenderTargets(false); } }