/// <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> /// Called when [attach]. /// </summary> /// <param name="technique">The technique.</param> /// <returns></returns> protected override bool OnAttach(IRenderTechnique technique) { if (base.OnAttach(technique)) { VertexLayout = technique.Layout; updatePass = technique[DefaultParticlePassNames.Update]; insertPass = technique[DefaultParticlePassNames.Insert]; renderPass = technique[DefaultParticlePassNames.Default]; #region Get binding slots currentStateSlot = updatePass.GetShader(ShaderStage.Compute).UnorderedAccessViewMapping.TryGetBindSlot(CurrentSimStateUAVBufferName); newStateSlot = updatePass.GetShader(ShaderStage.Compute).UnorderedAccessViewMapping.TryGetBindSlot(NewSimStateUAVBufferName); renderStateSlot = renderPass.GetShader(ShaderStage.Vertex).ShaderResourceViewMapping.TryGetBindSlot(SimStateBufferName); textureSlot = renderPass.GetShader(ShaderStage.Pixel).ShaderResourceViewMapping.TryGetBindSlot(ShaderTextureBufferName); samplerSlot = renderPass.GetShader(ShaderStage.Pixel).SamplerMapping.TryGetBindSlot(ShaderTextureSamplerName); #endregion perFrameCB = technique.ConstantBufferPool.Register(DefaultBufferNames.ParticleFrameCB, ParticlePerFrame.SizeInBytes); insertCB = technique.ConstantBufferPool.Register(DefaultBufferNames.ParticleCreateParameters, ParticleInsertParameters.SizeInBytes); isBlendChanged = true; if (isInitialParticleChanged) { OnInitialParticleChanged(ParticleCount); } textureSampler = Collect(technique.EffectsManager.StateManager.Register(SamplerDescription)); return(true); } else { return(false); } }
/// <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; }
/// <summary> /// <see cref="IEffectMaterialVariables.BindMaterialTextures(DeviceContext, IShaderPass)"/> /// </summary> /// <param name="context"></param> /// <param name="shaderPass"></param> /// <returns></returns> public bool BindMaterialTextures(DeviceContext context, IShaderPass shaderPass) { if (material == null) { return(false); } UpdateMappings(shaderPass); if (HasTextures) { for (int i = 0; i < shaderPass.Shaders.Count; ++i) { var shader = shaderPass.Shaders[i]; if (shader.IsNULL || !EnumHelper.HasFlag(Constants.CanBindTextureStages, shader.ShaderType)) { continue; } OnBindMaterialTextures(context, shader); } } if (RenderShadowMap) { shaderPass.GetShader(ShaderStage.Pixel).BindSampler(context, SamplerBindingMap[ShaderStage.Pixel.ToIndex()][NUMSAMPLERS - 1], SamplerResources[NUMSAMPLERS - 1]); } return(true); }
/// <summary> /// Called when [attach]. /// </summary> /// <param name="technique">The technique.</param> /// <returns></returns> protected override bool OnAttach(IRenderTechnique technique) { if (base.OnAttach(technique)) { DefaultShaderPass = technique.EffectsManager[DefaultRenderTechniqueNames.ScreenDuplication][DefaultPassNames.Default]; CursorShaderPass = technique.EffectsManager[DefaultRenderTechniqueNames.ScreenDuplication][DefaultPassNames.ScreenQuad]; textureBindSlot = DefaultShaderPass.GetShader(ShaderStage.Pixel).ShaderResourceViewMapping.TryGetBindSlot(DefaultBufferNames.DiffuseMapTB); samplerBindSlot = DefaultShaderPass.GetShader(ShaderStage.Pixel).SamplerMapping.TryGetBindSlot(DefaultSamplerStateNames.DiffuseMapSampler); textureSampler = Collect(technique.EffectsManager.StateManager.Register(DefaultSamplers.ScreenDupSampler)); return(Initialize(technique.EffectsManager)); } else { return(false); } }
/// <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 bool OnAttach(IRenderTechnique technique) { if (base.OnAttach(technique)) { screenQuadPass = technique.GetPass(DefaultPassNames.ScreenQuad); screenQuadCopy = technique.GetPass(DefaultPassNames.ScreenQuadCopy); blurPassVertical = technique.GetPass(DefaultPassNames.EffectBlurVertical); blurPassHorizontal = technique.GetPass(DefaultPassNames.EffectBlurHorizontal); screenOutlinePass = technique.GetPass(DefaultPassNames.MeshOutline); textureSlot = screenOutlinePass.GetShader(ShaderStage.Pixel).ShaderResourceViewMapping.TryGetBindSlot(DefaultBufferNames.DiffuseMapTB); samplerSlot = screenOutlinePass.GetShader(ShaderStage.Pixel).SamplerMapping.TryGetBindSlot(DefaultSamplerStateNames.DiffuseMapSampler); sampler = Collect(technique.EffectsManager.StateManager.Register(DefaultSamplers.LinearSamplerClampAni4)); return(true); } else { return(false); } }
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 }
/// <summary> /// Called when [default pass changed]. /// </summary> /// <param name="pass">The pass.</param> protected override void OnDefaultPassChanged(IShaderPass pass) { cubeTextureSlot = pass.GetShader(ShaderStage.Pixel).ShaderResourceViewMapping.TryGetBindSlot(ShaderCubeTextureName); textureSamplerSlot = pass.GetShader(ShaderStage.Pixel).SamplerMapping.TryGetBindSlot(ShaderCubeTextureSamplerName); }
protected override void OnDefaultPassChanged(IShaderPass pass) { base.OnDefaultPassChanged(pass); shadowMapSlot = pass.GetShader(ShaderStage.Pixel).ShaderResourceViewMapping.TryGetBindSlot(ShaderShadowMapTextureName); }
protected override void OnDefaultPassChanged(IShaderPass pass) { base.OnDefaultPassChanged(pass); ColorTextureSlot = pass.GetShader(ShaderStage.Pixel).ShaderResourceViewMapping.TryGetBindSlot(CustomShaderNames.TexData); ColorTextureSamplerSlot = pass.GetShader(ShaderStage.Pixel).SamplerMapping.TryGetBindSlot(CustomShaderNames.TexDataSampler); }
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); } }