You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
437 lines
18 KiB
C++
437 lines
18 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
DecalRenderingShared.cpp
|
|
=============================================================================*/
|
|
|
|
#include "DecalRenderingShared.h"
|
|
#include "StaticBoundShaderState.h"
|
|
#include "Components/DecalComponent.h"
|
|
#include "GlobalShader.h"
|
|
#include "MaterialShaderType.h"
|
|
#include "MaterialShader.h"
|
|
#include "DebugViewModeRendering.h"
|
|
#include "ScenePrivate.h"
|
|
#include "PipelineStateCache.h"
|
|
|
|
static TAutoConsoleVariable<float> CVarDecalFadeScreenSizeMultiplier(
|
|
TEXT("r.Decal.FadeScreenSizeMult"),
|
|
1.0f,
|
|
TEXT("Control the per decal fade screen size. Multiplies with the per-decal screen size fade threshold.")
|
|
TEXT(" Smaller means decals fade less aggressively.")
|
|
);
|
|
|
|
FTransientDecalRenderData::FTransientDecalRenderData(const FScene& InScene, const FDeferredDecalProxy* InDecalProxy, float InConservativeRadius)
|
|
: DecalProxy(InDecalProxy)
|
|
, FadeAlpha(1.0f)
|
|
, ConservativeRadius(InConservativeRadius)
|
|
{
|
|
MaterialProxy = InDecalProxy->DecalMaterial->GetRenderProxy();
|
|
MaterialResource = &MaterialProxy->GetMaterialWithFallback(InScene.GetFeatureLevel(), MaterialProxy);
|
|
check(MaterialProxy && MaterialResource);
|
|
DecalBlendDesc = DecalRendering::ComputeDecalBlendDesc(InScene.GetShaderPlatform(), MaterialResource);
|
|
}
|
|
|
|
/**
|
|
* A vertex shader for projecting a deferred decal onto the scene.
|
|
*/
|
|
class FDeferredDecalVS : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FDeferredDecalVS,Global);
|
|
public:
|
|
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
FDeferredDecalVS( ) { }
|
|
FDeferredDecalVS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
FrustumComponentToClip.Bind(Initializer.ParameterMap, TEXT("FrustumComponentToClip"));
|
|
}
|
|
|
|
void SetParameters(FRHICommandList& RHICmdList, const FMatrix44f& InFrustumComponentToClip)
|
|
{
|
|
FRHIVertexShader* ShaderRHI = RHICmdList.GetBoundVertexShader();
|
|
SetShaderValue(RHICmdList, ShaderRHI, FrustumComponentToClip, InFrustumComponentToClip);
|
|
}
|
|
|
|
private:
|
|
LAYOUT_FIELD(FShaderParameter, FrustumComponentToClip);
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FDeferredDecalVS,TEXT("/Engine/Private/DeferredDecal.usf"),TEXT("MainVS"),SF_Vertex);
|
|
|
|
/**
|
|
* A pixel shader for projecting a deferred decal onto the scene.
|
|
*/
|
|
class FDeferredDecalPS : public FMaterialShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FDeferredDecalPS,Material);
|
|
|
|
public:
|
|
static bool ShouldCompilePermutation(const FMaterialShaderPermutationParameters& Parameters)
|
|
{
|
|
return (Parameters.MaterialParameters.MaterialDomain == MD_DeferredDecal) &&
|
|
DecalRendering::GetBaseRenderStage(DecalRendering::ComputeDecalBlendDesc(Parameters.Platform, Parameters.MaterialParameters)) != EDecalRenderStage::None;
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(const FMaterialShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FMaterialShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
DecalRendering::ModifyCompilationEnvironment(DecalRendering::ComputeDecalBlendDesc(Parameters.Platform, Parameters.MaterialParameters), EDecalRenderStage::None, OutEnvironment);
|
|
}
|
|
|
|
FDeferredDecalPS() {}
|
|
FDeferredDecalPS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FMaterialShader(Initializer)
|
|
{
|
|
SvPositionToDecal.Bind(Initializer.ParameterMap,TEXT("SvPositionToDecal"));
|
|
DecalToWorld.Bind(Initializer.ParameterMap,TEXT("DecalToWorld"));
|
|
WorldToDecal.Bind(Initializer.ParameterMap,TEXT("WorldToDecal"));
|
|
DecalOrientation.Bind(Initializer.ParameterMap,TEXT("DecalOrientation"));
|
|
DecalParams.Bind(Initializer.ParameterMap, TEXT("DecalParams"));
|
|
}
|
|
|
|
void SetParameters(FRHICommandList& RHICmdList, const FViewInfo& View, const FMaterialRenderProxy* MaterialProxy, const FDeferredDecalProxy& DecalProxy, const float FadeAlphaValue=1.0f)
|
|
{
|
|
FRHIPixelShader* ShaderRHI = RHICmdList.GetBoundPixelShader();
|
|
|
|
const FMaterialRenderProxy* MaterialProxyForRendering = MaterialProxy;
|
|
const FMaterial& Material = MaterialProxy->GetMaterialWithFallback(View.GetFeatureLevel(), MaterialProxyForRendering);
|
|
FMaterialShader::SetParameters(RHICmdList, ShaderRHI, MaterialProxyForRendering, Material, View);
|
|
|
|
FTransform ComponentTrans = DecalProxy.ComponentTrans;
|
|
|
|
FMatrix44f WorldToComponent = ComponentTrans.ToInverseMatrixWithScale();
|
|
|
|
// Set the transform from screen space to light space.
|
|
if(SvPositionToDecal.IsBound())
|
|
{
|
|
FVector2D InvViewSize = FVector2D(1.0f / View.ViewRect.Width(), 1.0f / View.ViewRect.Height());
|
|
|
|
// setup a matrix to transform float4(SvPosition.xyz,1) directly to Decal (quality, performance as we don't need to convert or use interpolator)
|
|
|
|
// new_xy = (xy - ViewRectMin.xy) * ViewSizeAndInvSize.zw * float2(2,-2) + float2(-1, 1);
|
|
|
|
// transformed into one MAD: new_xy = xy * ViewSizeAndInvSize.zw * float2(2,-2) + (-ViewRectMin.xy) * ViewSizeAndInvSize.zw * float2(2,-2) + float2(-1, 1);
|
|
|
|
float Mx = 2.0f * InvViewSize.X;
|
|
float My = -2.0f * InvViewSize.Y;
|
|
float Ax = -1.0f - 2.0f * View.ViewRect.Min.X * InvViewSize.X;
|
|
float Ay = 1.0f + 2.0f * View.ViewRect.Min.Y * InvViewSize.Y;
|
|
|
|
// todo: we could use InvTranslatedViewProjectionMatrix and TranslatedWorldToComponent for better quality
|
|
const FMatrix44f SvPositionToDecalValue =
|
|
FMatrix(
|
|
FPlane(Mx, 0, 0, 0),
|
|
FPlane( 0, My, 0, 0),
|
|
FPlane( 0, 0, 1, 0),
|
|
FPlane(Ax, Ay, 0, 1)
|
|
) * View.ViewMatrices.GetInvViewProjectionMatrix() * WorldToComponent;
|
|
|
|
SetShaderValue(RHICmdList, ShaderRHI, SvPositionToDecal, SvPositionToDecalValue);
|
|
}
|
|
|
|
// Set the transform from light space to world space
|
|
if(DecalToWorld.IsBound())
|
|
{
|
|
const FMatrix44f DecalToWorldValue = ComponentTrans.ToMatrixWithScale();
|
|
|
|
SetShaderValue(RHICmdList, ShaderRHI, DecalToWorld, DecalToWorldValue);
|
|
}
|
|
|
|
SetShaderValue(RHICmdList, ShaderRHI, WorldToDecal, WorldToComponent);
|
|
|
|
if (DecalOrientation.IsBound())
|
|
{
|
|
// can get DecalOrientation form DecalToWorld matrix, but it will require binding whole matrix and normalizing axis in the shader
|
|
SetShaderValue(RHICmdList, ShaderRHI, DecalOrientation, FVector3f(ComponentTrans.GetUnitAxis(EAxis::X)));
|
|
}
|
|
|
|
float LifetimeAlpha = 1.0f;
|
|
|
|
// Certain engine captures (e.g. environment reflection) don't have a tick. Default to fully opaque.
|
|
if (View.Family->CurrentWorldTime)
|
|
{
|
|
LifetimeAlpha = FMath::Clamp(FMath::Min(View.Family->CurrentWorldTime * -DecalProxy.InvFadeDuration + DecalProxy.FadeStartDelayNormalized, View.Family->CurrentWorldTime * DecalProxy.InvFadeInDuration + DecalProxy.FadeInStartDelayNormalized), 0.0f, 1.0f);
|
|
}
|
|
|
|
SetShaderValue(RHICmdList, ShaderRHI, DecalParams, FVector2D(FadeAlphaValue, LifetimeAlpha));
|
|
}
|
|
|
|
private:
|
|
LAYOUT_FIELD(FShaderParameter, SvPositionToDecal);
|
|
LAYOUT_FIELD(FShaderParameter, DecalToWorld);
|
|
LAYOUT_FIELD(FShaderParameter, WorldToDecal);
|
|
LAYOUT_FIELD(FShaderParameter, DecalOrientation);
|
|
LAYOUT_FIELD(FShaderParameter, DecalParams);
|
|
};
|
|
|
|
IMPLEMENT_MATERIAL_SHADER_TYPE(,FDeferredDecalPS,TEXT("/Engine/Private/DeferredDecal.usf"),TEXT("MainPS"),SF_Pixel);
|
|
|
|
class FDeferredDecalEmissivePS : public FDeferredDecalPS
|
|
{
|
|
DECLARE_SHADER_TYPE(FDeferredDecalEmissivePS, Material);
|
|
|
|
public:
|
|
static bool ShouldCompilePermutation(const FMaterialShaderPermutationParameters& Parameters)
|
|
{
|
|
return (Parameters.MaterialParameters.MaterialDomain == MD_DeferredDecal) &&
|
|
DecalRendering::IsCompatibleWithRenderStage(DecalRendering::ComputeDecalBlendDesc(Parameters.Platform, Parameters.MaterialParameters), EDecalRenderStage::Emissive);
|
|
}
|
|
static void ModifyCompilationEnvironment(const FMaterialShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FMaterialShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
DecalRendering::ModifyCompilationEnvironment(DecalRendering::ComputeDecalBlendDesc(Parameters.Platform, Parameters.MaterialParameters), EDecalRenderStage::Emissive, OutEnvironment);
|
|
}
|
|
|
|
FDeferredDecalEmissivePS() {}
|
|
FDeferredDecalEmissivePS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FDeferredDecalPS(Initializer)
|
|
{}
|
|
};
|
|
|
|
IMPLEMENT_MATERIAL_SHADER_TYPE(, FDeferredDecalEmissivePS, TEXT("/Engine/Private/DeferredDecal.usf"), TEXT("MainPS"), SF_Pixel);
|
|
|
|
class FDeferredDecalAmbientOcclusionPS : public FDeferredDecalPS
|
|
{
|
|
DECLARE_SHADER_TYPE(FDeferredDecalAmbientOcclusionPS, Material);
|
|
|
|
public:
|
|
static bool ShouldCompilePermutation(const FMaterialShaderPermutationParameters& Parameters)
|
|
{
|
|
return (Parameters.MaterialParameters.MaterialDomain == MD_DeferredDecal) &&
|
|
DecalRendering::IsCompatibleWithRenderStage(DecalRendering::ComputeDecalBlendDesc(Parameters.Platform, Parameters.MaterialParameters), EDecalRenderStage::AmbientOcclusion);
|
|
}
|
|
static void ModifyCompilationEnvironment(const FMaterialShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FMaterialShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
DecalRendering::ModifyCompilationEnvironment(DecalRendering::ComputeDecalBlendDesc(Parameters.Platform, Parameters.MaterialParameters), EDecalRenderStage::AmbientOcclusion, OutEnvironment);
|
|
}
|
|
|
|
FDeferredDecalAmbientOcclusionPS() {}
|
|
FDeferredDecalAmbientOcclusionPS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FDeferredDecalPS(Initializer)
|
|
{}
|
|
};
|
|
|
|
IMPLEMENT_MATERIAL_SHADER_TYPE(, FDeferredDecalAmbientOcclusionPS, TEXT("/Engine/Private/DeferredDecal.usf"), TEXT("MainPS"), SF_Pixel);
|
|
|
|
namespace DecalRendering
|
|
{
|
|
bool BuildVisibleDecalList(const FScene& Scene, const FViewInfo& View, EDecalRenderStage DecalRenderStage, FTransientDecalRenderDataList* OutVisibleDecals)
|
|
{
|
|
QUICK_SCOPE_CYCLE_COUNTER(BuildVisibleDecalList);
|
|
|
|
if (OutVisibleDecals)
|
|
{
|
|
OutVisibleDecals->Empty(Scene.Decals.Num());
|
|
}
|
|
|
|
// Don't draw for shader complexity mode.
|
|
// todo: Handle shader complexity mode for deferred decal.
|
|
if (View.Family->EngineShowFlags.ShaderComplexity)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
const float FadeMultiplier = CVarDecalFadeScreenSizeMultiplier.GetValueOnRenderThread();
|
|
const EShaderPlatform ShaderPlatform = View.GetShaderPlatform();
|
|
|
|
const bool bIsPerspectiveProjection = View.IsPerspectiveProjection();
|
|
|
|
// Build a list of decals that need to be rendered for this view in SortedDecals
|
|
for (const FDeferredDecalProxy* DecalProxy : Scene.Decals)
|
|
{
|
|
if (!DecalProxy->DecalMaterial || !DecalProxy->DecalMaterial->IsValidLowLevelFast())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
bool bIsShown = true;
|
|
|
|
if (!DecalProxy->IsShown(&View))
|
|
{
|
|
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() +
|
|
ComponentToWorldMatrix.GetScaledAxis(EAxis::Y).SizeSquared() +
|
|
ComponentToWorldMatrix.GetScaledAxis(EAxis::Z).SizeSquared());
|
|
|
|
// 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, ConservativeRadius);
|
|
|
|
if (IsCompatibleWithRenderStage(Data.DecalBlendDesc, DecalRenderStage))
|
|
{
|
|
if (bIsPerspectiveProjection && Data.DecalProxy->FadeScreenSize != 0.0f)
|
|
{
|
|
float Distance = (View.ViewMatrices.GetViewOrigin() - ComponentToWorldMatrix.GetOrigin()).Size();
|
|
float Radius = ComponentToWorldMatrix.GetMaximumAxisScale();
|
|
float CurrentScreenSize = ((Radius / Distance) * FadeMultiplier);
|
|
|
|
// fading coefficient needs to increase with increasing field of view and decrease with increasing resolution
|
|
// FadeCoeffScale is an empirically determined constant to bring us back roughly to fraction of screen size for FadeScreenSize
|
|
const float FadeCoeffScale = 600.0f;
|
|
float FOVFactor = ((2.0f/View.ViewMatrices.GetProjectionMatrix().M[0][0]) / View.ViewRect.Width()) * FadeCoeffScale;
|
|
float FadeCoeff = Data.DecalProxy->FadeScreenSize * FOVFactor;
|
|
float FadeRange = FadeCoeff * 0.5f;
|
|
|
|
float Alpha = (CurrentScreenSize - FadeCoeff) / FadeRange;
|
|
Data.FadeAlpha = FMath::Min(Alpha, 1.0f);
|
|
}
|
|
|
|
const bool bShouldRender = Data.FadeAlpha > 0.0f;
|
|
|
|
if (bShouldRender)
|
|
{
|
|
if (!OutVisibleDecals)
|
|
{
|
|
return true;
|
|
}
|
|
OutVisibleDecals->Add(Data);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!OutVisibleDecals)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (OutVisibleDecals->Num() > 0)
|
|
{
|
|
// 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.DecalBlendDesc.bWriteNormal != A.DecalBlendDesc.bWriteNormal)
|
|
{
|
|
// bWriteNormal here has priority because we want to render decals that output normals before those could read normals.
|
|
// Also this is the only flag that can trigger a change of EDecalRenderTargetMode inside a single EDecalRenderStage, and we batch according to this.
|
|
return B.DecalBlendDesc.bWriteNormal < A.DecalBlendDesc.bWriteNormal; // < so that those outputting normal are first.
|
|
}
|
|
if (B.DecalBlendDesc.Packed != A.DecalBlendDesc.Packed)
|
|
{
|
|
// Sorting by the FDecalBlendDesc contents will reduce blend state changes.
|
|
return (int32)B.DecalBlendDesc.Packed < (int32)A.DecalBlendDesc.Packed;
|
|
}
|
|
if (B.MaterialProxy != A.MaterialProxy)
|
|
{
|
|
// Batch decals with the same material together
|
|
return B.MaterialProxy < A.MaterialProxy;
|
|
}
|
|
return (PTRINT)B.DecalProxy->Component < (PTRINT)A.DecalProxy->Component;
|
|
}
|
|
};
|
|
|
|
// Sort decals by blend mode to reduce render target switches
|
|
OutVisibleDecals->Sort(FCompareFTransientDecalRenderData());
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
FMatrix ComputeComponentToClipMatrix(const FViewInfo& View, const FMatrix& DecalComponentToWorld)
|
|
{
|
|
FMatrix ComponentToWorldMatrixTrans = DecalComponentToWorld.ConcatTranslation(View.ViewMatrices.GetPreViewTranslation());
|
|
return ComponentToWorldMatrixTrans * View.ViewMatrices.GetTranslatedViewProjectionMatrix();
|
|
}
|
|
|
|
void SetShader(FRHICommandList& RHICmdList, FGraphicsPipelineStateInitializer& GraphicsPSOInit, const FViewInfo& View,
|
|
const FTransientDecalRenderData& DecalData, EDecalRenderStage DecalRenderStage, const FMatrix& FrustumComponentToClip)
|
|
{
|
|
const FMaterialShaderMap* MaterialShaderMap = DecalData.MaterialResource->GetRenderingThreadShaderMap();
|
|
const EDebugViewShaderMode DebugViewMode = View.Family->GetDebugViewShaderMode();
|
|
|
|
// When in shader complexity, decals get rendered as emissive even though there might not be emissive decals.
|
|
// FDeferredDecalEmissivePS might not be available depending on the decal blend mode.
|
|
TShaderRef<FDeferredDecalPS> PixelShader;
|
|
if (DecalRenderStage == EDecalRenderStage::Emissive || DebugViewMode != DVSM_None)
|
|
{
|
|
PixelShader = TShaderRef<FDeferredDecalPS>(MaterialShaderMap->GetShader<FDeferredDecalEmissivePS>());
|
|
}
|
|
else if (DecalRenderStage == EDecalRenderStage::AmbientOcclusion)
|
|
{
|
|
PixelShader = TShaderRef<FDeferredDecalPS>(MaterialShaderMap->GetShader<FDeferredDecalAmbientOcclusionPS>());
|
|
}
|
|
else
|
|
{
|
|
PixelShader = MaterialShaderMap->GetShader<FDeferredDecalPS>();
|
|
}
|
|
|
|
TShaderMapRef<FDeferredDecalVS> VertexShader(View.ShaderMap);
|
|
|
|
{
|
|
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GetVertexDeclarationFVector4();
|
|
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader();
|
|
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = PixelShader.GetPixelShader();
|
|
GraphicsPSOInit.PrimitiveType = PT_TriangleList;
|
|
|
|
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit);
|
|
PixelShader->SetParameters(RHICmdList, View, DecalData.MaterialProxy, *DecalData.DecalProxy, DecalData.FadeAlpha);
|
|
}
|
|
|
|
// SetUniformBufferParameter() need to happen after the shader has been set otherwise a DebugBreak could occur.
|
|
|
|
// we don't have the Primitive uniform buffer setup for decals (later we want to batch)
|
|
{
|
|
auto& PrimitiveVS = VertexShader->GetUniformBufferParameter<FPrimitiveUniformShaderParameters>();
|
|
auto& PrimitivePS = PixelShader->GetUniformBufferParameter<FPrimitiveUniformShaderParameters>();
|
|
|
|
// uncomment to track down usage of the Primitive uniform buffer
|
|
// check(!PrimitiveVS.IsBound());
|
|
// check(!PrimitivePS.IsBound());
|
|
|
|
// to prevent potential shader error (UE-18852 ElementalDemo crashes due to nil constant buffer)
|
|
SetUniformBufferParameter(RHICmdList, VertexShader.GetVertexShader(), PrimitiveVS, GIdentityPrimitiveUniformBuffer);
|
|
|
|
if (DebugViewMode == DVSM_None)
|
|
{
|
|
SetUniformBufferParameter(RHICmdList, PixelShader.GetPixelShader(), PrimitivePS, GIdentityPrimitiveUniformBuffer);
|
|
}
|
|
}
|
|
|
|
VertexShader->SetParameters(RHICmdList, FrustumComponentToClip);
|
|
|
|
// Set stream source after updating cached strides
|
|
RHICmdList.SetStreamSource(0, GetUnitCubeVertexBuffer(), 0);
|
|
}
|
|
|
|
void SetVertexShaderOnly(FRHICommandList& RHICmdList, FGraphicsPipelineStateInitializer& GraphicsPSOInit, const FViewInfo& View, const FMatrix& FrustumComponentToClip)
|
|
{
|
|
TShaderMapRef<FDeferredDecalVS> VertexShader(View.ShaderMap);
|
|
|
|
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GetVertexDeclarationFVector4();
|
|
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader();
|
|
GraphicsPSOInit.PrimitiveType = PT_TriangleList;
|
|
|
|
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit);
|
|
VertexShader->SetParameters(RHICmdList, FrustumComponentToClip);
|
|
}
|
|
}
|