void Device::SetRenderTarget( const Texture3D& _Target, const Texture2D* _pDepthStencil, const D3D11_VIEWPORT* _pViewport ) { ID3D11RenderTargetView* pTargetView = _Target.GetRTV( 0, 0, 0 ); ID3D11DepthStencilView* pDepthStencilView = _pDepthStencil != NULL ? _pDepthStencil->GetDSV() : NULL; SetRenderTargets( _Target.GetWidth(), _Target.GetHeight(), 1, &pTargetView, pDepthStencilView, _pViewport ); }
void D3DContext::Resize() { uint width = m_Properties.width; uint height = m_Properties.height; ReleaseCOM(m_RenderTargetView); ReleaseCOM(m_DepthStencilView); ReleaseCOM(m_DepthStencilBuffer); swapchain->ResizeBuffers(1, width, height, DXGI_FORMAT_R8G8B8A8_UNORM, 0); ID3D11Texture2D *backBuffer; swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBuffer); dev->CreateRenderTargetView(backBuffer, NULL, &m_RenderTargetView); backBuffer->Release(); D3D11_TEXTURE2D_DESC depthStencilDesc; depthStencilDesc.Width = width; depthStencilDesc.Height = height; depthStencilDesc.MipLevels = 1; depthStencilDesc.ArraySize = 1; depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depthStencilDesc.SampleDesc.Count = m_MSAAEnabled ? 4 : 1; depthStencilDesc.SampleDesc.Quality = m_MSAAEnabled ? (m_MSAAQuality - 1) : 0; depthStencilDesc.Usage = D3D11_USAGE_DEFAULT; depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; depthStencilDesc.CPUAccessFlags = 0; depthStencilDesc.MiscFlags = 0; dev->CreateTexture2D(&depthStencilDesc, 0, &m_DepthStencilBuffer); dev->CreateDepthStencilView(m_DepthStencilBuffer, 0, &m_DepthStencilView); SetRenderTargets(m_RenderTargetView, m_DepthStencilView); m_ScreenViewport.TopLeftX = 0; m_ScreenViewport.TopLeftY = 0; m_ScreenViewport.Width = (float)width; m_ScreenViewport.Height = (float)height; m_ScreenViewport.MinDepth = 0.0f; m_ScreenViewport.MaxDepth = 1.0f; devcon->RSSetViewports(1, &m_ScreenViewport); D3D11_RASTERIZER_DESC rasterDesc; rasterDesc.AntialiasedLineEnable = false; rasterDesc.CullMode = D3D11_CULL_NONE; rasterDesc.DepthBias = 0; rasterDesc.DepthBiasClamp = 0.0f; rasterDesc.DepthClipEnable = true; rasterDesc.FillMode = D3D11_FILL_SOLID; rasterDesc.FrontCounterClockwise = true; rasterDesc.MultisampleEnable = false; rasterDesc.ScissorEnable = false; rasterDesc.SlopeScaledDepthBias = 0.0f; ID3D11RasterizerState* rs; dev->CreateRasterizerState(&rasterDesc, &rs); devcon->RSSetState(rs); ReleaseCOM(rs); }
void RenderToVolumeTexture(const Ptr<Texture> & volumeTexture) { auto rc = Global::GetRenderEngine()->GetRenderContext(); auto & quadVBs = GetQuadVBs(); auto & quadIB = GetQuadIB(); RenderViewport vp; vp.topLeftX = 0.0f; vp.topLeftY = 0.0f; vp.width = static_cast<float>(volumeTexture->GetDesc().width); vp.height = static_cast<float>(volumeTexture->GetDesc().height); vp.minDepth = 0.0f; vp.maxDepth = 1.0f; rc->SetViewport(vp); float2 uvMap[4]; uvMap[0] = float2(0.0f, 0.0f); uvMap[1] = float2(1.0f, 0.0f); uvMap[2] = float2(0.0f, 1.0f); uvMap[3] = float2(1.0f, 1.0f); auto uvBufMappedData = quadVBs[1]->Map(MAP_WRITE_DISCARD); memcpy(uvBufMappedData.pData, uvMap, sizeof(float2) * 4); quadVBs[1]->UnMap(); // Set vbs, ib rc->SetVertexBuffer(quadVBs); rc->SetIndexBuffer(quadIB); rc->SetPrimitiveTopology(PRIMITIVE_TOPOLOGY_TRIANGLELIST); // Set rtv rc->SetRenderTargets({ volumeTexture->GetRenderTargetView(0, 0, volumeTexture->GetDesc().depth) }); // Set dsv rc->SetDepthStencilState(DepthStencilStateTemplate<false>::Get()); // Bind shader auto vs = Shader::FindOrCreate<RenderToVolumeTextureVS>(); auto gs = Shader::FindOrCreate<RenderToVolumeTextureGS>(); vs->Flush(); gs->Flush(); // Draw rc->DrawIndexedInstanced(quadIB->GetDesc().numElements, volumeTexture->GetDesc().depth, 0, 0, 0); rc->SetDepthStencilState(nullptr); rc->ResetShader(SHADER_GS); }
void TextureFilter( const Ptr<ShaderResourceView> & src, const Ptr<RenderTargetView> & dst, const std::vector<float2> & uvOffsets, const std::vector<float> & weights, const Ptr<class Sampler> & sampler) { ToyGE_ASSERT(uvOffsets.size() == weights.size()); ToyGE_ASSERT(src); ToyGE_ASSERT(dst); int32_t numSamples = (int32_t)uvOffsets.size(); if (numSamples <= 0) return; auto rc = Global::GetRenderEngine()->GetRenderContext(); rc->SetViewport(GetTextureQuadViewport(dst->GetResource()->Cast<Texture>())); auto filterVS = Shader::FindOrCreate<FilterVS>({ { "NUM_SAMPLES", std::to_string(numSamples) } }); auto filterPS = Shader::FindOrCreate<FilterPS>({ { "NUM_SAMPLES", std::to_string(numSamples) } }); filterVS->SetScalar("samplesOffsets", &uvOffsets[0], (int32_t)(sizeof(uvOffsets[0]) * uvOffsets.size())); filterVS->Flush(); filterPS->SetScalar("samplesWeights", &weights[0], (int32_t)(sizeof(weights[0]) * weights.size())); filterPS->SetSRV("filterTex", src); filterPS->SetSampler("filterSampler", sampler ? sampler : SamplerTemplate<>::Get()); filterPS->Flush(); rc->SetRenderTargets({ dst }); rc->SetDepthStencil(nullptr); rc->SetDepthStencilState(DepthStencilStateTemplate<false>::Get()); rc->SetVertexBuffer({ GetQuadVBs()[0] }); rc->SetIndexBuffer(GetQuadIB()); rc->SetPrimitiveTopology(PRIMITIVE_TOPOLOGY_TRIANGLELIST); rc->DrawIndexed(0, 0); }
void SkyBox::Render(const Ptr<RenderTargetView> & target, const Ptr<DepthStencilView> & dsv, const Ptr<RenderView> & view) { if (!_tex) return; auto rc = Global::GetRenderEngine()->GetRenderContext(); auto translationMat = translation(view->GetCamera()->GetPos()); auto transformMat = mul(translationMat, view->GetCamera()->GetViewProjMatrix()); auto vs = Shader::FindOrCreate<SkyBoxVS>(); auto ps = Shader::FindOrCreate<SkyBoxPS>(); vs->SetScalar("transform", transformMat); ps->SetSRV("skyBoxTex", _tex->GetShaderResourceView(0, 0, 0, 0, true)); ps->SetSampler("linearSampler", SamplerTemplate<>::Get()); vs->Flush(); ps->Flush(); rc->SetViewport(GetTextureQuadViewport(target->GetResource()->Cast<Texture>())); rc->SetRenderTargets({ target }); rc->SetDepthStencil(dsv); rc->SetRasterizerState(RasterizerStateTemplate<FILL_SOLID, CULL_NONE>::Get()); rc->SetDepthStencilState(DepthStencilStateTemplate<true, DEPTH_WRITE_ZERO, COMPARISON_LESS_EQUAL>::Get()); rc->SetVertexBuffer(_sphereMesh->GetRenderData()->GetMeshElements()[0]->GetVertexBuffer()); rc->SetIndexBuffer(_sphereMesh->GetRenderData()->GetMeshElements()[0]->GetIndexBuffer()); rc->SetPrimitiveTopology(PRIMITIVE_TOPOLOGY_TRIANGLELIST); rc->DrawIndexed(0, 0); rc->SetRasterizerState(nullptr); rc->SetDepthStencilState(nullptr); }
void FRCPassPostProcessDOFSetup::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, DOFSetup); const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0); if(!InputDesc) { // input is not hooked up correctly return; } uint32 NumRenderTargets = bNearBlurEnabled ? 2 : 1; const FSceneView& View = Context.View; const FSceneViewFamily& ViewFamily = *(View.Family); const auto FeatureLevel = Context.GetFeatureLevel(); auto ShaderMap = Context.GetShaderMap(); FIntPoint SrcSize = InputDesc->Extent; FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent; // e.g. 4 means the input texture is 4x smaller than the buffer size uint32 ScaleFactor = FSceneRenderTargets::Get(Context.RHICmdList).GetBufferSizeXY().X / SrcSize.X; FIntRect SrcRect = View.ViewRect / ScaleFactor; FIntRect DestRect = SrcRect / 2; const FSceneRenderTargetItem& DestRenderTarget0 = PassOutputs[0].RequestSurface(Context); const FSceneRenderTargetItem& DestRenderTarget1 = bNearBlurEnabled ? PassOutputs[1].RequestSurface(Context) : FSceneRenderTargetItem(); // Set the view family's render target/viewport. FTextureRHIParamRef RenderTargets[2] = { DestRenderTarget0.TargetableTexture, DestRenderTarget1.TargetableTexture }; SetRenderTargets(Context.RHICmdList, NumRenderTargets, RenderTargets, FTextureRHIParamRef(), 0, NULL); FLinearColor ClearColors[2] = { FLinearColor(0, 0, 0, 0), FLinearColor(0, 0, 0, 0) }; // is optimized away if possible (RT size=view size, ) Context.RHICmdList.ClearMRT(true, NumRenderTargets, ClearColors, false, 1.0f, false, 0, DestRect); Context.SetViewportAndCallRHI(0, 0, 0.0f, DestSize.X, DestSize.Y, 1.0f ); // set the state Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); TShaderMapRef<FPostProcessVS> VertexShader(ShaderMap); if (bNearBlurEnabled) { static FGlobalBoundShaderState BoundShaderState; TShaderMapRef< FPostProcessDOFSetupPS<1> > PixelShader(ShaderMap); SetGlobalBoundShaderState(Context.RHICmdList, FeatureLevel, BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetParameters(Context); } else { static FGlobalBoundShaderState BoundShaderState; TShaderMapRef< FPostProcessDOFSetupPS<0> > PixelShader(ShaderMap); SetGlobalBoundShaderState(Context.RHICmdList, FeatureLevel, BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetParameters(Context); } VertexShader->SetParameters(Context); DrawPostProcessPass( Context.RHICmdList, DestRect.Min.X, DestRect.Min.Y, DestRect.Width() + 1, DestRect.Height() + 1, SrcRect.Min.X, SrcRect.Min.Y, SrcRect.Width() + 1, SrcRect.Height() + 1, DestSize, SrcSize, *VertexShader, View.StereoPass, Context.HasHmdMesh(), EDRF_UseTriangleOptimization); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget0.TargetableTexture, DestRenderTarget0.ShaderResourceTexture, false, FResolveParams()); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget1.TargetableTexture, DestRenderTarget1.ShaderResourceTexture, false, FResolveParams()); }
void FRCPassPostProcessLpvIndirect::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessLpvIndirect); { FRenderingCompositeOutput* OutputOfMyInput = GetInput(ePId_Input0)->GetOutput(); PassOutputs[0].PooledRenderTarget = OutputOfMyInput->PooledRenderTarget; OutputOfMyInput->RenderTargetDesc.DebugName = PassOutputs[0].RenderTargetDesc.DebugName; PassOutputs[0].RenderTargetDesc = OutputOfMyInput->RenderTargetDesc; check(PassOutputs[0].RenderTargetDesc.Extent.X); check(PassOutputs[0].RenderTargetDesc.Extent.Y); } const FPostProcessSettings& PostprocessSettings = Context.View.FinalPostProcessSettings; const FSceneView& View = Context.View; const FSceneViewFamily& ViewFamily = *(View.Family); FIntRect SrcRect = View.ViewRect; // todo: view size should scale with input texture size so we can do SSAO in half resolution as well FIntRect DestRect = View.ViewRect; FIntPoint DestSize = DestRect.Size(); uint32 NumReflectionCaptures = ViewFamily.Scene->GetRenderScene()->ReflectionSceneData.RegisteredReflectionCaptures.Num(); const FSceneRenderTargetItem& DestColorRenderTarget = GSceneRenderTargets.GetSceneColor()->GetRenderTargetItem(); // Set the view family's render target/viewport. FTextureRHIParamRef RenderTargets[] = { DestColorRenderTarget.TargetableTexture, }; // Set the view family's render target/viewport. SetRenderTargets(Context.RHICmdList, 1, RenderTargets, GSceneRenderTargets.GetSceneDepthSurface(), 0, NULL); Context.SetViewportAndCallRHI(View.ViewRect); // set the state if ( ViewFamily.EngineShowFlags.LpvLightingOnly ) { Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); } else { // additive blending Context.RHICmdList.SetBlendState(TStaticBlendState<CW_RGB, BO_Add, BF_One, BF_One>::GetRHI()); } Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); TShaderMapRef<FPostProcessVS> VertexShader(Context.GetShaderMap()); FSceneViewState* ViewState = (FSceneViewState*)View.State; FLightPropagationVolume* Lpv = NULL; bool bUseLpv = false; if ( ViewState ) { Lpv = ViewState->GetLightPropagationVolume(); bUseLpv = Lpv && PostprocessSettings.LPVIntensity > 0.0f; } if ( !bUseLpv ) { return; } TShaderMapRef<FPostProcessLpvIndirectPS> PixelShader(Context.GetShaderMap()); static FGlobalBoundShaderState BoundShaderState; // call it once after setting up the shader data to avoid the warnings in the function SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); FLpvReadUniformBufferParameters LpvReadUniformBufferParams; FLpvReadUniformBufferRef LpvReadUniformBuffer; LpvReadUniformBufferParams = Lpv->GetReadUniformBufferParams(); LpvReadUniformBuffer = FLpvReadUniformBufferRef::CreateUniformBufferImmediate( LpvReadUniformBufferParams, UniformBuffer_SingleDraw ); #if LPV_VOLUME_TEXTURE FTextureRHIParamRef LpvBufferSrvs[7]; for ( int i = 0; i < 7; i++ ) { LpvBufferSrvs[i] = Lpv->GetLpvBufferSrv(i); } PixelShader->SetParameters(LpvBufferSrvs, LpvReadUniformBuffer, Context); #else FShaderResourceViewRHIParamRef LpvBufferSrv = Lpv->GetLpvBufferSrv(); PixelShader->SetParameters(LpvBufferSrv, LpvReadUniformBuffer, Context); #endif // Draw a quad mapping scene color to the view's render target DrawRectangle( Context.RHICmdList, 0, 0, View.ViewRect.Width(), View.ViewRect.Height(), View.ViewRect.Min.X, View.ViewRect.Min.Y, View.ViewRect.Width(), View.ViewRect.Height(), View.ViewRect.Size(), GSceneRenderTargets.GetBufferSizeXY(), *VertexShader); Context.RHICmdList.CopyToResolveTarget(DestColorRenderTarget.TargetableTexture, DestColorRenderTarget.ShaderResourceTexture, false, FResolveParams()); }
void FRCPassPostProcessDeferredDecals::Process(FRenderingCompositePassContext& Context) { FRHICommandListImmediate& RHICmdList = Context.RHICmdList; FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList); const bool bShaderComplexity = Context.View.Family->EngineShowFlags.ShaderComplexity; const bool bDBuffer = IsDBufferEnabled(); const bool bStencilSizeThreshold = CVarStencilSizeThreshold.GetValueOnRenderThread() >= 0; SCOPED_DRAW_EVENT(RHICmdList, PostProcessDeferredDecals); enum EDecalResolveBufferIndex { SceneColorIndex, GBufferAIndex, GBufferBIndex, GBufferCIndex, DBufferAIndex, DBufferBIndex, DBufferCIndex, ResolveBufferMax, }; FTextureRHIParamRef TargetsToResolve[ResolveBufferMax] = { nullptr }; if(DecalRenderStage == DRS_BeforeBasePass) { // before BasePass, only if DBuffer is enabled check(bDBuffer); // DBuffer: Decal buffer FPooledRenderTargetDesc Desc(FPooledRenderTargetDesc::Create2DDesc(SceneContext.GBufferA->GetDesc().Extent, PF_B8G8R8A8, FClearValueBinding::None, TexCreate_None, TexCreate_ShaderResource | TexCreate_RenderTargetable, false)); if(!SceneContext.DBufferA) { Desc.ClearValue = FClearValueBinding::Black; GRenderTargetPool.FindFreeElement(Desc, SceneContext.DBufferA, TEXT("DBufferA")); } if(!SceneContext.DBufferB) { Desc.ClearValue = FClearValueBinding(FLinearColor(128.0f / 255.0f, 128.0f / 255.0f, 128.0f / 255.0f, 1)); GRenderTargetPool.FindFreeElement(Desc, SceneContext.DBufferB, TEXT("DBufferB")); } Desc.Format = PF_R8G8; if(!SceneContext.DBufferC) { Desc.ClearValue = FClearValueBinding(FLinearColor(0, 1, 0, 1)); GRenderTargetPool.FindFreeElement(Desc, SceneContext.DBufferC, TEXT("DBufferC")); } // we assume views are non overlapping, then we need to clear only once in the beginning, otherwise we would need to set scissor rects // and don't get FastClear any more. bool bFirstView = Context.View.Family->Views[0] == &Context.View; if(bFirstView) { SCOPED_DRAW_EVENT(RHICmdList, DBufferClear); FRHIRenderTargetView RenderTargets[3]; RenderTargets[0] = FRHIRenderTargetView(SceneContext.DBufferA->GetRenderTargetItem().TargetableTexture, 0, -1, ERenderTargetLoadAction::EClear, ERenderTargetStoreAction::EStore); RenderTargets[1] = FRHIRenderTargetView(SceneContext.DBufferB->GetRenderTargetItem().TargetableTexture, 0, -1, ERenderTargetLoadAction::EClear, ERenderTargetStoreAction::EStore); RenderTargets[2] = FRHIRenderTargetView(SceneContext.DBufferC->GetRenderTargetItem().TargetableTexture, 0, -1, ERenderTargetLoadAction::EClear, ERenderTargetStoreAction::EStore); FRHIDepthRenderTargetView DepthView(SceneContext.GetSceneDepthSurface(), ERenderTargetLoadAction::ELoad, ERenderTargetStoreAction::ENoAction, ERenderTargetLoadAction::ELoad, ERenderTargetStoreAction::ENoAction, FExclusiveDepthStencil(FExclusiveDepthStencil::DepthRead_StencilWrite)); FRHISetRenderTargetsInfo Info(3, RenderTargets, DepthView); RHICmdList.SetRenderTargetsAndClear(Info); TargetsToResolve[DBufferAIndex] = SceneContext.DBufferA->GetRenderTargetItem().TargetableTexture; TargetsToResolve[DBufferBIndex] = SceneContext.DBufferB->GetRenderTargetItem().TargetableTexture; TargetsToResolve[DBufferCIndex] = SceneContext.DBufferC->GetRenderTargetItem().TargetableTexture; } } // this cast is safe as only the dedicated server implements this differently and this pass should not be executed on the dedicated server const FViewInfo& View = Context.View; const FSceneViewFamily& ViewFamily = *(View.Family); FScene& Scene = *(FScene*)ViewFamily.Scene; //don't early return. Resolves must be run for fast clears to work. bool bRenderDecal = Scene.Decals.Num() && ViewFamily.EngineShowFlags.Decals; if (bRenderDecal) { // Build a list of decals that need to be rendered for this view FTransientDecalRenderDataList SortedDecals; FDecalRendering::BuildVisibleDecalList(Scene, View, DecalRenderStage, SortedDecals); if (SortedDecals.Num() > 0) { FIntRect SrcRect = View.ViewRect; FIntRect DestRect = View.ViewRect; bool bStencilDecalsInThisStage = true; #if DBUFFER_DONT_USE_STENCIL_YET if (DecalRenderStage != DRS_BeforeLighting) { bStencilDecalsInThisStage = false; } #endif // Setup a stencil mask to prevent certain pixels from receiving deferred decals if (bStencilDecalsInThisStage) { StencilDecalMask(RHICmdList, View, Context.HasHmdMesh()); } // optimization to have less state changes EDecalRasterizerState LastDecalRasterizerState = DRS_Undefined; FDecalDepthState LastDecalDepthState; int32 LastDecalBlendMode = -1; int32 LastDecalHasNormal = -1; // Decal state can change based on its normal property.(SM5) FDecalRendering::ERenderTargetMode LastRenderTargetMode = FDecalRendering::RTM_Unknown; const ERHIFeatureLevel::Type SMFeatureLevel = Context.GetFeatureLevel(); SCOPED_DRAW_EVENT(RHICmdList, Decals); INC_DWORD_STAT_BY(STAT_Decals, SortedDecals.Num()); for (int32 DecalIndex = 0, DecalCount = SortedDecals.Num(); DecalIndex < DecalCount; DecalIndex++) { const FTransientDecalRenderData& DecalData = SortedDecals[DecalIndex]; const FDeferredDecalProxy& DecalProxy = *DecalData.DecalProxy; const FMatrix ComponentToWorldMatrix = DecalProxy.ComponentTrans.ToMatrixWithScale(); const FMatrix FrustumComponentToClip = FDecalRendering::ComputeComponentToClipMatrix(View, ComponentToWorldMatrix); EDecalBlendMode DecalBlendMode = DecalData.DecalBlendMode; bool bStencilThisDecal = bStencilDecalsInThisStage; #if DBUFFER_DONT_USE_STENCIL_YET if (FDecalRendering::ComputeRenderStage(View.GetShaderPlatform(), DecalBlendMode) != DRS_BeforeLighting) { bStencilThisDecal = false; } #endif FDecalRendering::ERenderTargetMode CurrentRenderTargetMode = FDecalRendering::ComputeRenderTargetMode(View.GetShaderPlatform(), DecalBlendMode); if (bShaderComplexity) { CurrentRenderTargetMode = FDecalRendering::RTM_SceneColor; // we want additive blending for the ShaderComplexity mode DecalBlendMode = DBM_Emissive; } // fewer rendertarget switches if possible if (CurrentRenderTargetMode != LastRenderTargetMode) { LastRenderTargetMode = CurrentRenderTargetMode; switch (CurrentRenderTargetMode) { case FDecalRendering::RTM_SceneColorAndGBuffer: { TargetsToResolve[SceneColorIndex] = SceneContext.GetSceneColor()->GetRenderTargetItem().TargetableTexture; TargetsToResolve[GBufferAIndex] = SceneContext.GBufferA->GetRenderTargetItem().TargetableTexture; TargetsToResolve[GBufferBIndex] = SceneContext.GBufferB->GetRenderTargetItem().TargetableTexture; TargetsToResolve[GBufferCIndex] = SceneContext.GBufferC->GetRenderTargetItem().TargetableTexture; SetRenderTargets(RHICmdList, 4, TargetsToResolve, SceneContext.GetSceneDepthSurface(), ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite); } break; case FDecalRendering::RTM_SceneColorAndGBufferDepthWrite: { TargetsToResolve[SceneColorIndex] = SceneContext.GetSceneColor()->GetRenderTargetItem().TargetableTexture; TargetsToResolve[GBufferAIndex] = SceneContext.GBufferA->GetRenderTargetItem().TargetableTexture; TargetsToResolve[GBufferBIndex] = SceneContext.GBufferB->GetRenderTargetItem().TargetableTexture; TargetsToResolve[GBufferCIndex] = SceneContext.GBufferC->GetRenderTargetItem().TargetableTexture; SetRenderTargets(RHICmdList, 4, TargetsToResolve, SceneContext.GetSceneDepthSurface(), ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthWrite_StencilWrite); } break; case FDecalRendering::RTM_GBufferNormal: TargetsToResolve[GBufferAIndex] = SceneContext.GBufferA->GetRenderTargetItem().TargetableTexture; SetRenderTarget(RHICmdList, TargetsToResolve[GBufferAIndex], SceneContext.GetSceneDepthSurface(), ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite); break; case FDecalRendering::RTM_SceneColor: TargetsToResolve[SceneColorIndex] = SceneContext.GetSceneColor()->GetRenderTargetItem().TargetableTexture; SetRenderTarget(RHICmdList, TargetsToResolve[SceneColorIndex], SceneContext.GetSceneDepthSurface(), ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite); break; case FDecalRendering::RTM_DBuffer: { TargetsToResolve[DBufferAIndex] = SceneContext.DBufferA->GetRenderTargetItem().TargetableTexture; TargetsToResolve[DBufferBIndex] = SceneContext.DBufferB->GetRenderTargetItem().TargetableTexture; TargetsToResolve[DBufferCIndex] = SceneContext.DBufferC->GetRenderTargetItem().TargetableTexture; SetRenderTargets(RHICmdList, 3, &TargetsToResolve[DBufferAIndex], SceneContext.GetSceneDepthSurface(), ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite); } break; default: check(0); break; } Context.SetViewportAndCallRHI(DestRect); // we need to reset the stream source after any call to SetRenderTarget (at least for Metal, which doesn't queue up VB assignments) RHICmdList.SetStreamSource(0, GetUnitCubeVertexBuffer(), sizeof(FVector4), 0); } bool bThisDecalUsesStencil = false; if (bStencilThisDecal) { if (bStencilSizeThreshold) { // note this is after a SetStreamSource (in if CurrentRenderTargetMode != LastRenderTargetMode) call as it needs to get the VB input bThisDecalUsesStencil = RenderPreStencil(Context, ComponentToWorldMatrix, FrustumComponentToClip); LastDecalRasterizerState = DRS_Undefined; LastDecalDepthState = FDecalDepthState(); LastDecalBlendMode = -1; } } const bool bBlendStateChange = DecalBlendMode != LastDecalBlendMode;// Has decal mode changed. const bool bDecalNormalChanged = GSupportsSeparateRenderTargetBlendState && // has normal changed for SM5 stain/translucent decals? (DecalBlendMode == DBM_Translucent || DecalBlendMode == DBM_Stain) && (int32)DecalData.bHasNormal != LastDecalHasNormal; // fewer blend state changes if possible if (bBlendStateChange || bDecalNormalChanged) { LastDecalBlendMode = DecalBlendMode; LastDecalHasNormal = (int32)DecalData.bHasNormal; SetDecalBlendState(RHICmdList, SMFeatureLevel, DecalRenderStage, (EDecalBlendMode)LastDecalBlendMode, DecalData.bHasNormal); } // todo const float ConservativeRadius = DecalData.ConservativeRadius; // const int32 IsInsideDecal = ((FVector)View.ViewMatrices.ViewOrigin - ComponentToWorldMatrix.GetOrigin()).SizeSquared() < FMath::Square(ConservativeRadius * 1.05f + View.NearClippingDistance * 2.0f) + ( bThisDecalUsesStencil ) ? 2 : 0; const bool bInsideDecal = ((FVector)View.ViewMatrices.ViewOrigin - ComponentToWorldMatrix.GetOrigin()).SizeSquared() < FMath::Square(ConservativeRadius * 1.05f + View.NearClippingDistance * 2.0f); // const bool bInsideDecal = !(IsInsideDecal & 1); // update rasterizer state if needed { EDecalRasterizerState DecalRasterizerState = ComputeDecalRasterizerState(bInsideDecal, View); if (LastDecalRasterizerState != DecalRasterizerState) { LastDecalRasterizerState = DecalRasterizerState; SetDecalRasterizerState(DecalRasterizerState, RHICmdList); } } // update DepthStencil state if needed { FDecalDepthState DecalDepthState = ComputeDecalDepthState(DecalBlendMode, bInsideDecal, bStencilDecalsInThisStage, bThisDecalUsesStencil); if (LastDecalDepthState != DecalDepthState) { LastDecalDepthState = DecalDepthState; SetDecalDepthState(DecalDepthState, RHICmdList); } } FDecalRendering::SetShader(RHICmdList, View, bShaderComplexity, DecalData, FrustumComponentToClip); RHICmdList.DrawIndexedPrimitive(GetUnitCubeIndexBuffer(), PT_TriangleList, 0, 0, 8, 0, ARRAY_COUNT(GCubeIndices) / 3, 1); } // we don't modify stencil but if out input was having stencil for us (after base pass - we need to clear) // Clear stencil to 0, which is the assumed default by other passes RHICmdList.Clear(false, FLinearColor::White, false, (float)ERHIZBuffer::FarPlane, true, 0, FIntRect()); if (DecalRenderStage == DRS_BeforeBasePass) { // before BasePass GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.DBufferA); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.DBufferB); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.DBufferC); } } } // resolve the targets we wrote to. FResolveParams ResolveParams; for (int32 i = 0; i < ResolveBufferMax; ++i) { if (TargetsToResolve[i]) { RHICmdList.CopyToResolveTarget(TargetsToResolve[i], TargetsToResolve[i], true, ResolveParams); } } }
void DrawQuad( const std::vector< Ptr<class RenderTargetView> > & rtvs, float topLeftX, float topLeftY, float width, float height, float topLeftU, float topLeftV, float uvWidth, float uvHeight, const Ptr<class DepthStencilView> & dsv) { /*if (rtvs.size() == 0) return;*/ auto & quadVBs = GetQuadVBs(); auto & quadIB = GetQuadIB(); auto rc = Global::GetRenderEngine()->GetRenderContext(); // Viewport if (width == 0.0f) { if (rtvs.size() > 0) { auto tex = rtvs[0]->GetResource()->Cast<Texture>(); auto & mipSize = tex->GetMipSize(rtvs[0]->Cast<TextureRenderTargetView>()->mipLevel); width = (float)mipSize.x(); } else if (dsv) { auto tex = dsv->GetResource()->Cast<Texture>(); auto & mipSize = tex->GetMipSize(dsv->Cast<TextureDepthStencilView>()->mipLevel); width = (float)mipSize.x(); } } if (height == 0.0f) { if (rtvs.size() > 0) { auto tex = rtvs[0]->GetResource()->Cast<Texture>(); auto & mipSize = tex->GetMipSize(rtvs[0]->Cast<TextureRenderTargetView>()->mipLevel); height = (float)mipSize.y(); } else if (dsv) { auto tex = dsv->GetResource()->Cast<Texture>(); auto & mipSize = tex->GetMipSize(dsv->Cast<TextureDepthStencilView>()->mipLevel); height = (float)mipSize.y(); } } RenderViewport vp; vp.topLeftX = static_cast<float>(topLeftX); vp.topLeftY = static_cast<float>(topLeftY); vp.width = static_cast<float>(width); vp.height = static_cast<float>(height); vp.minDepth = 0.0f; vp.maxDepth = 1.0f; rc->SetViewport(vp); // Update uvs float2 uvMap[4]; uvMap[0] = float2(topLeftU, topLeftV); uvMap[1] = float2(topLeftU + uvWidth, topLeftV); uvMap[2] = float2(topLeftU, topLeftV + uvHeight); uvMap[3] = float2(topLeftU + uvWidth, topLeftV + uvHeight); auto uvBufMappedData = quadVBs[1]->Map(MAP_WRITE_DISCARD); memcpy(uvBufMappedData.pData, uvMap, sizeof(float2) * 4); quadVBs[1]->UnMap(); // Set vbs, ib rc->SetVertexBuffer(quadVBs); rc->SetIndexBuffer(quadIB); rc->SetPrimitiveTopology(PRIMITIVE_TOPOLOGY_TRIANGLELIST); // Set rtv rc->SetRenderTargets(rtvs); // Set dsv rc->SetDepthStencil(dsv); if (!dsv) rc->SetDepthStencilState(DepthStencilStateTemplate<false>::Get()); // Bind shader auto drawQuadVS = Shader::FindOrCreate<DrawQuadVS>(); drawQuadVS->Flush(); // Draw rc->DrawIndexed(0, 0); if (!dsv) rc->SetDepthStencilState(nullptr); }
void Device::SetRenderTarget( U32 _Width, U32 _Height, const ID3D11RenderTargetView& _Target, ID3D11DepthStencilView* _pDepthStencil, const D3D11_VIEWPORT* _pViewport ) { const ID3D11RenderTargetView* pTargetView = &_Target; SetRenderTargets( _Width, _Height, 1, (ID3D11RenderTargetView* const*) &pTargetView, _pDepthStencil, _pViewport ); }
void FRCPassPostProcessLpvIndirect::DoDirectionalOcclusionPass(FRenderingCompositePassContext& Context) const { FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(Context.RHICmdList); SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessLpvDirectionalOcclusion ); const FSceneRenderTargetItem& DestDirectionalOcclusionRenderTarget = SceneContext.DirectionalOcclusion->GetRenderTargetItem(); const FViewInfo& View = Context.View; FSceneViewState* ViewState = (FSceneViewState*)View.State; if(!ViewState) { return; } const FFinalPostProcessSettings& PostprocessSettings = Context.View.FinalPostProcessSettings; const FLightPropagationVolumeSettings& LPVSettings = PostprocessSettings.BlendableManager.GetSingleFinalDataConst<FLightPropagationVolumeSettings>(); FLightPropagationVolume* Lpv = ViewState->GetLightPropagationVolume(Context.GetFeatureLevel()); if(!Lpv || LPVSettings.LPVIntensity == 0.0f) { return; } FTextureRHIParamRef RenderTarget = DestDirectionalOcclusionRenderTarget.TargetableTexture; SetRenderTargets(Context.RHICmdList, 1, &RenderTarget, NULL, ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilNop); Context.SetViewportAndCallRHI(View.ViewRect); Context.RHICmdList.SetBlendState( TStaticBlendState<>::GetRHI() ); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI()); TShaderMapRef<FPostProcessVS> VertexShader(View.ShaderMap); FLpvReadUniformBufferParameters LpvReadUniformBufferParams; FLpvReadUniformBufferRef LpvReadUniformBuffer; TShaderMapRef< FPostProcessLpvDirectionalOcclusionPS > PixelShader(View.ShaderMap); static FGlobalBoundShaderState BoundShaderState; // call it once after setting up the shader data to avoid the warnings in the function SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); LpvReadUniformBufferParams = Lpv->GetReadUniformBufferParams(); LpvReadUniformBuffer = FLpvReadUniformBufferRef::CreateUniformBufferImmediate( LpvReadUniformBufferParams, UniformBuffer_SingleDraw ); PixelShader->SetParameters( Lpv->GetAOVolumeTextureSRV(), LpvReadUniformBuffer, Context ); DrawPostProcessPass( Context.RHICmdList, 0, 0, View.ViewRect.Width(), View.ViewRect.Height(), View.ViewRect.Min.X, View.ViewRect.Min.Y, View.ViewRect.Width(), View.ViewRect.Height(), View.ViewRect.Size(), SceneContext.GetBufferSizeXY(), *VertexShader, View.StereoPass, Context.HasHmdMesh()); }
void FRCPassPostProcessLpvIndirect::Process(FRenderingCompositePassContext& Context) { FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(Context.RHICmdList); { FRenderingCompositeOutput* OutputOfMyInput = GetInput(ePId_Input0)->GetOutput(); PassOutputs[0].PooledRenderTarget = OutputOfMyInput->PooledRenderTarget; OutputOfMyInput->RenderTargetDesc.DebugName = PassOutputs[0].RenderTargetDesc.DebugName; PassOutputs[0].RenderTargetDesc = OutputOfMyInput->RenderTargetDesc; check(PassOutputs[0].RenderTargetDesc.Extent.X); check(PassOutputs[0].RenderTargetDesc.Extent.Y); } const FFinalPostProcessSettings& PostprocessSettings = Context.View.FinalPostProcessSettings; const FSceneView& View = Context.View; FSceneViewState* ViewState = (FSceneViewState*)View.State; if(!ViewState) { return; } // This check should be inclusive to stereo views const bool bIncludeStereoViews = true; FLightPropagationVolume* Lpv = ViewState->GetLightPropagationVolume(Context.GetFeatureLevel(), bIncludeStereoViews); const FLightPropagationVolumeSettings& LPVSettings = PostprocessSettings.BlendableManager.GetSingleFinalDataConst<FLightPropagationVolumeSettings>(); if(!Lpv || LPVSettings.LPVIntensity == 0.0f) { return; } const FSceneViewFamily& ViewFamily = *(View.Family); FIntRect SrcRect = View.ViewRect; // todo: view size should scale with input texture size so we can do SSAO in half resolution as well FIntRect DestRect = View.ViewRect; FIntPoint DestSize = DestRect.Size(); const bool bMixing = CVarLPVMixing.GetValueOnRenderThread() != 0; // Apply specular separately if we're mixing reflection environment with indirect lighting const bool bApplySeparateSpecularRT = View.Family->EngineShowFlags.ReflectionEnvironment && bMixing; const FSceneRenderTargetItem& DestColorRenderTarget = SceneContext.GetSceneColor()->GetRenderTargetItem(); const FSceneRenderTargetItem& DestSpecularRenderTarget = SceneContext.LightAccumulation->GetRenderTargetItem(); const FSceneRenderTargetItem& DestDirectionalOcclusionRenderTarget = SceneContext.DirectionalOcclusion->GetRenderTargetItem(); // Make sure the LPV Update has completed Lpv->InsertGPUWaitForAsyncUpdate(Context.RHICmdList); if ( LPVSettings.LPVDirectionalOcclusionIntensity > 0.0001f ) { DoDirectionalOcclusionPass(Context); } FTextureRHIParamRef RenderTargets[2]; RenderTargets[0] = DestColorRenderTarget.TargetableTexture; RenderTargets[1] = DestSpecularRenderTarget.TargetableTexture; // Set the view family's render target/viewport. // If specular not applied: set only color target uint32 NumRenderTargets = 1; if ( bApplySeparateSpecularRT ) { NumRenderTargets = 2; } SetRenderTargets(Context.RHICmdList, NumRenderTargets, RenderTargets, 0, ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilNop); Context.SetViewportAndCallRHI(View.ViewRect); // set the state Context.RHICmdList.SetBlendState(TStaticBlendState<CW_RGB,BO_Add,BF_One,BF_One,BO_Add,BF_One,BF_One>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI()); TShaderMapRef<FPostProcessVS> VertexShader(Context.GetShaderMap()); TShaderMapRef< TPostProcessLpvIndirectPS<false> > PixelShaderNoSpecular(Context.GetShaderMap()); TShaderMapRef< TPostProcessLpvIndirectPS<true> > PixelShaderWithSpecular(Context.GetShaderMap()); FPostProcessLpvIndirectPS* PixelShader = NULL; int BoundShaderIndex = -1; if ( bApplySeparateSpecularRT ) { PixelShader = (FPostProcessLpvIndirectPS*)*PixelShaderWithSpecular; BoundShaderIndex = 0; } else { PixelShader = (FPostProcessLpvIndirectPS*)*PixelShaderNoSpecular; BoundShaderIndex = 1; } static FGlobalBoundShaderState BoundShaderState[2]; // call it once after setting up the shader data to avoid the warnings in the function SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState[BoundShaderIndex], GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, PixelShader); FLpvReadUniformBufferParameters LpvReadUniformBufferParams; FLpvReadUniformBufferRef LpvReadUniformBuffer; LpvReadUniformBufferParams = Lpv->GetReadUniformBufferParams(); LpvReadUniformBuffer = FLpvReadUniformBufferRef::CreateUniformBufferImmediate( LpvReadUniformBufferParams, UniformBuffer_SingleDraw ); FTextureRHIParamRef LpvBufferSrvs[7]; for ( int i = 0; i < 7; i++ ) { LpvBufferSrvs[i] = Lpv->GetLpvBufferSrv(i); } PixelShader->SetParameters( LpvBufferSrvs, Lpv->GetAOVolumeTextureSRV(), LpvReadUniformBuffer, Context ); { SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessLpvIndirect ); DrawPostProcessPass( Context.RHICmdList, 0, 0, View.ViewRect.Width(), View.ViewRect.Height(), View.ViewRect.Min.X, View.ViewRect.Min.Y, View.ViewRect.Width(), View.ViewRect.Height(), View.ViewRect.Size(), SceneContext.GetBufferSizeXY(), *VertexShader, View.StereoPass, Context.HasHmdMesh()); Context.RHICmdList.CopyToResolveTarget(DestColorRenderTarget.TargetableTexture, DestColorRenderTarget.ShaderResourceTexture, false, FResolveParams()); if(bApplySeparateSpecularRT) { Context.RHICmdList.CopyToResolveTarget(DestSpecularRenderTarget.TargetableTexture, DestSpecularRenderTarget.ShaderResourceTexture, false, FResolveParams()); } } if ( LPVSettings.LPVDirectionalOcclusionIntensity > 0.0001f ) { GRenderTargetPool.VisualizeTexture.SetCheckPoint(Context.RHICmdList, SceneContext.DirectionalOcclusion); } }
void FRCPassPostProcessMotionBlurSetup::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, MotionBlurSetup); const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0); if(!InputDesc) { // input is not hooked up correctly return; } const FSceneView& View = Context.View; const FSceneViewFamily& ViewFamily = *(View.Family); FIntPoint SrcSize = InputDesc->Extent; FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent; // e.g. 4 means the input texture is 4x smaller than the buffer size uint32 ScaleFactor = GSceneRenderTargets.GetBufferSizeXY().X / SrcSize.X; FIntRect SrcRect = View.ViewRect / ScaleFactor; // Viewport size not even also causes issue FIntRect DestRect = FIntRect::DivideAndRoundUp(SrcRect, 2); const FSceneRenderTargetItem& DestRenderTarget0 = PassOutputs[0].RequestSurface(Context); const FSceneRenderTargetItem& DestRenderTarget1 = PassOutputs[1].RequestSurface(Context); // Set the view family's render target/viewport. FTextureRHIParamRef RenderTargets[] = { DestRenderTarget0.TargetableTexture, DestRenderTarget1.TargetableTexture }; SetRenderTargets(Context.RHICmdList, ARRAY_COUNT(RenderTargets), RenderTargets, FTextureRHIParamRef(), 0, NULL); // is optimized away if possible (RT size=view size, ) FLinearColor ClearColors[2] = {FLinearColor(0,0,0,0), FLinearColor(0,0,0,0)}; Context.RHICmdList.ClearMRT(true, 2, ClearColors, false, 1.0f, false, 0, DestRect); Context.SetViewportAndCallRHI(0, 0, 0.0f, DestSize.X, DestSize.Y, 1.0f ); // set the state Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); TShaderMapRef<FPostProcessMotionBlurSetupVS> VertexShader(Context.GetShaderMap()); { TShaderMapRef<FPostProcessMotionBlurSetupPS > PixelShader(Context.GetShaderMap()); static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetParameters(Context); VertexShader->SetParameters(Context); } // Draw a quad mapping scene color to the view's render target DrawRectangle( Context.RHICmdList, DestRect.Min.X, DestRect.Min.Y, DestRect.Width(), DestRect.Height(), SrcRect.Min.X, SrcRect.Min.Y, SrcRect.Width(), SrcRect.Height(), DestSize, SrcSize, *VertexShader, EDRF_UseTriangleOptimization); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget0.TargetableTexture, DestRenderTarget0.ShaderResourceTexture, false, FResolveParams()); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget1.TargetableTexture, DestRenderTarget1.ShaderResourceTexture, false, FResolveParams()); }
void ImageBasedLensFlare::LensBlur(const Ptr<Texture> & setupTex, const Ptr<Texture> & target) { int32_t tileSize = 9; //Extract Sprite Points int32_t extractWidth = (setupTex->GetDesc().width + tileSize - 1) / tileSize; int32_t extractHeight = (setupTex->GetDesc().height + tileSize - 1) / tileSize; RenderBufferDesc spPointsBufDesc; spPointsBufDesc.bindFlag = BUFFER_BIND_SHADER_RESOURCE | BUFFER_BIND_UNORDERED_ACCESS; spPointsBufDesc.elementSize = sizeof(float2) + sizeof(float3); spPointsBufDesc.numElements = extractWidth * extractHeight; spPointsBufDesc.cpuAccess = 0; spPointsBufDesc.bStructured = true; auto spPointsBufRef = BufferPool::Instance().FindFree(spPointsBufDesc); auto spPointsBuf = spPointsBufRef->Get()->Cast<RenderBuffer>(); { auto ps = Shader::FindOrCreate<ExtractSpritePointsPS>(); ps->SetScalar("spriteThreshold", _spriteThreshold); ps->SetSRV("setupTex", setupTex->GetShaderResourceView()); ps->SetUAV("spPointsBuf", spPointsBuf->GetUnorderedAccessView(0, 0, RENDER_FORMAT_UNKNOWN, BUFFER_UAV_APPEND)); ps->Flush(); DrawQuad({}, 0.0f, 0.0f, (float)extractWidth, (float)extractHeight); } //Render Sprites if (!_indirectAgsBuf) { RenderBufferDesc indirectArgsBufDesc; indirectArgsBufDesc.bindFlag = BUFFER_BIND_INDIRECT_ARGS; indirectArgsBufDesc.elementSize = 16; indirectArgsBufDesc.numElements = 1; indirectArgsBufDesc.cpuAccess = 0; indirectArgsBufDesc.bStructured = false; uint32_t initData[] = { 0, 1, 0, 0 }; _indirectAgsBuf = Global::GetRenderEngine()->GetRenderFactory()->CreateBuffer(); _indirectAgsBuf->SetDesc(indirectArgsBufDesc); _indirectAgsBuf->Init(initData); } spPointsBuf->CopyStructureCountTo(_indirectAgsBuf, 0, 0, spPointsBuf->GetDesc().numElements, RENDER_FORMAT_UNKNOWN, BUFFER_UAV_APPEND); { auto vs = Shader::FindOrCreate<LensBlurVS>(); auto gs = Shader::FindOrCreate<LensBlurGS>(); auto ps = Shader::FindOrCreate<LensBlurPS>(); vs->SetScalar("texSize", target->GetTexSize()); gs->SetScalar("texSize", target->GetTexSize()); gs->SetScalar("flareIntensity", _flareIntensity); vs->SetSRV("spPointsRenderBuf", spPointsBuf->GetShaderResourceView(0, 0, RENDER_FORMAT_UNKNOWN)); auto lensTexAsset = Asset::Find<TextureAsset>("Textures/Bokeh_Circle.dds"); if (!lensTexAsset->IsInit()) lensTexAsset->Init(); auto lensTex = lensTexAsset->GetTexture(); ps->SetSRV("lensTex", lensTex->GetShaderResourceView()); ps->SetSampler("linearSampler", SamplerTemplate<>::Get()); vs->Flush(); gs->Flush(); ps->Flush(); auto rc = Global::GetRenderEngine()->GetRenderContext(); rc->SetVertexBuffer({}); rc->SetIndexBuffer(nullptr); rc->SetPrimitiveTopology(PRIMITIVE_TOPOLOGY_POINTLIST); rc->SetViewport(GetTextureQuadViewport(target)); rc->SetRenderTargets({ target->GetRenderTargetView(0, 0, 1) }); rc->SetDepthStencil(nullptr); rc->SetDepthStencilState(DepthStencilStateTemplate<false>::Get()); rc->SetBlendState(BlendStateTemplate<false, false, true, BLEND_PARAM_SRC_ALPHA, BLEND_PARAM_ONE, BLEND_OP_ADD>::Get()); rc->DrawInstancedIndirect(_indirectAgsBuf, 0); rc->ResetShader(SHADER_GS); rc->SetBlendState(nullptr); } }
void FRCPassPostProcessDeferredDecals::Process(FRenderingCompositePassContext& Context) { FRHICommandListImmediate& RHICmdList = Context.RHICmdList; const bool bShaderComplexity = Context.View.Family->EngineShowFlags.ShaderComplexity; const bool bDBuffer = IsDBufferEnabled(); const bool bStencilSizeThreshold = CVarStencilSizeThreshold.GetValueOnRenderThread() >= 0; SCOPED_DRAW_EVENT(RHICmdList, PostProcessDeferredDecals); if(RenderStage == 0) { // before BasePass, only if DBuffer is enabled check(bDBuffer); // DBuffer: Decal buffer FPooledRenderTargetDesc Desc(FPooledRenderTargetDesc::Create2DDesc(GSceneRenderTargets.GBufferA->GetDesc().Extent, PF_B8G8R8A8, TexCreate_None, TexCreate_ShaderResource | TexCreate_RenderTargetable, false)); if(!GSceneRenderTargets.DBufferA) { GRenderTargetPool.FindFreeElement(Desc, GSceneRenderTargets.DBufferA, TEXT("DBufferA")); } if(!GSceneRenderTargets.DBufferB) { GRenderTargetPool.FindFreeElement(Desc, GSceneRenderTargets.DBufferB, TEXT("DBufferB")); } Desc.Format = PF_R8G8; if(!GSceneRenderTargets.DBufferC) { GRenderTargetPool.FindFreeElement(Desc, GSceneRenderTargets.DBufferC, TEXT("DBufferC")); } // we assume views are non overlapping, then we need to clear only once in the beginning, otherwise we would need to set scissor rects // and don't get FastClear any more. bool bFirstView = Context.View.Family->Views[0] == &Context.View; if(bFirstView) { SCOPED_DRAW_EVENT(RHICmdList, DBufferClear); // could be optimized SetRenderTarget(RHICmdList, GSceneRenderTargets.DBufferA->GetRenderTargetItem().TargetableTexture, FTextureRHIParamRef()); RHICmdList.Clear(true, FLinearColor(0, 0, 0, 1), false, (float)ERHIZBuffer::FarPlane, false, 0, FIntRect()); SetRenderTarget(RHICmdList, GSceneRenderTargets.DBufferB->GetRenderTargetItem().TargetableTexture, FTextureRHIParamRef()); // todo: some hardware would like to have 0 or 1 for faster clear, we chose 128/255 to represent 0 (8 bit cannot represent 0.5f) RHICmdList.Clear(true, FLinearColor(128.0f / 255.0f, 128.0f / 255.0f, 128.0f / 255.0f, 1), false, (float)ERHIZBuffer::FarPlane, false, 0, FIntRect()); SetRenderTarget(RHICmdList, GSceneRenderTargets.DBufferC->GetRenderTargetItem().TargetableTexture, FTextureRHIParamRef()); // R:roughness, G:roughness opacity RHICmdList.Clear(true, FLinearColor(0, 1, 0, 1), false, (float)ERHIZBuffer::FarPlane, false, 0, FIntRect()); } } // this cast is safe as only the dedicated server implements this differently and this pass should not be executed on the dedicated server const FViewInfo& View = Context.View; const FSceneViewFamily& ViewFamily = *(View.Family); FScene& Scene = *(FScene*)ViewFamily.Scene; if(!Scene.Decals.Num()) { // to avoid the stats showing up return; } TArray<FTransientDecalRenderData, SceneRenderingAllocator> SortedDecals; SortedDecals.Empty(Scene.Decals.Num()); // Build a list of decals that need to be rendered for this view in SortedDecals for (TSparseArray<FDeferredDecalProxy*>::TConstIterator It(Scene.Decals); It; ++It) { FDeferredDecalProxy* DecalProxy = *It; bool bIsShown = true; // Handle the decal actor having bHidden set when we are in the editor, in G mode #if WITH_EDITOR if (View.Family->EngineShowFlags.Editor) #endif { if (!DecalProxy->DrawInGame) { bIsShown = false; } } const FMatrix ComponentToWorldMatrix = DecalProxy->ComponentTrans.ToMatrixWithScale(); // can be optimized as we test against a sphere around the box instead of the box itself const float ConservativeRadius = FMath::Sqrt( ComponentToWorldMatrix.GetScaledAxis( EAxis::X ).SizeSquared() * FMath::Square(GDefaultDecalSize.X) + ComponentToWorldMatrix.GetScaledAxis( EAxis::Y ).SizeSquared() * FMath::Square(GDefaultDecalSize.Y) + ComponentToWorldMatrix.GetScaledAxis( EAxis::Z ).SizeSquared() * FMath::Square(GDefaultDecalSize.Z)); // can be optimized as the test is too conservative (sphere instead of OBB) if(ConservativeRadius < SMALL_NUMBER || !View.ViewFrustum.IntersectSphere(ComponentToWorldMatrix.GetOrigin(), ConservativeRadius)) { bIsShown = false; } if (bIsShown) { FTransientDecalRenderData Data(Scene, DecalProxy); uint32 DecalRenderStage = ComputeRenderStage(Data.DecalBlendMode); // we could do this test earlier to avoid the decal intersection but getting DecalBlendMode also costs if (Context.View.Family->EngineShowFlags.ShaderComplexity || RenderStage == DecalRenderStage) { SortedDecals.Add(Data); } } } if(SortedDecals.Num() > 0) { FIntRect SrcRect = View.ViewRect; FIntRect DestRect = View.ViewRect; bool bStencilDecals = true; #if DBUFFER_DONT_USE_STENCIL_YET if(RenderStage == 0) { bStencilDecals = false; } #endif // Setup a stencil mask to prevent certain pixels from receiving deferred decals if(bStencilDecals) { StencilDecalMask(RHICmdList, View); } // Sort by sort order to allow control over composited result // Then sort decals by state to reduce render target switches // Also sort by component since Sort() is not stable struct FCompareFTransientDecalRenderData { FORCEINLINE bool operator()( const FTransientDecalRenderData& A, const FTransientDecalRenderData& B ) const { if (B.DecalProxy->SortOrder != A.DecalProxy->SortOrder) { return A.DecalProxy->SortOrder < B.DecalProxy->SortOrder; } if (B.DecalBlendMode != A.DecalBlendMode) { return (int32)B.DecalBlendMode < (int32)A.DecalBlendMode; } if (B.bHasNormal != A.bHasNormal) { return B.bHasNormal < A.bHasNormal; } // Batch decals with the same material together if (B.MaterialProxy != A.MaterialProxy ) { return B.MaterialProxy < A.MaterialProxy; } return (PTRINT)B.DecalProxy->Component < (PTRINT)A.DecalProxy->Component; } }; // Sort decals by blend mode to reduce render target switches SortedDecals.Sort( FCompareFTransientDecalRenderData() ); // optimization to have less state changes int32 LastDecalBlendMode = -1; int32 LastDecalHasNormal = -1; // Decal state can change based on its normal property.(SM5) ERenderTargetMode LastRenderTargetMode = RTM_Unknown; int32 WasInsideDecal = -1; const ERHIFeatureLevel::Type SMFeatureLevel = Context.GetFeatureLevel(); SCOPED_DRAW_EVENT(RHICmdList, Decals); INC_DWORD_STAT_BY(STAT_Decals, SortedDecals.Num()); enum EDecalResolveBufferIndex { SceneColorIndex, GBufferAIndex, GBufferBIndex, GBufferCIndex, DBufferAIndex, DBufferBIndex, DBufferCIndex, ResolveBufferMax, }; FTextureRHIParamRef TargetsToResolve[ResolveBufferMax] = { nullptr }; for (int32 DecalIndex = 0, DecalCount = SortedDecals.Num(); DecalIndex < DecalCount; DecalIndex++) { const FTransientDecalRenderData& DecalData = SortedDecals[DecalIndex]; const FDeferredDecalProxy& DecalProxy = *DecalData.DecalProxy; const FMatrix ComponentToWorldMatrix = DecalProxy.ComponentTrans.ToMatrixWithScale(); // Set vertex shader params const FMaterialShaderMap* MaterialShaderMap = DecalData.MaterialResource->GetRenderingThreadShaderMap(); FScaleMatrix DecalScaleTransform(GDefaultDecalSize); FTranslationMatrix PreViewTranslation(View.ViewMatrices.PreViewTranslation); FMatrix FrustumComponentToClip = DecalScaleTransform * ComponentToWorldMatrix * PreViewTranslation * View.ViewMatrices.TranslatedViewProjectionMatrix; // can be optimized as we test against a sphere around the box instead of the box itself const float ConservativeRadius = FMath::Sqrt( ComponentToWorldMatrix.GetScaledAxis( EAxis::X ).SizeSquared() * FMath::Square(GDefaultDecalSize.X) + ComponentToWorldMatrix.GetScaledAxis( EAxis::Y ).SizeSquared() * FMath::Square(GDefaultDecalSize.Y) + ComponentToWorldMatrix.GetScaledAxis( EAxis::Z ).SizeSquared() * FMath::Square(GDefaultDecalSize.Z)); EDecalBlendMode DecalBlendMode = DecalData.DecalBlendMode; bool bStencilThisDecal = bStencilDecals; #if DBUFFER_DONT_USE_STENCIL_YET if(ComputeRenderStage(DecalBlendMode) == 0) { bStencilThisDecal = false; } #endif ERenderTargetMode CurrentRenderTargetMode = ComputeRenderTargetMode(DecalBlendMode); if(bShaderComplexity) { CurrentRenderTargetMode = RTM_SceneColor; // we want additive blending for the ShaderComplexity mode DecalBlendMode = DBM_Emissive; } // fewer rendertarget switches if possible if(CurrentRenderTargetMode != LastRenderTargetMode) { LastRenderTargetMode = CurrentRenderTargetMode; switch(CurrentRenderTargetMode) { case RTM_SceneColorAndGBuffer: { TargetsToResolve[SceneColorIndex] = GSceneRenderTargets.GetSceneColor()->GetRenderTargetItem().TargetableTexture; TargetsToResolve[GBufferAIndex] = GSceneRenderTargets.GBufferA->GetRenderTargetItem().TargetableTexture; TargetsToResolve[GBufferBIndex] = GSceneRenderTargets.GBufferB->GetRenderTargetItem().TargetableTexture; TargetsToResolve[GBufferCIndex] = GSceneRenderTargets.GBufferC->GetRenderTargetItem().TargetableTexture; SetRenderTargets(RHICmdList, 4, TargetsToResolve, GSceneRenderTargets.GetSceneDepthSurface(), ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite); } break; case RTM_GBufferNormal: TargetsToResolve[GBufferAIndex] = GSceneRenderTargets.GBufferA->GetRenderTargetItem().TargetableTexture; SetRenderTarget(RHICmdList, TargetsToResolve[GBufferAIndex], GSceneRenderTargets.GetSceneDepthSurface(), ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite); break; case RTM_SceneColor: TargetsToResolve[SceneColorIndex] = GSceneRenderTargets.GetSceneColor()->GetRenderTargetItem().TargetableTexture; SetRenderTarget(RHICmdList, TargetsToResolve[SceneColorIndex], GSceneRenderTargets.GetSceneDepthSurface(), ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite); break; case RTM_DBuffer: { TargetsToResolve[DBufferAIndex] = GSceneRenderTargets.DBufferA->GetRenderTargetItem().TargetableTexture; TargetsToResolve[DBufferBIndex] = GSceneRenderTargets.DBufferB->GetRenderTargetItem().TargetableTexture; TargetsToResolve[DBufferCIndex] = GSceneRenderTargets.DBufferC->GetRenderTargetItem().TargetableTexture; SetRenderTargets(RHICmdList, 3, &TargetsToResolve[DBufferAIndex], GSceneRenderTargets.GetSceneDepthSurface(), ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite); } break; default: check(0); break; } Context.SetViewportAndCallRHI(DestRect); // we need to reset the stream source after any call to SetRenderTarget (at least for Metal, which doesn't queue up VB assignments) RHICmdList.SetStreamSource(0, GUnitCubeVertexBuffer.VertexBufferRHI, sizeof(FVector4), 0); } bool bThisDecalUsesStencil = false; if (bStencilThisDecal) { if (bStencilSizeThreshold) { // note this is after a SetStreamSource (in if CurrentRenderTargetMode != LastRenderTargetMode) call as it needs to get the VB input bThisDecalUsesStencil = RenderPreStencil(Context, MaterialShaderMap, ComponentToWorldMatrix, FrustumComponentToClip); WasInsideDecal = -1; LastDecalBlendMode = -1; } } const bool bBlendStateChange = DecalBlendMode != LastDecalBlendMode;// Has decal mode changed. const bool bDecalNormalChanged = GSupportsSeparateRenderTargetBlendState && // has normal changed for SM5 stain/translucent decals? (DecalBlendMode == DBM_Translucent || DecalBlendMode == DBM_Stain) && (int32)DecalData.bHasNormal != LastDecalHasNormal; // fewer blend state changes if possible if (bBlendStateChange || bDecalNormalChanged) { LastDecalBlendMode = DecalBlendMode; LastDecalHasNormal = (int32)DecalData.bHasNormal; SetDecalBlendState(RHICmdList, SMFeatureLevel, RenderStage, (EDecalBlendMode)LastDecalBlendMode, DecalData.bHasNormal); } { TShaderMapRef<FDeferredDecalVS> VertexShader(Context.GetShaderMap()); SetShader(Context, bShaderComplexity, DecalData, *VertexShader); VertexShader->SetParameters(RHICmdList, View, FrustumComponentToClip); const int32 IsInsideDecal = ((FVector)View.ViewMatrices.ViewOrigin - ComponentToWorldMatrix.GetOrigin()).SizeSquared() < FMath::Square(ConservativeRadius * 1.05f + View.NearClippingDistance * 2.0f) + ( bThisDecalUsesStencil ) ? 2 : 0; if ( WasInsideDecal != IsInsideDecal ) { WasInsideDecal = IsInsideDecal; if ( !(IsInsideDecal & 1) ) { // Render backfaces with depth tests disabled since the camera is inside (or close to inside) the light function geometry RHICmdList.SetRasterizerState(View.bReverseCulling ? TStaticRasterizerState<FM_Solid, CM_CCW>::GetRHI() : TStaticRasterizerState<FM_Solid, CM_CW>::GetRHI()); if(bStencilDecals) { // Enable stencil testing, only write to pixels with stencil of 0 if ( bThisDecalUsesStencil ) { RHICmdList.SetDepthStencilState(TStaticDepthStencilState< false,CF_Always, true,CF_Equal,SO_Zero,SO_Zero,SO_Zero, true,CF_Equal,SO_Zero,SO_Zero,SO_Zero, 0xff, 0x7f >::GetRHI(), 1); } else { RHICmdList.SetDepthStencilState(TStaticDepthStencilState< false,CF_Always, true,CF_Equal,SO_Keep,SO_Keep,SO_Keep, false,CF_Always,SO_Keep,SO_Keep,SO_Keep, 0x80,0x00>::GetRHI(), 0); } } else { RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always, true>::GetRHI(), 0); } } else { // Render frontfaces with depth tests on to get the speedup from HiZ since the camera is outside the light function geometry if(bStencilDecals) { // Render frontfaces with depth tests on to get the speedup from HiZ since the camera is outside the light function geometry // Enable stencil testing, only write to pixels with stencil of 0 if ( bThisDecalUsesStencil ) { RHICmdList.SetDepthStencilState(TStaticDepthStencilState< false,CF_DepthNearOrEqual, true,CF_Equal,SO_Zero,SO_Zero,SO_Zero, true,CF_Equal,SO_Zero,SO_Zero,SO_Zero, 0xff, 0x7f >::GetRHI(), 1); } else { RHICmdList.SetDepthStencilState(TStaticDepthStencilState< false,CF_DepthNearOrEqual, true,CF_Equal,SO_Keep,SO_Keep,SO_Keep, false,CF_Always,SO_Keep,SO_Keep,SO_Keep, 0x80,0x00>::GetRHI(), 0); } RHICmdList.SetRasterizerState(View.bReverseCulling ? TStaticRasterizerState<FM_Solid, CM_CW>::GetRHI() : TStaticRasterizerState<FM_Solid, CM_CCW>::GetRHI()); } else { RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_DepthNearOrEqual>::GetRHI(), 0); } RHICmdList.SetRasterizerState(View.bReverseCulling ? TStaticRasterizerState<FM_Solid, CM_CW>::GetRHI() : TStaticRasterizerState<FM_Solid, CM_CCW>::GetRHI()); } } RHICmdList.DrawIndexedPrimitive(GUnitCubeIndexBuffer.IndexBufferRHI, PT_TriangleList, 0, 0, 8, 0, GUnitCubeIndexBuffer.GetIndexCount() / 3, 1); } } // we don't modify stencil but if out input was having stencil for us (after base pass - we need to clear) // Clear stencil to 0, which is the assumed default by other passes RHICmdList.Clear(false, FLinearColor::White, false, (float)ERHIZBuffer::FarPlane, true, 0, FIntRect()); // resolve the targets we wrote to. FResolveParams ResolveParams; for (int32 i = 0; i < ResolveBufferMax; ++i) { if (TargetsToResolve[i]) { RHICmdList.CopyToResolveTarget(TargetsToResolve[i], TargetsToResolve[i], true, ResolveParams); } } } if(RenderStage == 0) { // before BasePass GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, GSceneRenderTargets.DBufferA); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, GSceneRenderTargets.DBufferB); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, GSceneRenderTargets.DBufferC); } }