protected override void OnRender(RenderContext 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(); } }
public void BindStates(DeviceContextProxy context, StateType type) { if (type == StateType.None || IsNULL) { return; } if (EnumHelper.HasFlag(type, StateType.BlendState)) { context.SetBlendState(BlendState, BlendFactor, SampleMask); } if (EnumHelper.HasFlag(type, StateType.DepthStencilState)) { context.SetDepthStencilState(DepthStencilState, StencilRef); } if (EnumHelper.HasFlag(type, StateType.RasterState)) { context.SetRasterState(RasterState); } }
/// <summary> /// Binds the states. /// </summary> /// <param name="context">The context.</param> /// <param name="type">The type.</param> public void BindStates(DeviceContextProxy context, StateType type) { if (type == StateType.None) { return; } if (EnumHelper.HasFlag(type, StateType.BlendState)) { context.SetBlendState(BlendState); } if (EnumHelper.HasFlag(type, StateType.DepthStencilState)) { context.SetDepthStencilState(DepthStencilState); } if (EnumHelper.HasFlag(type, StateType.RasterState)) { context.SetRasterState(RasterState); } }
/// <summary> /// Called when [render]. /// </summary> /// <param name="context">The context.</param> /// <param name="deviceContext">The device context.</param> protected override void OnRender(RenderContext context, DeviceContextProxy deviceContext) { var buffer = context.RenderHost.RenderBuffer; bool hasMSAA = buffer.ColorBufferSampleDesc.Count > 1; var dPass = DoublePass; var depthStencilBuffer = hasMSAA ? buffer.FullResDepthStencilPool.Get(Format.D32_Float_S8X24_UInt) : buffer.DepthStencilBuffer; BindTarget(depthStencilBuffer, buffer.FullResPPBuffer.CurrentRTV, deviceContext, buffer.TargetWidth, buffer.TargetHeight, false); if (hasMSAA) { //Needs to do a depth pass for existing meshes.Because the msaa depth buffer is not resolvable. deviceContext.ClearDepthStencilView(depthStencilBuffer, DepthStencilClearFlags.Depth, 1, 0); depthPrepassCore.Render(context, deviceContext); } var frustum = context.BoundingFrustum; context.IsCustomPass = true; if (dPass) { deviceContext.ClearDepthStencilView(depthStencilBuffer, DepthStencilClearFlags.Stencil, 1, 0); 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)) { currentCores.Add(new KeyValuePair <SceneNode, IEffectAttributes>(mesh, effect)); context.CustomPassName = DefaultPassNames.EffectMeshXRayP1; var pass = mesh.EffectTechnique[DefaultPassNames.EffectMeshXRayP1]; if (pass.IsNULL) { continue; } pass.BindShader(deviceContext); pass.BindStates(deviceContext, StateType.BlendState | StateType.DepthStencilState); mesh.Render(context, deviceContext); } } for (int i = 0; i < currentCores.Count; ++i) { var mesh = currentCores[i]; IEffectAttributes effect = mesh.Value; 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; OnUploadPerModelConstantBuffers(deviceContext); } context.CustomPassName = DefaultPassNames.EffectMeshXRayP2; var pass = mesh.Key.EffectTechnique[DefaultPassNames.EffectMeshXRayP2]; if (pass.IsNULL) { continue; } pass.BindShader(deviceContext); pass.BindStates(deviceContext, StateType.BlendState | StateType.DepthStencilState); mesh.Key.Render(context, deviceContext); } currentCores.Clear(); } else { 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.EffectMeshXRayP2; var pass = mesh.EffectTechnique[DefaultPassNames.EffectMeshXRayP2]; if (pass.IsNULL) { continue; } pass.BindShader(deviceContext); pass.BindStates(deviceContext, StateType.BlendState); deviceContext.SetDepthStencilState(pass.DepthStencilState, 0); mesh.Render(context, deviceContext); } } } if (hasMSAA) { deviceContext.ClearRenderTagetBindings(); buffer.FullResDepthStencilPool.Put(Format.D32_Float_S8X24_UInt, depthStencilBuffer); } context.IsCustomPass = false; }
/// <summary> /// Called when [render]. /// </summary> /// <param name="context">The context.</param> /// <param name="deviceContext">The device context.</param> public override void Render(RenderContext context, DeviceContextProxy deviceContext) { var buffer = context.RenderHost.RenderBuffer; var dPass = EnableDoublePass; var depthStencilBuffer = buffer.DepthStencilBufferNoMSAA; deviceContext.SetRenderTarget(depthStencilBuffer, buffer.FullResPPBuffer.CurrentRTV); var viewport = context.Viewport; deviceContext.SetViewport(ref viewport); deviceContext.SetScissorRectangle(ref viewport); deviceContext.ClearDepthStencilView(depthStencilBuffer, DepthStencilClearFlags.Stencil, 1, 0); if (dPass) { for (var i = 0; i < context.RenderHost.PerFrameNodesWithPostEffect.Count; ++i) { var mesh = context.RenderHost.PerFrameNodesWithPostEffect[i]; if (mesh.TryGetPostEffect(EffectName, out var effect)) { currentCores.Add(new KeyValuePair <SceneNode, IEffectAttributes>(mesh, effect)); context.CustomPassName = DefaultPassNames.EffectMeshXRayP1; var pass = mesh.EffectTechnique[DefaultPassNames.EffectMeshXRayP1]; if (pass.IsNULL) { continue; } pass.BindShader(deviceContext); pass.BindStates(deviceContext, StateType.BlendState | StateType.DepthStencilState); mesh.RenderCustom(context, deviceContext); } } modelCB.Upload(deviceContext, ref modelStruct); for (var i = 0; i < currentCores.Count; ++i) { var mesh = currentCores[i]; var effect = mesh.Value; var color = Color; if (effect.TryGetAttribute(EffectAttributeNames.ColorAttributeName, out var attribute) && attribute is string colorStr) { color = colorStr.ToColor4(); } if (modelStruct.Color != color) { modelStruct.Color = color; modelCB.Upload(deviceContext, ref modelStruct); } context.CustomPassName = DefaultPassNames.EffectMeshXRayP2; var pass = mesh.Key.EffectTechnique[DefaultPassNames.EffectMeshXRayP2]; if (pass.IsNULL) { continue; } pass.BindShader(deviceContext); pass.BindStates(deviceContext, StateType.BlendState | StateType.DepthStencilState); mesh.Key.RenderCustom(context, deviceContext); } currentCores.Clear(); } else { modelCB.Upload(deviceContext, ref modelStruct); for (var i = 0; i < context.RenderHost.PerFrameNodesWithPostEffect.Count; ++i) { var mesh = context.RenderHost.PerFrameNodesWithPostEffect[i]; if (mesh.TryGetPostEffect(EffectName, out var effect)) { var color = Color; if (effect.TryGetAttribute(EffectAttributeNames.ColorAttributeName, out var attribute) && attribute is string colorStr) { color = colorStr.ToColor4(); } if (modelStruct.Color != color) { modelStruct.Color = color; modelCB.Upload(deviceContext, ref modelStruct); } context.CustomPassName = DefaultPassNames.EffectMeshXRayP2; var pass = mesh.EffectTechnique[DefaultPassNames.EffectMeshXRayP2]; if (pass.IsNULL) { continue; } pass.BindShader(deviceContext); pass.BindStates(deviceContext, StateType.BlendState); deviceContext.SetDepthStencilState(pass.DepthStencilState, 0); mesh.RenderCustom(context, deviceContext); } } } }
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); } }
/// <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) { context.IsCustomPass = true; if (DoublePass) { deviceContext.DeviceContext.ClearDepthStencilView(context.RenderHost.DepthStencilBufferView, DepthStencilClearFlags.Stencil, 0, 0); currentCores.Clear(); for (int i = 0; i < context.RenderHost.PerFrameGeneralCoresWithPostEffect.Count; ++i) { IEffectAttributes effect; var mesh = context.RenderHost.PerFrameGeneralCoresWithPostEffect[i]; if (mesh.TryGetPostEffect(EffectName, out effect)) { currentCores.Add(new KeyValuePair <RenderCore, IEffectAttributes>(mesh, effect)); context.CustomPassName = DefaultPassNames.EffectMeshXRayP1; var pass = mesh.EffectTechnique[DefaultPassNames.EffectMeshXRayP1]; if (pass.IsNULL) { continue; } pass.BindShader(deviceContext); pass.BindStates(deviceContext, StateType.BlendState); deviceContext.SetDepthStencilState(pass.DepthStencilState, 0);//Increment the stencil value mesh.Render(context, deviceContext); } } for (int i = 0; i < currentCores.Count; ++i) { var mesh = currentCores[i]; IEffectAttributes effect = mesh.Value; 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.EffectMeshXRayP2; var pass = mesh.Key.EffectTechnique[DefaultPassNames.EffectMeshXRayP2]; if (pass.IsNULL) { continue; } pass.BindShader(deviceContext); pass.BindStates(deviceContext, StateType.BlendState); deviceContext.SetDepthStencilState(pass.DepthStencilState, 1);//Do stencil test only on value = 1. mesh.Key.Render(context, deviceContext); } currentCores.Clear(); } else { 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.EffectMeshXRayP2; var pass = mesh.EffectTechnique[DefaultPassNames.EffectMeshXRayP2]; if (pass.IsNULL) { continue; } pass.BindShader(deviceContext); pass.BindStates(deviceContext, StateType.BlendState); deviceContext.SetDepthStencilState(pass.DepthStencilState, 0); mesh.Render(context, deviceContext); } } } context.IsCustomPass = false; }
/// <summary> /// Called when [render]. /// </summary> /// <param name="context">The context.</param> /// <param name="deviceContext">The device context.</param> public override void Render(RenderContext context, DeviceContextProxy deviceContext) { var buffer = context.RenderHost.RenderBuffer; bool hasMSAA = buffer.ColorBufferSampleDesc.Count > 1; var dPass = EnableDoublePass; var depthStencilBuffer = hasMSAA ? context.GetOffScreenDS(OffScreenTextureSize.Full, Format.D32_Float_S8X24_UInt) : buffer.DepthStencilBuffer; deviceContext.SetRenderTarget(depthStencilBuffer, buffer.FullResPPBuffer.CurrentRTV, buffer.TargetWidth, buffer.TargetHeight); if (hasMSAA) { //Needs to do a depth pass for existing meshes.Because the msaa depth buffer is not resolvable. deviceContext.ClearDepthStencilView(depthStencilBuffer, DepthStencilClearFlags.Depth, 1, 0); depthPrepassCore.Render(context, deviceContext); } deviceContext.ClearDepthStencilView(depthStencilBuffer, DepthStencilClearFlags.Stencil, 1, 0); if (dPass) { for (int i = 0; i < context.RenderHost.PerFrameNodesWithPostEffect.Count; ++i) { var mesh = context.RenderHost.PerFrameNodesWithPostEffect[i]; if (mesh.TryGetPostEffect(EffectName, out IEffectAttributes effect)) { currentCores.Add(new KeyValuePair <SceneNode, IEffectAttributes>(mesh, effect)); context.CustomPassName = DefaultPassNames.EffectMeshXRayP1; var pass = mesh.EffectTechnique[DefaultPassNames.EffectMeshXRayP1]; if (pass.IsNULL) { continue; } pass.BindShader(deviceContext); pass.BindStates(deviceContext, StateType.BlendState | StateType.DepthStencilState); mesh.RenderCustom(context, deviceContext); } } modelCB.Upload(deviceContext, ref modelStruct); for (int i = 0; i < currentCores.Count; ++i) { var mesh = currentCores[i]; IEffectAttributes effect = mesh.Value; 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.EffectMeshXRayP2; var pass = mesh.Key.EffectTechnique[DefaultPassNames.EffectMeshXRayP2]; if (pass.IsNULL) { continue; } pass.BindShader(deviceContext); pass.BindStates(deviceContext, StateType.BlendState | StateType.DepthStencilState); mesh.Key.RenderCustom(context, deviceContext); } currentCores.Clear(); } else { modelCB.Upload(deviceContext, ref modelStruct); for (int i = 0; i < context.RenderHost.PerFrameNodesWithPostEffect.Count; ++i) { var mesh = context.RenderHost.PerFrameNodesWithPostEffect[i]; 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.EffectMeshXRayP2; var pass = mesh.EffectTechnique[DefaultPassNames.EffectMeshXRayP2]; if (pass.IsNULL) { continue; } pass.BindShader(deviceContext); pass.BindStates(deviceContext, StateType.BlendState); deviceContext.SetDepthStencilState(pass.DepthStencilState, 0); mesh.RenderCustom(context, deviceContext); } } } if (hasMSAA) { deviceContext.ClearRenderTagetBindings(); depthStencilBuffer.Dispose(); } }