You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
580 lines
22 KiB
C++
580 lines
22 KiB
C++
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
SurfelTree.cpp
|
|
=============================================================================*/
|
|
|
|
#include "RendererPrivate.h"
|
|
#include "ScenePrivate.h"
|
|
#include "UniformBuffer.h"
|
|
#include "ShaderParameters.h"
|
|
#include "PostProcessing.h"
|
|
#include "SceneFilterRendering.h"
|
|
#include "DistanceFieldLightingShared.h"
|
|
#include "DistanceFieldSurfaceCacheLighting.h"
|
|
#include "DistanceFieldGlobalIllumination.h"
|
|
#include "RHICommandList.h"
|
|
#include "SceneUtils.h"
|
|
#include "DistanceFieldAtlas.h"
|
|
|
|
|
|
class FConvertToUniformMeshVS : public FMeshMaterialShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FConvertToUniformMeshVS,MeshMaterial);
|
|
|
|
protected:
|
|
|
|
FConvertToUniformMeshVS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FMeshMaterialShader(Initializer)
|
|
{
|
|
}
|
|
|
|
FConvertToUniformMeshVS()
|
|
{
|
|
}
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform,const FMaterial* Material,const FVertexFactoryType* VertexFactoryType)
|
|
{
|
|
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM5)
|
|
&& DoesPlatformSupportDistanceFieldGI(Platform)
|
|
&& (FCString::Strstr(VertexFactoryType->GetName(), TEXT("LocalVertexFactory")) != NULL
|
|
|| FCString::Strstr(VertexFactoryType->GetName(), TEXT("InstancedStaticMeshVertexFactory")) != NULL);
|
|
}
|
|
|
|
public:
|
|
|
|
void SetParameters(FRHICommandList& RHICmdList, const FVertexFactory* VertexFactory,const FMaterialRenderProxy* MaterialRenderProxy,const FSceneView* View)
|
|
{
|
|
FMeshMaterialShader::SetParameters(RHICmdList, GetVertexShader(), MaterialRenderProxy, *MaterialRenderProxy->GetMaterial(View->GetFeatureLevel()), *View, ESceneRenderTargetsMode::SetTextures);
|
|
}
|
|
|
|
void SetMesh(FRHICommandList& RHICmdList, const FVertexFactory* VertexFactory,const FSceneView& View,const FPrimitiveSceneProxy* Proxy,const FMeshBatchElement& BatchElement, float DitheredLODTransitionValue)
|
|
{
|
|
FMeshMaterialShader::SetMesh(RHICmdList, GetVertexShader(),VertexFactory,View,Proxy,BatchElement,DitheredLODTransitionValue);
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_MATERIAL_SHADER_TYPE(,FConvertToUniformMeshVS,TEXT("ConvertToUniformMesh"),TEXT("ConvertToUniformMeshVS"),SF_Vertex);
|
|
|
|
void GetUniformMeshStreamOutLayout(FStreamOutElementList& Layout)
|
|
{
|
|
Layout.Add(FStreamOutElement(0, "SV_Position", 0, 4, 0));
|
|
Layout.Add(FStreamOutElement(0, "Tangent", 0, 3, 0));
|
|
Layout.Add(FStreamOutElement(0, "Tangent", 1, 3, 0));
|
|
Layout.Add(FStreamOutElement(0, "Tangent", 2, 3, 0));
|
|
Layout.Add(FStreamOutElement(0, "UV", 0, 2, 0));
|
|
Layout.Add(FStreamOutElement(0, "UV", 1, 2, 0));
|
|
Layout.Add(FStreamOutElement(0, "VertexColor", 0, 4, 0));
|
|
}
|
|
|
|
// In float4's, must match usf
|
|
int32 FSurfelBuffers::InterpolatedVertexDataStride = 6;
|
|
|
|
/** Returns number of float's in the uniform vertex. */
|
|
int32 ComputeUniformVertexStride()
|
|
{
|
|
FStreamOutElementList Layout;
|
|
int32 StreamStride = 0;
|
|
|
|
GetUniformMeshStreamOutLayout(Layout);
|
|
|
|
for (int32 ElementIndex = 0; ElementIndex < Layout.Num(); ElementIndex++)
|
|
{
|
|
StreamStride += Layout[ElementIndex].ComponentCount;
|
|
}
|
|
|
|
// D3D11 stream out buffer element stride must be a factor of 4
|
|
return FMath::DivideAndRoundUp(StreamStride, 4) * 4;
|
|
}
|
|
|
|
void FUniformMeshBuffers::Initialize()
|
|
{
|
|
if (MaxElements > 0)
|
|
{
|
|
const int32 VertexStride = ComputeUniformVertexStride();
|
|
FRHIResourceCreateInfo CreateInfo;
|
|
TriangleData = RHICreateVertexBuffer(MaxElements * VertexStride * GPixelFormats[PF_R32_FLOAT].BlockBytes, BUF_ShaderResource | BUF_StreamOutput, CreateInfo);
|
|
TriangleDataSRV = RHICreateShaderResourceView(TriangleData, GPixelFormats[PF_R32_FLOAT].BlockBytes, PF_R32_FLOAT);
|
|
|
|
TriangleAreas.Initialize(sizeof(float), MaxElements, PF_R32_FLOAT);
|
|
TriangleCDFs.Initialize(sizeof(float), MaxElements, PF_R32_FLOAT);
|
|
}
|
|
}
|
|
|
|
class FConvertToUniformMeshGS : public FMeshMaterialShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FConvertToUniformMeshGS,MeshMaterial);
|
|
|
|
protected:
|
|
|
|
FConvertToUniformMeshGS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FMeshMaterialShader(Initializer)
|
|
{
|
|
}
|
|
|
|
FConvertToUniformMeshGS()
|
|
{
|
|
}
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform,const FMaterial* Material,const FVertexFactoryType* VertexFactoryType)
|
|
{
|
|
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM5)
|
|
&& DoesPlatformSupportDistanceFieldGI(Platform)
|
|
&& (FCString::Strstr(VertexFactoryType->GetName(), TEXT("LocalVertexFactory")) != NULL
|
|
|| FCString::Strstr(VertexFactoryType->GetName(), TEXT("InstancedStaticMeshVertexFactory")) != NULL);
|
|
}
|
|
|
|
static void GetStreamOutElements(FStreamOutElementList& ElementList, TArray<uint32>& StreamStrides, int32& RasterizedStream)
|
|
{
|
|
StreamStrides.Add(ComputeUniformVertexStride() * 4);
|
|
GetUniformMeshStreamOutLayout(ElementList);
|
|
RasterizedStream = -1;
|
|
}
|
|
|
|
public:
|
|
|
|
void SetParameters(FRHICommandList& RHICmdList, const FVertexFactory* VertexFactory,const FMaterialRenderProxy* MaterialRenderProxy,const FSceneView* View)
|
|
{
|
|
FMeshMaterialShader::SetParameters(RHICmdList, (FGeometryShaderRHIParamRef)GetGeometryShader(), MaterialRenderProxy, *MaterialRenderProxy->GetMaterial(View->GetFeatureLevel()), *View, ESceneRenderTargetsMode::SetTextures);
|
|
}
|
|
|
|
void SetMesh(FRHICommandList& RHICmdList, const FVertexFactory* VertexFactory,const FSceneView& View,const FPrimitiveSceneProxy* Proxy,const FMeshBatchElement& BatchElement, float DitheredLODTransitionValue)
|
|
{
|
|
FMeshMaterialShader::SetMesh(RHICmdList, (FGeometryShaderRHIParamRef)GetGeometryShader(),VertexFactory,View,Proxy,BatchElement,DitheredLODTransitionValue);
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_MATERIAL_SHADER_TYPE(,FConvertToUniformMeshGS,TEXT("ConvertToUniformMesh"),TEXT("ConvertToUniformMeshGS"),SF_Geometry);
|
|
|
|
|
|
class FConvertToUniformMeshDrawingPolicy : public FMeshDrawingPolicy
|
|
{
|
|
public:
|
|
/** context type */
|
|
typedef FMeshDrawingPolicy::ElementDataType ElementDataType;
|
|
|
|
/**
|
|
* Constructor
|
|
* @param InIndexBuffer - index buffer for rendering
|
|
* @param InVertexFactory - vertex factory for rendering
|
|
* @param InMaterialRenderProxy - material instance for rendering
|
|
* @param bInOverrideWithShaderComplexity - whether to override with shader complexity
|
|
*/
|
|
FConvertToUniformMeshDrawingPolicy(
|
|
const FVertexFactory* InVertexFactory,
|
|
const FMaterialRenderProxy* InMaterialRenderProxy,
|
|
const FMaterial& MaterialResouce,
|
|
ERHIFeatureLevel::Type InFeatureLevel
|
|
);
|
|
|
|
// FMeshDrawingPolicy interface.
|
|
|
|
/**
|
|
* Match two draw policies
|
|
* @param Other - draw policy to compare
|
|
* @return true if the draw policies are a match
|
|
*/
|
|
bool Matches(const FConvertToUniformMeshDrawingPolicy& Other) const;
|
|
|
|
/**
|
|
* Executes the draw commands which can be shared between any meshes using this drawer.
|
|
* @param CI - The command interface to execute the draw commands on.
|
|
* @param View - The view of the scene being drawn.
|
|
*/
|
|
void SetSharedState(FRHICommandList& RHICmdList, const FSceneView* View, const ContextDataType PolicyContext) const;
|
|
|
|
/**
|
|
* Create bound shader state using the vertex decl from the mesh draw policy
|
|
* as well as the shaders needed to draw the mesh
|
|
* @return new bound shader state object
|
|
*/
|
|
FBoundShaderStateInput GetBoundShaderStateInput(ERHIFeatureLevel::Type InFeatureLevel);
|
|
|
|
/**
|
|
* Sets the render states for drawing a mesh.
|
|
* @param PrimitiveSceneProxy - The primitive drawing the dynamic mesh. If this is a view element, this will be NULL.
|
|
* @param Mesh - mesh element with data needed for rendering
|
|
* @param ElementData - context specific data for mesh rendering
|
|
*/
|
|
void SetMeshRenderState(
|
|
FRHICommandList& RHICmdList,
|
|
const FSceneView& View,
|
|
const FPrimitiveSceneProxy* PrimitiveSceneProxy,
|
|
const FMeshBatch& Mesh,
|
|
int32 BatchElementIndex,
|
|
bool bBackFace,
|
|
float DitheredLODTransitionValue,
|
|
const ElementDataType& ElementData,
|
|
const ContextDataType PolicyContext
|
|
) const;
|
|
|
|
private:
|
|
FConvertToUniformMeshVS* VertexShader;
|
|
FConvertToUniformMeshGS* GeometryShader;
|
|
};
|
|
|
|
FConvertToUniformMeshDrawingPolicy::FConvertToUniformMeshDrawingPolicy(
|
|
const FVertexFactory* InVertexFactory,
|
|
const FMaterialRenderProxy* InMaterialRenderProxy,
|
|
const FMaterial& InMaterialResource,
|
|
ERHIFeatureLevel::Type InFeatureLevel
|
|
)
|
|
: FMeshDrawingPolicy(InVertexFactory,InMaterialRenderProxy,InMaterialResource,false)
|
|
{
|
|
VertexShader = InMaterialResource.GetShader<FConvertToUniformMeshVS>(InVertexFactory->GetType());
|
|
GeometryShader = InMaterialResource.GetShader<FConvertToUniformMeshGS>(InVertexFactory->GetType());
|
|
}
|
|
|
|
bool FConvertToUniformMeshDrawingPolicy::Matches(
|
|
const FConvertToUniformMeshDrawingPolicy& Other
|
|
) const
|
|
{
|
|
return FMeshDrawingPolicy::Matches(Other) &&
|
|
VertexShader == Other.VertexShader &&
|
|
GeometryShader == Other.GeometryShader;
|
|
}
|
|
|
|
void FConvertToUniformMeshDrawingPolicy::SetSharedState(
|
|
FRHICommandList& RHICmdList,
|
|
const FSceneView* View,
|
|
const ContextDataType PolicyContext
|
|
) const
|
|
{
|
|
// Set shared mesh resources
|
|
FMeshDrawingPolicy::SetSharedState(RHICmdList, View, PolicyContext);
|
|
|
|
VertexShader->SetParameters(RHICmdList, VertexFactory, MaterialRenderProxy, View);
|
|
GeometryShader->SetParameters(RHICmdList, VertexFactory, MaterialRenderProxy, View);
|
|
}
|
|
|
|
FBoundShaderStateInput FConvertToUniformMeshDrawingPolicy::GetBoundShaderStateInput(ERHIFeatureLevel::Type InFeatureLevel)
|
|
{
|
|
return FBoundShaderStateInput(
|
|
FMeshDrawingPolicy::GetVertexDeclaration(),
|
|
VertexShader->GetVertexShader(),
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
GeometryShader->GetGeometryShader());
|
|
|
|
}
|
|
|
|
void FConvertToUniformMeshDrawingPolicy::SetMeshRenderState(
|
|
FRHICommandList& RHICmdList,
|
|
const FSceneView& View,
|
|
const FPrimitiveSceneProxy* PrimitiveSceneProxy,
|
|
const FMeshBatch& Mesh,
|
|
int32 BatchElementIndex,
|
|
bool bBackFace,
|
|
float DitheredLODTransitionValue,
|
|
const ElementDataType& ElementData,
|
|
const ContextDataType PolicyContext
|
|
) const
|
|
{
|
|
const FMeshBatchElement& BatchElement = Mesh.Elements[BatchElementIndex];
|
|
|
|
EmitMeshDrawEvents(RHICmdList, PrimitiveSceneProxy, Mesh);
|
|
|
|
// Set transforms
|
|
VertexShader->SetMesh(RHICmdList, VertexFactory,View,PrimitiveSceneProxy,BatchElement, DitheredLODTransitionValue);
|
|
GeometryShader->SetMesh(RHICmdList, VertexFactory,View,PrimitiveSceneProxy,BatchElement, DitheredLODTransitionValue);
|
|
|
|
// Set rasterizer state.
|
|
RHICmdList.SetRasterizerState(GetStaticRasterizerState<true>(
|
|
(Mesh.bWireframe || IsWireframe()) ? FM_Wireframe : FM_Solid,
|
|
IsTwoSided() ? CM_None : (XOR( XOR(View.bReverseCulling,bBackFace), Mesh.ReverseCulling) ? CM_CCW : CM_CW)));
|
|
}
|
|
|
|
bool ShouldGenerateSurfelsOnMesh(const FMeshBatch& Mesh, ERHIFeatureLevel::Type FeatureLevel)
|
|
{
|
|
//@todo - support for tessellated meshes
|
|
return Mesh.Type == PT_TriangleList
|
|
&& !Mesh.IsTranslucent(FeatureLevel)
|
|
&& Mesh.MaterialRenderProxy->GetMaterial(FeatureLevel)->GetShadingModel() != MSM_Unlit;
|
|
}
|
|
|
|
FUniformMeshBuffers GUniformMeshTemporaryBuffers;
|
|
|
|
TArray<TArray<FMeshBatchAndRelevance,SceneRenderingAllocator>> GDynamicMeshElements;
|
|
|
|
int32 FUniformMeshConverter::Convert(
|
|
FRHICommandListImmediate& RHICmdList,
|
|
FSceneRenderer& Renderer,
|
|
FViewInfo& View,
|
|
const FPrimitiveSceneInfo* PrimitiveSceneInfo,
|
|
FUniformMeshBuffers*& OutUniformMeshBuffers,
|
|
const FMaterialRenderProxy*& OutMaterialRenderProxy,
|
|
FUniformBufferRHIParamRef& OutPrimitiveUniformBuffer)
|
|
{
|
|
const FPrimitiveSceneProxy* PrimitiveSceneProxy = PrimitiveSceneInfo->Proxy;
|
|
const auto FeatureLevel = View.GetFeatureLevel();
|
|
|
|
if (GDynamicMeshElements.Num() == 0)
|
|
{
|
|
GDynamicMeshElements.Empty(10000);
|
|
}
|
|
|
|
FSimpleElementCollector DynamicSimpleElements;
|
|
GDynamicMeshElements.Add(TArray<FMeshBatchAndRelevance,SceneRenderingAllocator>());
|
|
TArray<FMeshBatchAndRelevance,SceneRenderingAllocator>& DynamicMeshElements = GDynamicMeshElements.Last();
|
|
TArray<const FSceneView*> ViewsArray;
|
|
ViewsArray.Add(&View);
|
|
|
|
Renderer.MeshCollector.ClearViewMeshArrays();
|
|
Renderer.MeshCollector.AddViewMeshArrays(&View, &DynamicMeshElements, &DynamicSimpleElements, FeatureLevel);
|
|
|
|
View.bRenderFirstInstanceOnly = true;
|
|
Renderer.MeshCollector.SetPrimitive(PrimitiveSceneInfo->Proxy, PrimitiveSceneInfo->DefaultDynamicHitProxyId);
|
|
PrimitiveSceneInfo->Proxy->GetDynamicMeshElements(ViewsArray, *(View.Family), 0x1, Renderer.MeshCollector);
|
|
View.bRenderFirstInstanceOnly = false;
|
|
|
|
int32 NumTriangles = 0;
|
|
|
|
FPrimitiveViewRelevance ViewRelevance = PrimitiveSceneInfo->Proxy->GetViewRelevance(&View);
|
|
|
|
if (ViewRelevance.bDynamicRelevance)
|
|
{
|
|
for (int32 MeshBatchIndex = 0; MeshBatchIndex < DynamicMeshElements.Num(); MeshBatchIndex++)
|
|
{
|
|
const FMeshBatchAndRelevance& MeshBatchAndRelevance = DynamicMeshElements[MeshBatchIndex];
|
|
|
|
if (ShouldGenerateSurfelsOnMesh(*MeshBatchAndRelevance.Mesh, FeatureLevel))
|
|
{
|
|
NumTriangles += MeshBatchAndRelevance.Mesh->GetNumPrimitives();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ViewRelevance.bStaticRelevance)
|
|
{
|
|
float LargestScreenSize = 0;
|
|
|
|
for (int32 StaticMeshIdx=0; StaticMeshIdx < PrimitiveSceneInfo->StaticMeshes.Num(); StaticMeshIdx++)
|
|
{
|
|
const FStaticMesh& StaticMesh = PrimitiveSceneInfo->StaticMeshes[StaticMeshIdx];
|
|
LargestScreenSize = FMath::Max(LargestScreenSize, StaticMesh.ScreenSize);
|
|
}
|
|
|
|
for (int32 StaticMeshIdx=0; StaticMeshIdx < PrimitiveSceneInfo->StaticMeshes.Num(); StaticMeshIdx++)
|
|
{
|
|
const FStaticMesh& StaticMesh = PrimitiveSceneInfo->StaticMeshes[StaticMeshIdx];
|
|
|
|
if (ShouldGenerateSurfelsOnMesh(StaticMesh, FeatureLevel)
|
|
&& !StaticMesh.bShadowOnly
|
|
// LOD0 only
|
|
&& StaticMesh.ScreenSize == LargestScreenSize)
|
|
{
|
|
NumTriangles += StaticMesh.GetNumPrimitives();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NumTriangles > 0)
|
|
{
|
|
if (GUniformMeshTemporaryBuffers.MaxElements < NumTriangles * 3)
|
|
{
|
|
GUniformMeshTemporaryBuffers.MaxElements = NumTriangles * 3;
|
|
GUniformMeshTemporaryBuffers.Release();
|
|
GUniformMeshTemporaryBuffers.Initialize();
|
|
}
|
|
|
|
RHICmdList.SetRenderTargets(0, (const FRHIRenderTargetView*)NULL, NULL, 0, (const FUnorderedAccessViewRHIParamRef*)NULL);
|
|
|
|
uint32 Offsets[1] = {0};
|
|
const FVertexBufferRHIParamRef StreamOutTargets[1] = {GUniformMeshTemporaryBuffers.TriangleData.GetReference()};
|
|
RHICmdList.SetStreamOutTargets(1, StreamOutTargets, Offsets);
|
|
|
|
if (ViewRelevance.bDynamicRelevance)
|
|
{
|
|
for (int32 MeshBatchIndex = 0; MeshBatchIndex < DynamicMeshElements.Num(); MeshBatchIndex++)
|
|
{
|
|
const FMeshBatchAndRelevance& MeshBatchAndRelevance = DynamicMeshElements[MeshBatchIndex];
|
|
|
|
if (ShouldGenerateSurfelsOnMesh(*MeshBatchAndRelevance.Mesh, FeatureLevel))
|
|
{
|
|
const FMeshBatch& Mesh = *MeshBatchAndRelevance.Mesh;
|
|
|
|
FConvertToUniformMeshDrawingPolicy DrawingPolicy(
|
|
Mesh.VertexFactory,
|
|
Mesh.MaterialRenderProxy,
|
|
*Mesh.MaterialRenderProxy->GetMaterial(FeatureLevel),
|
|
FeatureLevel);
|
|
|
|
//@todo - fix
|
|
OutMaterialRenderProxy = Mesh.MaterialRenderProxy;
|
|
|
|
RHICmdList.BuildAndSetLocalBoundShaderState(DrawingPolicy.GetBoundShaderStateInput(FeatureLevel));
|
|
DrawingPolicy.SetSharedState(RHICmdList, &View, FConvertToUniformMeshDrawingPolicy::ContextDataType());
|
|
|
|
for (int32 BatchElementIndex = 0; BatchElementIndex < Mesh.Elements.Num(); BatchElementIndex++)
|
|
{
|
|
//@todo - fix
|
|
OutPrimitiveUniformBuffer = IsValidRef(Mesh.Elements[BatchElementIndex].PrimitiveUniformBuffer)
|
|
? Mesh.Elements[BatchElementIndex].PrimitiveUniformBuffer
|
|
: *Mesh.Elements[BatchElementIndex].PrimitiveUniformBufferResource;
|
|
|
|
DrawingPolicy.SetMeshRenderState(RHICmdList, View,PrimitiveSceneProxy,Mesh,BatchElementIndex,false,0.0f,FConvertToUniformMeshDrawingPolicy::ElementDataType(), FConvertToUniformMeshDrawingPolicy::ContextDataType());
|
|
DrawingPolicy.DrawMesh(RHICmdList, Mesh, BatchElementIndex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ViewRelevance.bStaticRelevance)
|
|
{
|
|
float LargestScreenSize = 0;
|
|
|
|
for (int32 StaticMeshIdx=0; StaticMeshIdx < PrimitiveSceneInfo->StaticMeshes.Num(); StaticMeshIdx++)
|
|
{
|
|
const FStaticMesh& StaticMesh = PrimitiveSceneInfo->StaticMeshes[StaticMeshIdx];
|
|
LargestScreenSize = FMath::Max(LargestScreenSize, StaticMesh.ScreenSize);
|
|
}
|
|
|
|
for (int32 StaticMeshIdx = 0; StaticMeshIdx < PrimitiveSceneInfo->StaticMeshes.Num(); StaticMeshIdx++)
|
|
{
|
|
const FStaticMesh& StaticMesh = PrimitiveSceneInfo->StaticMeshes[StaticMeshIdx];
|
|
|
|
if (ShouldGenerateSurfelsOnMesh(StaticMesh, FeatureLevel)
|
|
&& !StaticMesh.bShadowOnly
|
|
&& StaticMesh.ScreenSize == LargestScreenSize)
|
|
{
|
|
FConvertToUniformMeshDrawingPolicy DrawingPolicy(
|
|
StaticMesh.VertexFactory,
|
|
StaticMesh.MaterialRenderProxy,
|
|
*StaticMesh.MaterialRenderProxy->GetMaterial(FeatureLevel),
|
|
FeatureLevel
|
|
);
|
|
RHICmdList.BuildAndSetLocalBoundShaderState(DrawingPolicy.GetBoundShaderStateInput(FeatureLevel));
|
|
DrawingPolicy.SetSharedState(RHICmdList, &View, FConvertToUniformMeshDrawingPolicy::ContextDataType());
|
|
|
|
//@todo - fix
|
|
OutMaterialRenderProxy = StaticMesh.MaterialRenderProxy;
|
|
|
|
for (int32 BatchElementIndex = 0; BatchElementIndex < StaticMesh.Elements.Num(); BatchElementIndex++)
|
|
{
|
|
//@todo - fix
|
|
OutPrimitiveUniformBuffer = IsValidRef(StaticMesh.Elements[BatchElementIndex].PrimitiveUniformBuffer)
|
|
? StaticMesh.Elements[BatchElementIndex].PrimitiveUniformBuffer
|
|
: *StaticMesh.Elements[BatchElementIndex].PrimitiveUniformBufferResource;
|
|
|
|
DrawingPolicy.SetMeshRenderState(RHICmdList, View,PrimitiveSceneProxy,StaticMesh,BatchElementIndex,false,0.0f,
|
|
FConvertToUniformMeshDrawingPolicy::ElementDataType(),
|
|
FConvertToUniformMeshDrawingPolicy::ContextDataType()
|
|
);
|
|
DrawingPolicy.DrawMesh(RHICmdList, StaticMesh, BatchElementIndex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
RHICmdList.SetStreamOutTargets(1, (const FVertexBufferRHIParamRef*)NULL, Offsets);
|
|
}
|
|
|
|
OutUniformMeshBuffers = &GUniformMeshTemporaryBuffers;
|
|
return NumTriangles;
|
|
}
|
|
|
|
int32 GEvaluateSurfelMaterialGroupSize = 64;
|
|
|
|
class FEvaluateSurfelMaterialCS : public FMaterialShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FEvaluateSurfelMaterialCS,Material)
|
|
public:
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform, const FMaterial* Material)
|
|
{
|
|
//@todo - lit materials only
|
|
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM5) && DoesPlatformSupportDistanceFieldGI(Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, const FMaterial* Material, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FMaterialShader::ModifyCompilationEnvironment(Platform,OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("EVALUATE_SURFEL_MATERIAL_GROUP_SIZE"), GEvaluateSurfelMaterialGroupSize);
|
|
OutEnvironment.SetDefine(TEXT("HAS_PRIMITIVE_UNIFORM_BUFFER"), 1);
|
|
}
|
|
|
|
FEvaluateSurfelMaterialCS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FMaterialShader(Initializer)
|
|
{
|
|
SurfelBufferParameters.Bind(Initializer.ParameterMap);
|
|
SurfelStartIndex.Bind(Initializer.ParameterMap, TEXT("SurfelStartIndex"));
|
|
NumSurfelsToGenerate.Bind(Initializer.ParameterMap, TEXT("NumSurfelsToGenerate"));
|
|
Instance0InverseTransform.Bind(Initializer.ParameterMap, TEXT("Instance0InverseTransform"));
|
|
}
|
|
|
|
FEvaluateSurfelMaterialCS()
|
|
{
|
|
}
|
|
|
|
void SetParameters(
|
|
FRHICommandList& RHICmdList,
|
|
const FSceneView& View,
|
|
int32 SurfelStartIndexValue,
|
|
int32 NumSurfelsToGenerateValue,
|
|
const FMaterialRenderProxy* MaterialProxy,
|
|
FUniformBufferRHIParamRef PrimitiveUniformBuffer,
|
|
const FMatrix& Instance0Transform
|
|
)
|
|
{
|
|
FComputeShaderRHIParamRef ShaderRHI = GetComputeShader();
|
|
FMaterialShader::SetParameters(RHICmdList, ShaderRHI, MaterialProxy, *MaterialProxy->GetMaterial(View.GetFeatureLevel()), View, true, ESceneRenderTargetsMode::SetTextures);
|
|
|
|
SetUniformBufferParameter(RHICmdList, ShaderRHI,GetUniformBufferParameter<FPrimitiveUniformShaderParameters>(),PrimitiveUniformBuffer);
|
|
|
|
const FScene* Scene = (const FScene*)View.Family->Scene;
|
|
SurfelBufferParameters.Set(RHICmdList, ShaderRHI, *Scene->DistanceFieldSceneData.SurfelBuffers, *Scene->DistanceFieldSceneData.InstancedSurfelBuffers);
|
|
|
|
SetShaderValue(RHICmdList, ShaderRHI, SurfelStartIndex, SurfelStartIndexValue);
|
|
SetShaderValue(RHICmdList, ShaderRHI, NumSurfelsToGenerate, NumSurfelsToGenerateValue);
|
|
|
|
SetShaderValue(RHICmdList, ShaderRHI, Instance0InverseTransform, Instance0Transform.Inverse());
|
|
}
|
|
|
|
void UnsetParameters(FRHICommandList& RHICmdList)
|
|
{
|
|
FComputeShaderRHIParamRef ShaderRHI = GetComputeShader();
|
|
SurfelBufferParameters.UnsetParameters(RHICmdList, ShaderRHI);
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FMaterialShader::Serialize(Ar);
|
|
Ar << SurfelBufferParameters;
|
|
Ar << SurfelStartIndex;
|
|
Ar << NumSurfelsToGenerate;
|
|
Ar << Instance0InverseTransform;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
|
|
private:
|
|
|
|
FSurfelBufferParameters SurfelBufferParameters;
|
|
FShaderParameter SurfelStartIndex;
|
|
FShaderParameter NumSurfelsToGenerate;
|
|
FShaderParameter Instance0InverseTransform;
|
|
};
|
|
|
|
IMPLEMENT_MATERIAL_SHADER_TYPE(,FEvaluateSurfelMaterialCS,TEXT("EvaluateSurfelMaterial"),TEXT("EvaluateSurfelMaterialCS"),SF_Compute);
|
|
|
|
void FUniformMeshConverter::GenerateSurfels(
|
|
FRHICommandListImmediate& RHICmdList,
|
|
FViewInfo& View,
|
|
const FPrimitiveSceneInfo* PrimitiveSceneInfo,
|
|
const FMaterialRenderProxy* MaterialProxy,
|
|
FUniformBufferRHIParamRef PrimitiveUniformBuffer,
|
|
const FMatrix& Instance0Transform,
|
|
int32 SurfelOffset,
|
|
int32 NumSurfels)
|
|
{
|
|
const FMaterial* Material = MaterialProxy->GetMaterial(View.GetFeatureLevel());
|
|
const FMaterialShaderMap* MaterialShaderMap = Material->GetRenderingThreadShaderMap();
|
|
FEvaluateSurfelMaterialCS* ComputeShader = MaterialShaderMap->GetShader<FEvaluateSurfelMaterialCS>();
|
|
|
|
RHICmdList.SetComputeShader(ComputeShader->GetComputeShader());
|
|
ComputeShader->SetParameters(RHICmdList, View, SurfelOffset, NumSurfels, MaterialProxy, PrimitiveUniformBuffer, Instance0Transform);
|
|
DispatchComputeShader(RHICmdList, ComputeShader, FMath::DivideAndRoundUp(NumSurfels, GEvaluateSurfelMaterialGroupSize), 1, 1);
|
|
|
|
ComputeShader->UnsetParameters(RHICmdList);
|
|
}
|