protected override void OnRender(RenderContext 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); //Skip this frame to avoid performance hit due to texture creation InvalidateRenderer(); return; } #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.PerFrameNodesWithPostEffect.Count; ++i) { IEffectAttributes effect; var mesh = context.RenderHost.PerFrameNodesWithPostEffect[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); } }
protected override void OnRender(RenderContext context, DeviceContextProxy deviceContext) { #region Initialize textures var buffer = context.RenderHost.RenderBuffer; if (depthdesc.Width != buffer.TargetWidth || depthdesc.Height != buffer.TargetHeight) { depthdesc.Width = buffer.TargetWidth; depthdesc.Height = buffer.TargetHeight; blurCore.Resize(deviceContext, depthdesc.Width / downSamplingScale, depthdesc.Height / downSamplingScale); //Skip this frame to avoid performance hit due to texture creation InvalidateRenderer(); return; } #endregion var depthStencilBuffer = buffer.FullResDepthStencilPool.Get(depthdesc.Format); #region Render objects onto offscreen texture var renderTargetFull = buffer.FullResPPBuffer.NextRTV; deviceContext.ClearDepthStencilView(depthStencilBuffer, DepthStencilClearFlags.Stencil, 0, 0); BindTarget(depthStencilBuffer, renderTargetFull, deviceContext, buffer.TargetWidth, buffer.TargetHeight); var frustum = context.BoundingFrustum; context.IsCustomPass = true; bool hasMesh = false; for (int i = 0; i < context.RenderHost.PerFrameNodesWithPostEffect.Count; ++i) { var mesh = context.RenderHost.PerFrameNodesWithPostEffect[i]; if (context.EnableBoundingFrustum && !mesh.TestViewFrustum(ref frustum)) { continue; } if (mesh.TryGetPostEffect(EffectName, out IEffectAttributes 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 | StateType.DepthStencilState); mesh.Render(context, deviceContext); hasMesh = true; } } context.IsCustomPass = false; #endregion if (hasMesh) { #region Do Blur Pass BindTarget(null, blurCore.CurrentRTV, deviceContext, blurCore.Width, blurCore.Height, true); blurPassVertical.PixelShader.BindSampler(deviceContext, samplerSlot, sampler); blurPassVertical.PixelShader.BindTexture(deviceContext, textureSlot, buffer.FullResPPBuffer.NextSRV); blurPassVertical.BindShader(deviceContext); blurPassVertical.BindStates(deviceContext, StateType.BlendState | StateType.RasterState | StateType.DepthStencilState); 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, buffer.TargetWidth, buffer.TargetHeight); screenQuadPass.PixelShader.BindTexture(deviceContext, textureSlot, blurCore.CurrentSRV); screenQuadPass.BindShader(deviceContext); screenQuadPass.BindStates(deviceContext, StateType.BlendState | StateType.RasterState | StateType.DepthStencilState); deviceContext.Draw(4, 0); #endregion #region Draw outline onto original target BindTarget(null, buffer.FullResPPBuffer.CurrentRTV, deviceContext, buffer.TargetWidth, buffer.TargetHeight, false); screenOutlinePass.PixelShader.BindTexture(deviceContext, textureSlot, buffer.FullResPPBuffer.NextSRV); screenOutlinePass.BindShader(deviceContext); screenOutlinePass.BindStates(deviceContext, StateType.BlendState | StateType.RasterState | StateType.DepthStencilState); deviceContext.Draw(4, 0); screenOutlinePass.PixelShader.BindTexture(deviceContext, textureSlot, null); #endregion } buffer.FullResDepthStencilPool.Put(depthdesc.Format, depthStencilBuffer); }
protected override void OnRender(RenderContext context, DeviceContextProxy deviceContext) { #region Initialize textures var buffer = context.RenderHost.RenderBuffer; if (depthdesc.Width != buffer.TargetWidth || depthdesc.Height != buffer.TargetHeight) { depthdesc.Width = buffer.TargetWidth; depthdesc.Height = buffer.TargetHeight; blurCore.Resize(deviceContext, depthdesc.Width / downSamplingScale, depthdesc.Height / downSamplingScale); //Skip this frame to avoid performance hit due to texture creation InvalidateRenderer(); return; } #endregion var depthStencilBuffer = buffer.FullResDepthStencilPool.Get(depthdesc.Format); var renderTargetFull = buffer.FullResPPBuffer.NextRTV; var frustum = context.BoundingFrustum; if (drawMode == OutlineMode.Separated) { for (int i = 0; i < context.RenderHost.PerFrameNodesWithPostEffect.Count; ++i) { #region Render objects onto offscreen texture var mesh = context.RenderHost.PerFrameNodesWithPostEffect[i]; if (context.EnableBoundingFrustum && !mesh.TestViewFrustum(ref frustum)) { continue; } BindTarget(depthStencilBuffer, renderTargetFull, deviceContext, buffer.TargetWidth, buffer.TargetHeight); deviceContext.ClearDepthStencilView(depthStencilBuffer, DepthStencilClearFlags.Stencil, 0, 0); modelCB.Upload(deviceContext, ref modelStruct); if (mesh.TryGetPostEffect(EffectName, out IEffectAttributes effect)) { var color = Color; if (effect.TryGetAttribute(EffectAttributeNames.ColorAttributeName, out object attribute) && attribute is string colorStr) { color = colorStr.ToColor4(); } if (modelStruct.Color != color) { modelStruct.Color = color; modelCB.Upload(deviceContext, ref modelStruct); } context.CustomPassName = DefaultPassNames.EffectOutlineP1; var pass = mesh.EffectTechnique[DefaultPassNames.EffectOutlineP1]; if (pass.IsNULL) { continue; } pass.BindShader(deviceContext); pass.BindStates(deviceContext, StateType.BlendState | StateType.DepthStencilState); mesh.RenderCustom(context, deviceContext); DrawOutline(context, deviceContext, depthStencilBuffer, renderTargetFull); } #endregion } } else { BindTarget(depthStencilBuffer, renderTargetFull, deviceContext, buffer.TargetWidth, buffer.TargetHeight); #region Render objects onto offscreen texture deviceContext.ClearDepthStencilView(depthStencilBuffer, DepthStencilClearFlags.Stencil, 0, 0); bool hasMesh = false; for (int i = 0; i < context.RenderHost.PerFrameNodesWithPostEffect.Count; ++i) { var mesh = context.RenderHost.PerFrameNodesWithPostEffect[i]; if (context.EnableBoundingFrustum && !mesh.TestViewFrustum(ref frustum)) { continue; } if (mesh.TryGetPostEffect(EffectName, out IEffectAttributes effect)) { var color = Color; if (effect.TryGetAttribute(EffectAttributeNames.ColorAttributeName, out object attribute) && attribute is string colorStr) { color = colorStr.ToColor4(); } if (modelStruct.Color != color) { modelStruct.Color = color; modelCB.Upload(deviceContext, ref modelStruct); } context.CustomPassName = DefaultPassNames.EffectOutlineP1; var pass = mesh.EffectTechnique[DefaultPassNames.EffectOutlineP1]; if (pass.IsNULL) { continue; } pass.BindShader(deviceContext); pass.BindStates(deviceContext, StateType.BlendState | StateType.DepthStencilState); mesh.RenderCustom(context, deviceContext); hasMesh = true; } } #endregion if (hasMesh) { DrawOutline(context, deviceContext, depthStencilBuffer, renderTargetFull); } } buffer.FullResDepthStencilPool.Put(depthdesc.Format, depthStencilBuffer); }