解释:
全局着色器(Global Shaders)是不通过材质编辑器创建的着色器。相反,全局着色器使用C++创建,它们在固定的几何体上运行,并且无需与材质或网格体结合。
有些算法材质中实现比较复杂,但是C++却很简单
着色器类型
- vs顶点着色器(Vertex Shader)
- ps像素着色器(Pixel Shader)
- gs几何体着色器(Geometry Shader)
- hs凸包着色器(Hull Shader)
- ds域着色器(Domain Shader)
- cs计算着色器(Computer Shader)
目的:
材质参数更新不需要通过材质节点,而是直接通过C++直接更新.ush文件中的参数内容
流程
1. 创建插件
2. 路径映射
3. 编写着色器文件.ush和对应C++结构体
4. 申明全局着色器类型
5. 在C++申明、绑定着色器参数,和赋值
6. 实现像素着色器和顶点着色器
7. GPU中数据更新
创建插件:
1. 创建插件
2. 在.build.cs中添加渲染模块
PublicIncludePaths.AddRange(
new string[] {
// ... add public include paths required here ...
"Foo/Public"
}
);
PrivateIncludePaths.AddRange(
new string[] {
"Foo/Private",
// ... add other private include paths required here ...
}
);
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
"RenderCore",
"RHI"
// ... add other public dependencies that you statically link with here ...
}
);
路径映射
在插件启动函数中添加
TEXT("/Plugin/Foo") 不能写成 TEXT("/Plugin/Foo/")
// Copyright Epic Games, Inc. All Rights Reserved.
#include "Foo.h"
#include "Modules/ModuleManager.h"
#include "Interfaces/IPluginManager.h"
#include "Misc/Paths.h"
#define LOCTEXT_NAMESPACE "FFooModule"
void FFooModule::StartupModule()
{
//FString FooShaderDir = FPaths::Combine(FPaths::ProjectPluginsDir(),TEXT("Foo/"), TEXT("Shaders"));
FString FooShaderDir = FPaths::Combine(IPluginManager::Get().FindPlugin("Foo")->GetBaseDir(), TEXT("Shaders"));
AddShaderSourceDirectoryMapping(TEXT("/Plugin/Foo"), FooShaderDir);
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
}
void FFooModule::ShutdownModule()
{
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
// we call this function before unloading the module.
}
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FFooModule, Foo)
路径映射注意事项
假设实际文件夹路径:Plugins/Foo/Shaders/Private/MyTest.usf
IMPLEMENT_SHADER_TYPE 和 IMPLEMENT_GLOBAL_SHADER写法不一样,否则编译会报错
//另一种申明方式 DECLARE_GLOBAL_SHADER(FMyTestVS);
class FLensDistortionUVGenerationVS : public FLensDistortionUVGenerationShader
{
DECLARE_SHADER_TYPE(FLensDistortionUVGenerationVS, Global);
public:
/** Default constructor. */
FLensDistortionUVGenerationVS() {}
/** Initialization constructor. */
FLensDistortionUVGenerationVS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FLensDistortionUVGenerationShader(Initializer)
{
}
};
class FLensDistortionUVGenerationPS : public FLensDistortionUVGenerationShader
{
DECLARE_SHADER_TYPE(FLensDistortionUVGenerationPS, Global);
public:
/** Default constructor. */
FLensDistortionUVGenerationPS() {}
/** Initialization constructor. */
FLensDistortionUVGenerationPS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FLensDistortionUVGenerationShader(Initializer)
{ }
};
//下面中一个有TEXT,一个没有,这个容易报错
//IMPLEMENT_GLOBAL_SHADER(FMyTestVS, "/Plugin/Foo/Private/MyShader.usf","MainVS", SF_Vertex);
//IMPLEMENT_GLOBAL_SHADER(FMyTestPS, "/Plugin/Foo/Private/MyShader.usf","MainPS", SF_Pixel);
IMPLEMENT_SHADER_TYPE(, FLensDistortionUVGenerationVS, TEXT("/Plugin/Foo/Private/MyShader.usf"), TEXT("MainVS"), SF_Vertex)
IMPLEMENT_SHADER_TYPE(, FLensDistortionUVGenerationPS, TEXT("/Plugin/Foo/Private/MyShader.usf"), TEXT("MainPS"), SF_Pixel)
编写着色器文件.ush和对应的C++结构体
MyShader.ush
// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
/*=============================================================================
LensDistortionUVGeneration.usf:将光学变形和不
变形UV置换贴图生成到一个渲染目标中。
像素着色器直接计算变形视口UV,
不对使用Sv_Position和参考方程式的视口UV置换执行变形,
并将它们保存到红色和绿色的通道中。
为避免用费拉里法进行解析、
或在 GPU 上执行牛顿法计算不变形视口 UV 这两种方式
来对视口UV置换进行变形,这对着色器的工作方式如下:顶点着色器不对网格的顶点执行变形,
并下传到像素着色器视口 UV 应在屏幕上
所处的位置,而不进行变形。像素
着色器可生成不变形视口UV,
减去像素的视口UV后即可对视口UV置换进行变形。
=============================================================================*/
#include "/Engine/Public/Platform.ush"
// 视口UV坐标中的像素大小。
float2 PixelUVSize;
// K1, K2, K3
float3 RadialDistortionCoefs;
// P1, P2
float2 TangentialDistortionCoefs;
// 未变形视口的相机矩阵。
float4 UndistortedCameraMatrix;
// 变形视口的相机矩阵。
float4 DistortedCameraMatrix;
// 对渲染目标输出乘法和加法。
float2 OutputMultiplyAndAdd;
// 不对V.z=1视图位置进行变形。
float2 UndistortNormalizedViewPosition(float2 V)
{
float2 V2 = V * V;
float R2 = V2.x + V2.y;
// 径向变形(额外添加括号是为匹配 MF_Undistortion.uasset)。
float2 UndistortedV = V * (1.0 + R2 * (RadialDistortionCoefs.x + R2 * (RadialDistortionCoefs.y + R2 * RadialDistortionCoefs.z)));
// 切向变形。
UndistortedV.x += TangentialDistortionCoefs.y * (R2 + 2 * V2.x) + 2 * TangentialDistortionCoefs.x * V.x * V.y;
UndistortedV.y += TangentialDistortionCoefs.x * (R2 + 2 * V2.y) + 2 * TangentialDistortionCoefs.y * V.x * V.y;
return UndistortedV;
}
// 返回变形视口UV的未变形视口UV。
//
// 注意:
// UV创建于左下角。
float2 UndistortViewportUV(float2 ViewportUV)
{
// 已变形视口UV -> 已变形视图位置(z=1)
float2 DistortedViewPosition = (ViewportUV - DistortedCameraMatrix.zw) / DistortedCameraMatrix.xy;
// 计算未变形的视图位置(z=1)
float2 UndistortedViewPosition = UndistortNormalizedViewPosition(DistortedViewPosition);
// 未变形的视图位置(z=1) -> 未变形的视口UV。
return UndistortedCameraMatrix.xy * UndistortedViewPosition + UndistortedCameraMatrix.zw;
}
// 翻转UV的y组件。
float2 FlipUV(float2 UV)
{
return float2(UV.x, 1 - UV.y);
}
void MainVS(
in uint GlobalVertexId :SV_VertexID,
out float2 OutVertexDistortedViewportUV :TEXCOORD0,
out float4 OutPosition :SV_POSITION
)
{
// 计算单元索引。
uint GridCellIndex = GlobalVertexId / 6;
// 计算网格中单元行和列的ID。
uint GridColumnId = GridCellIndex / GRID_SUBDIVISION_Y;
uint GridRowId = GridCellIndex - GridColumnId * GRID_SUBDIVISION_Y;
// 计算双三角形网格单元中的顶点ID。
uint VertexId = GlobalVertexId - GridCellIndex * 6;
// 计算单元中三角形顶点源自左下角的UV坐标。
float2 CellVertexUV = float2(0x1 & ((VertexId + 1) / 3), VertexId & 0x1);
// 计算网格中顶点源自左上角的UV。
float2 GridInvSize = 1.f / float2(GRID_SUBDIVISION_X, GRID_SUBDIVISION_Y);
float2 GridVertexUV = FlipUV(
GridInvSize * (CellVertexUV + float2(GridColumnId, GridRowId)));
// 标准不含半像素位移。
GridVertexUV -= PixelUVSize * 0.5;
// 输出顶点位置。
OutPosition = float4(FlipUV(
UndistortViewportUV(GridVertexUV) + PixelUVSize * 0.5) * 2 - 1, 0, 1);
// 输出顶点源自左上角的UV。
OutVertexDistortedViewportUV = GridVertexUV;
}
void MainPS(
in noperspective float2 VertexDistortedViewportUV :TEXCOORD0,
in float4 SvPosition :SV_POSITION,
out float4 OutColor :SV_Target0
)
{
// 计算像素源自左上角的UV。
float2 ViewportUV = SvPosition.xy * PixelUVSize;
// 标准不含半像素位移。
ViewportUV -= PixelUVSize * 0.5;
float2 DistortUVtoUndistortUV = (UndistortViewportUV((ViewportUV))) - ViewportUV;
float2 UndistortUVtoDistortUV = VertexDistortedViewportUV - ViewportUV;
// 输出置换通道。
OutColor = OutputMultiplyAndAdd.y + OutputMultiplyAndAdd.x * float4(
DistortUVtoUndistortUV, UndistortUVtoDistortUV);
}
c++结构体申明
/** 光学变形/不变形的数学相机模型。
*
* 相机矩阵 =
* | F.X 0 C.x |
* | 0 F.Y C.Y |
* | 0 0 1 |
*/
USTRUCT(BlueprintType)
struct FFooCameraModel
{
GENERATED_USTRUCT_BODY()
FFooCameraModel()
{
K1 = K2 = K3 = P1 = P2 = 0.f;
F = FVector2D(1.f, 1.f);
C = FVector2D(0.5f, 0.5f);
}
/** Radial parameter #1.*/
UPROPERTY(Interp, EditAnywhere, BlueprintReadWrite, Category = "Lens Distortion|Camera Model")
float K1;
/** 径向参数 #2。*/
UPROPERTY(Interp, EditAnywhere, BlueprintReadWrite, Category = "Lens Distortion|Camera Model")
float K2;
/** 径向参数 #3。*/
UPROPERTY(Interp, EditAnywhere, BlueprintReadWrite, Category = "Lens Distortion|Camera Model")
float K3;
/** 切向参数 #1。*/
UPROPERTY(Interp, EditAnywhere, BlueprintReadWrite, Category = "Lens Distortion|Camera Model")
float P1;
/** 切向参数 #2。*/
UPROPERTY(Interp, EditAnywhere, BlueprintReadWrite, Category = "Lens Distortion|Camera Model")
float P2;
/** 相机矩阵的Fx和Fy。*/
UPROPERTY(Interp, EditAnywhere, BlueprintReadWrite, Category = "Lens Distortion|Camera Model")
FVector2D F;
/** 相机矩阵的Cx和Cy。*/
UPROPERTY(Interp, EditAnywhere, BlueprintReadWrite, Category = "Lens Distortion|Camera Model")
FVector2D C;
/** 不在视图空间中进行3D向量变形(x, y, z=1.f)并返回(x', y', z'=1.f)。*/
FVector2D UndistortNormalizedViewPosition(FVector2D V) const;
/** 返回不变形渲染所需的过扫描因子,避免出现未渲染的变形像素。*/
float GetUndistortOverscanFactor(
float DistortedHorizontalFOV,
float DistortedAspectRatio) const;
/** 在输出渲染目标中绘制UV置换贴图。
* - 红色和绿色通道负责变形置换;
* - 蓝色和透明通道负责不变形置换。
* @param World 获取渲染设置的当前场景(如特征场景)。
* @param DistortedHorizontalFOV 变形渲染中理想的水平视野。
* @param DistortedAspectRatio 变形渲染中理想的高宽比。
* @param UndistortOverscanFactor 未变形渲染的过扫描因子。
* @param OutputRenderTarget 进行绘制的渲染目标。不必拥有和变形渲染相同的分辨率或高宽比。
* @param OutputMultiply 应用在置换上的乘法因子。
* @param OutputAdd 保存到输出渲染目标中之前被添加到相乘置换的值。
*/
void DrawUVDisplacementToRenderTarget2(
class UWorld* World,
float DistortedHorizontalFOV,
float DistortedAspectRatio,
float UndistortOverscanFactor,
class UTextureRenderTarget2D* OutputRenderTarget,
float OutputMultiply,
float OutputAdd) const;
/** 对比两个光学变形模型并返回其是否相同。*/
bool operator == (const FFooCameraModel& Other) const
{
return (
K1 == Other.K1 &&
K2 == Other.K2 &&
K3 == Other.K3 &&
P1 == Other.P1 &&
P2 == Other.P2 &&
F == Other.F &&
C == Other.C);
}
/** 对比两个光学变形模型并返回其是否不同。*/
bool operator != (const FFooCameraModel& Other) const
{
return !(*this == Other);
}
};
申明全局着色器类型
#include "Engine/TextureRenderTarget2D.h"
#include "Engine/World.h"
#include "GlobalShader.h"
#include "PipelineStateCache.h"
#include "ProfilingDebugging/RealtimeGPUProfiler.h"
#include "RHIStaticStates.h"
#include "SceneInterface.h"
#include "ShaderParameterUtils.h"
#include "Logging/MessageLog.h"
#include "TextureResource.h"
#include "DataDrivenShaderPlatformInfo.h"
#include "RenderingThread.h"
在C++申明、绑定着色器参数,和赋值
class FLensDistortionUVGenerationShader : public FGlobalShader
{
DECLARE_INLINE_TYPE_LAYOUT(FLensDistortionUVGenerationShader, NonVirtual);
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM5);
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("GRID_SUBDIVISION_X"), kGridSubdivisionX);
OutEnvironment.SetDefine(TEXT("GRID_SUBDIVISION_Y"), kGridSubdivisionY);
}
FLensDistortionUVGenerationShader() {}
FLensDistortionUVGenerationShader(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
PixelUVSize.Bind(Initializer.ParameterMap, TEXT("PixelUVSize"));
RadialDistortionCoefs.Bind(Initializer.ParameterMap, TEXT("RadialDistortionCoefs"));
TangentialDistortionCoefs.Bind(Initializer.ParameterMap, TEXT("TangentialDistortionCoefs"));
DistortedCameraMatrix.Bind(Initializer.ParameterMap, TEXT("DistortedCameraMatrix"));
UndistortedCameraMatrix.Bind(Initializer.ParameterMap, TEXT("UndistortedCameraMatrix"));
OutputMultiplyAndAdd.Bind(Initializer.ParameterMap, TEXT("OutputMultiplyAndAdd"));
}
//这个很重要
template<typename TShaderRHIParamRef>
void SetParameters(
FRHICommandListImmediate& RHICmdList,
const TShaderRHIParamRef ShaderRHI,
const FCompiledCameraModel& CompiledCameraModel,
const FIntPoint& DisplacementMapResolution)
{
FVector2f PixelUVSizeValue(
1.f / float(DisplacementMapResolution.X), 1.f / float(DisplacementMapResolution.Y));
FVector3f RadialDistortionCoefsValue(
CompiledCameraModel.OriginalCameraModel.K1,
CompiledCameraModel.OriginalCameraModel.K2,
CompiledCameraModel.OriginalCameraModel.K3);
FVector2f TangentialDistortionCoefsValue(
CompiledCameraModel.OriginalCameraModel.P1,
CompiledCameraModel.OriginalCameraModel.P2);
SetShaderValue(RHICmdList, ShaderRHI, PixelUVSize, PixelUVSizeValue);
SetShaderValue(RHICmdList, ShaderRHI, DistortedCameraMatrix, FVector4f(CompiledCameraModel.DistortedCameraMatrix));
SetShaderValue(RHICmdList, ShaderRHI, UndistortedCameraMatrix, FVector4f(CompiledCameraModel.UndistortedCameraMatrix));
SetShaderValue(RHICmdList, ShaderRHI, RadialDistortionCoefs, RadialDistortionCoefsValue);
SetShaderValue(RHICmdList, ShaderRHI, TangentialDistortionCoefs, TangentialDistortionCoefsValue);
SetShaderValue(RHICmdList, ShaderRHI, OutputMultiplyAndAdd, FVector2f(CompiledCameraModel.OutputMultiplyAndAdd));
}
private:
LAYOUT_FIELD(FShaderParameter, PixelUVSize);
LAYOUT_FIELD(FShaderParameter, RadialDistortionCoefs);
LAYOUT_FIELD(FShaderParameter, TangentialDistortionCoefs);
LAYOUT_FIELD(FShaderParameter, DistortedCameraMatrix);
LAYOUT_FIELD(FShaderParameter, UndistortedCameraMatrix);
LAYOUT_FIELD(FShaderParameter, OutputMultiplyAndAdd);
};
实现像素着色器和顶点着色器
class FLensDistortionUVGenerationVS : public FLensDistortionUVGenerationShader
{
DECLARE_SHADER_TYPE(FLensDistortionUVGenerationVS, Global);
public:
/** Default constructor. */
FLensDistortionUVGenerationVS() {}
/** Initialization constructor. */
FLensDistortionUVGenerationVS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FLensDistortionUVGenerationShader(Initializer)
{
}
};
class FLensDistortionUVGenerationPS : public FLensDistortionUVGenerationShader
{
DECLARE_SHADER_TYPE(FLensDistortionUVGenerationPS, Global);
public:
/** Default constructor. */
FLensDistortionUVGenerationPS() {}
/** Initialization constructor. */
FLensDistortionUVGenerationPS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FLensDistortionUVGenerationShader(Initializer)
{ }
};
GPU中更新数据
数据传递CPU->GPU
DrawUVDisplacementToRenderTarget_RenderThread
void FFooCameraModel::DrawUVDisplacementToRenderTarget2(
UWorld* World,
float DistortedHorizontalFOV,
float DistortedAspectRatio,
float UndistortOverscanFactor,
UTextureRenderTarget2D* OutputRenderTarget,
float OutputMultiply,
float OutputAdd) const
{
check(IsInGameThread());
if (!OutputRenderTarget)
{
FMessageLog("Blueprint").Warning(LOCTEXT("LensDistortionCameraModel_OutputTargetRequired", "DrawUVDisplacementToRenderTarget: Output render target is required."));
return;
}
// Compiles the camera model to know the overscan scale factor.
float TanHalfUndistortedHorizontalFOV = FMath::Tan(DistortedHorizontalFOV * 0.5f) * UndistortOverscanFactor;
float TanHalfUndistortedVerticalFOV = TanHalfUndistortedHorizontalFOV / DistortedAspectRatio;
// Output.
FCompiledCameraModel CompiledCameraModel;
CompiledCameraModel.OriginalCameraModel = *this;
CompiledCameraModel.DistortedCameraMatrix.X = 1.0f / TanHalfUndistortedHorizontalFOV;
CompiledCameraModel.DistortedCameraMatrix.Y = 1.0f / TanHalfUndistortedVerticalFOV;
CompiledCameraModel.DistortedCameraMatrix.Z = 0.5f;
CompiledCameraModel.DistortedCameraMatrix.W = 0.5f;
CompiledCameraModel.UndistortedCameraMatrix.X = F.X;
CompiledCameraModel.UndistortedCameraMatrix.Y = F.Y * DistortedAspectRatio;
CompiledCameraModel.UndistortedCameraMatrix.Z = C.X;
CompiledCameraModel.UndistortedCameraMatrix.W = C.Y;
CompiledCameraModel.OutputMultiplyAndAdd.X = OutputMultiply;
CompiledCameraModel.OutputMultiplyAndAdd.Y = OutputAdd;
const FName TextureRenderTargetName = OutputRenderTarget->GetFName();
FTextureRenderTargetResource* TextureRenderTargetResource = OutputRenderTarget->GameThread_GetRenderTargetResource();
ERHIFeatureLevel::Type FeatureLevel = World->Scene->GetFeatureLevel();
if (FeatureLevel < ERHIFeatureLevel::SM5)
{
FMessageLog("Blueprint").Warning(LOCTEXT("LensDistortionCameraModel_SM5Unavailable", "DrawUVDisplacementToRenderTarget: Requires RHIFeatureLevel::SM5 which is unavailable."));
return;
}
ENQUEUE_RENDER_COMMAND(CaptureCommand)(
[CompiledCameraModel, TextureRenderTargetResource, TextureRenderTargetName, FeatureLevel](FRHICommandListImmediate& RHICmdList)
{
DrawUVDisplacementToRenderTarget_RenderThread(
RHICmdList,
CompiledCameraModel,
TextureRenderTargetName,
TextureRenderTargetResource,
FeatureLevel);
}
);
}
构建渲染管道流程
- 渲染管道流程
- 数据传递
- FGraphicsPipelineStateInitializer GraphicsPSOInit;
- VertexShader->SetParameters(RHICmdList, VertexShader.GetVertexShader(), CompiledCameraModel, DisplacementMapResolution);
- PixelShader->SetParameters(RHICmdList, PixelShader.GetPixelShader(), CompiledCameraModel, DisplacementMapResolution);
static void DrawUVDisplacementToRenderTarget_RenderThread(
FRHICommandListImmediate& RHICmdList,
const FCompiledCameraModel& CompiledCameraModel,
const FName& TextureRenderTargetName,
FTextureRenderTargetResource* OutTextureRenderTargetResource,
ERHIFeatureLevel::Type FeatureLevel)
{
check(IsInRenderingThread());
#if WANTS_DRAW_MESH_EVENTS
FString EventName;
TextureRenderTargetName.ToString(EventName);
SCOPED_DRAW_EVENTF(RHICmdList, SceneCapture, TEXT("LensDistortionDisplacementGeneration %s"), *EventName);
#else
SCOPED_DRAW_EVENT(RHICmdList, DrawUVDisplacementToRenderTarget_RenderThread);
#endif
FRHITexture2D* RenderTargetTexture = OutTextureRenderTargetResource->GetRenderTargetTexture();
RHICmdList.Transition(FRHITransitionInfo(RenderTargetTexture, ERHIAccess::SRVMask, ERHIAccess::RTV));
FRHIRenderPassInfo RPInfo(RenderTargetTexture, ERenderTargetActions::DontLoad_Store);
RHICmdList.BeginRenderPass(RPInfo, TEXT("DrawUVDisplacement"));
{
FIntPoint DisplacementMapResolution(OutTextureRenderTargetResource->GetSizeX(), OutTextureRenderTargetResource->GetSizeY());
// Update viewport.
RHICmdList.SetViewport(
0, 0, 0.f,
DisplacementMapResolution.X, DisplacementMapResolution.Y, 1.f);
// Get shaders.
FGlobalShaderMap* GlobalShaderMap = GetGlobalShaderMap(FeatureLevel);
TShaderMapRef< FLensDistortionUVGenerationVS > VertexShader(GlobalShaderMap);
TShaderMapRef< FLensDistortionUVGenerationPS > PixelShader(GlobalShaderMap);
// Set the graphic pipeline state.
FGraphicsPipelineStateInitializer GraphicsPSOInit;
RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit);
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<false, CF_Always>::GetRHI();
GraphicsPSOInit.BlendState = TStaticBlendState<>::GetRHI();
GraphicsPSOInit.RasterizerState = TStaticRasterizerState<>::GetRHI();
GraphicsPSOInit.PrimitiveType = PT_TriangleList;
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GetVertexDeclarationFVector4();
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader();
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = PixelShader.GetPixelShader();
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit, 0);
// Update viewport.
RHICmdList.SetViewport(
0, 0, 0.f,
OutTextureRenderTargetResource->GetSizeX(), OutTextureRenderTargetResource->GetSizeY(), 1.f);
// Update shader uniform parameters.
VertexShader->SetParameters(RHICmdList, VertexShader.GetVertexShader(), CompiledCameraModel, DisplacementMapResolution);
PixelShader->SetParameters(RHICmdList, PixelShader.GetPixelShader(), CompiledCameraModel, DisplacementMapResolution);
// Draw grid.
uint32 PrimitiveCount = kGridSubdivisionX * kGridSubdivisionY * 2;
RHICmdList.DrawPrimitive(0, PrimitiveCount, 1);
}
RHICmdList.EndRenderPass();
RHICmdList.Transition(FRHITransitionInfo(RenderTargetTexture, ERHIAccess::RTV, ERHIAccess::SRVMask));
}