You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
- Decals materials are evaluated using callable shaders in PathTracingKernel. - Decals are culled using a 2D grid similar to the existing light grid. - In order to correctly handle decal blending order, decals are sorted using the same logic as the rasterizer on CPU. The compute shader that builds the decal grid maintains the correct order. - Decal materials are wrapped in FRayTracingDecalMaterialShader. The instance parameters of each decal are bound using uniform buffers. #preflight 628f3fed2f2409bc1e7a6414 #rb Yuriy.ODonnell, chris.kulla, Jeremy.Moore [CL 20377336 by tiago costa in ue5-main branch]
117 lines
5.1 KiB
C++
117 lines
5.1 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
MobileDecalRendering.cpp: Decals for mobile renderer
|
|
=============================================================================*/
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "Stats/Stats.h"
|
|
#include "RHIDefinitions.h"
|
|
#include "RHI.h"
|
|
#include "SceneUtils.h"
|
|
#include "RHIStaticStates.h"
|
|
#include "PostProcess/SceneRenderTargets.h"
|
|
#include "SceneRendering.h"
|
|
#include "ScenePrivate.h"
|
|
#include "DecalRenderingCommon.h"
|
|
#include "DecalRenderingShared.h"
|
|
|
|
void RenderMeshDecalsMobile(FRHICommandListImmediate& RHICmdList, const FViewInfo& View, EDecalRenderStage DecalRenderStage, EDecalRenderTargetMode RenderTargetMode);
|
|
extern void RenderDeferredDecalsMobile(FRHICommandListImmediate& RHICmdList, const FScene& Scene, const FViewInfo& View, EDecalRenderStage DecalRenderStage, EDecalRenderTargetMode RenderTargetMode);
|
|
|
|
void FMobileSceneRenderer::RenderDecals(FRHICommandListImmediate& RHICmdList, const FViewInfo& View)
|
|
{
|
|
if (!IsMobileHDR() || !ActiveViewFamily->EngineShowFlags.Decals || View.bIsPlanarReflection)
|
|
{
|
|
return;
|
|
}
|
|
|
|
CSV_SCOPED_TIMING_STAT_EXCLUSIVE(RenderDecals);
|
|
SCOPE_CYCLE_COUNTER(STAT_DecalsDrawTime);
|
|
|
|
const bool bIsMobileDeferred = IsMobileDeferredShadingEnabled(View.GetShaderPlatform());
|
|
const EDecalRenderStage DecalRenderStage = bIsMobileDeferred ? EDecalRenderStage::MobileBeforeLighting : EDecalRenderStage::Mobile;
|
|
const EDecalRenderTargetMode RenderTargetMode = bIsMobileDeferred ? EDecalRenderTargetMode::SceneColorAndGBuffer : EDecalRenderTargetMode::SceneColor;
|
|
|
|
// Deferred decals
|
|
if (Scene->Decals.Num() > 0)
|
|
{
|
|
SCOPED_DRAW_EVENT(RHICmdList, Decals);
|
|
RenderDeferredDecalsMobile(RHICmdList, *Scene, View, DecalRenderStage, RenderTargetMode);
|
|
}
|
|
|
|
// Mesh decals
|
|
if (View.MeshDecalBatches.Num() > 0)
|
|
{
|
|
SCOPED_DRAW_EVENT(RHICmdList, MeshDecals);
|
|
RenderMeshDecalsMobile(RHICmdList, View, DecalRenderStage, RenderTargetMode);
|
|
}
|
|
}
|
|
|
|
void RenderDeferredDecalsMobile(FRHICommandListImmediate& RHICmdList, const FScene& Scene, const FViewInfo& View, EDecalRenderStage DecalRenderStage, EDecalRenderTargetMode RenderTargetMode)
|
|
{
|
|
const uint32 DecalCount = Scene.Decals.Num();
|
|
int32 SortedDecalCount = 0;
|
|
FTransientDecalRenderDataList SortedDecals;
|
|
|
|
if (DecalCount > 0)
|
|
{
|
|
// Build a list of decals that need to be rendered for this view
|
|
DecalRendering::BuildVisibleDecalList(Scene, View, DecalRenderStage, &SortedDecals);
|
|
SortedDecalCount = SortedDecals.Num();
|
|
INC_DWORD_STAT_BY(STAT_Decals, SortedDecalCount);
|
|
}
|
|
|
|
if (SortedDecalCount > 0)
|
|
{
|
|
FGraphicsPipelineStateInitializer GraphicsPSOInit;
|
|
RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit);
|
|
|
|
RHICmdList.SetViewport(View.ViewRect.Min.X, View.ViewRect.Min.Y, 0, View.ViewRect.Max.X, View.ViewRect.Max.Y, 1);
|
|
RHICmdList.SetStreamSource(0, GetUnitCubeVertexBuffer(), 0);
|
|
|
|
for (int32 DecalIndex = 0; DecalIndex < SortedDecalCount; DecalIndex++)
|
|
{
|
|
const FTransientDecalRenderData& DecalData = SortedDecals[DecalIndex];
|
|
const FDeferredDecalProxy& DecalProxy = DecalData.Proxy;
|
|
const FMatrix ComponentToWorldMatrix = DecalProxy.ComponentTrans.ToMatrixWithScale();
|
|
const FMatrix FrustumComponentToClip = DecalRendering::ComputeComponentToClipMatrix(View, ComponentToWorldMatrix);
|
|
|
|
const float ConservativeRadius = DecalData.ConservativeRadius;
|
|
const bool bInsideDecal = ((FVector)View.ViewMatrices.GetViewOrigin() - ComponentToWorldMatrix.GetOrigin()).SizeSquared() < FMath::Square(ConservativeRadius * 1.05f + View.NearClippingDistance * 2.0f);
|
|
bool bReverseHanded = false;
|
|
{
|
|
// Account for the reversal of handedness caused by negative scale on the decal
|
|
const auto& Scale3d = DecalProxy.ComponentTrans.GetScale3D();
|
|
bReverseHanded = Scale3d[0] * Scale3d[1] * Scale3d[2] < 0.f;
|
|
}
|
|
EDecalRasterizerState DecalRasterizerState = DecalRendering::GetDecalRasterizerState(bInsideDecal, bReverseHanded, View.bReverseCulling);
|
|
GraphicsPSOInit.RasterizerState = DecalRendering::GetDecalRasterizerState(DecalRasterizerState);
|
|
|
|
if (bInsideDecal)
|
|
{
|
|
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<
|
|
false, CF_Always,
|
|
true, CF_Equal, SO_Keep, SO_Keep, SO_Keep,
|
|
false, CF_Always, SO_Keep, SO_Keep, SO_Keep,
|
|
GET_STENCIL_BIT_MASK(RECEIVE_DECAL, 1), 0x00>::GetRHI();
|
|
}
|
|
else
|
|
{
|
|
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<
|
|
false, CF_DepthNearOrEqual,
|
|
true, CF_Equal, SO_Keep, SO_Keep, SO_Keep,
|
|
false, CF_Always, SO_Keep, SO_Keep, SO_Keep,
|
|
GET_STENCIL_BIT_MASK(RECEIVE_DECAL, 1), 0x00>::GetRHI();
|
|
}
|
|
|
|
GraphicsPSOInit.BlendState = DecalRendering::GetDecalBlendState(DecalData.BlendDesc, DecalRenderStage, RenderTargetMode);
|
|
|
|
// Set shader params
|
|
DecalRendering::SetShader(RHICmdList, GraphicsPSOInit, 0, View, DecalData, DecalRenderStage, FrustumComponentToClip);
|
|
|
|
RHICmdList.DrawIndexedPrimitive(GetUnitCubeIndexBuffer(), 0, 0, 8, 0, UE_ARRAY_COUNT(GCubeIndices) / 3, 1);
|
|
}
|
|
}
|
|
}
|