结合我最近学习大佬们分享的教程来讲,我最大的感受:
1.大多数的教程关注如何实现一个GlobalShader:一堆代码的组织。But,Why we should do like this?
2.版本问题!UE作为一个开源代码,每次迭代,版本的更新除了带来新的视觉盛宴,留给开发者的还有一堆接口变更问题,有很多教程基于较早的版本,虽然版主大人还在不断努力,试图提供尽可能多的帮助,但是我不禁要感叹太难了,,,所以如何修成流水的版本,铁打的大神可能才是学习UE源码的根本意义。
由于以上两点,我不得不承认学得太累太苦,甚至不知道自己在干嘛?我花了大量时间在网上找教程,学习,但是我发现最好的资料就是UE的源码,但是前提是要能看懂!于是我花费了大量时间先摸清GlobalShader的基本框架,总算摸到了一点皮毛,在此,我想分享一点自己的学习经验,记录自己,同时希望也能帮到他人少走一点弯路。
以下是我根据现在的理解注释的一段来自UE4.25.4的源码,虽然是来自4.25.4,但我相信通过我的介绍,之后换版本也能轻松上手。
1.不同版本如何学习GlobalShader?
打开你的源码,直接搜索“public FGlobalShader”,没错我们就是要找一个派生自FGlobalShader的子类来一探究竟,这里我找到的是TDeferredLightHairVS;
2.分享我对这个类的注释
class TDeferredLightHairVS : public FGlobalShader
{
DECLARE_SHADER_TYPE(TDeferredLightHairVS, Global);
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);
// 将字符串压入Shader成为宏,并设置宏值为1
OutEnvironment.SetDefine(TEXT("SHADER_HAIR"), 1);
}
TDeferredLightHairVS() {}
TDeferredLightHairVS(const ShaderMetaType::CompiledShaderInitializerType& Initializer) :
FGlobalShader(Initializer)
{
// 建立参数变量与Shader的关系,进行数据通信
MaxViewportResolution.Bind(Initializer.ParameterMap, TEXT("MaxViewportResolution"));
HairVisibilityNodeCount.Bind(Initializer.ParameterMap, TEXT("HairVisibilityNodeCount"));
}
void SetParameters(FRHICommandList& RHICmdList, const FViewInfo& View, const FHairStrandsVisibilityData* VisibilityData)
{
FRHIVertexShader* ShaderRHI = RHICmdList.GetBoundVertexShader();
// 调用父类函数完成默认操作
FGlobalShader::SetParameters<FViewUniformShaderParameters>(RHICmdList, ShaderRHI, View.ViewUniformBuffer);
if (!VisibilityData)
{
return;
}
if (HairVisibilityNodeCount.IsBound() && VisibilityData->NodeCount)
{
// CommandList,ShaderRef,参数名,参数值
SetTextureParameter(RHICmdList, ShaderRHI, HairVisibilityNodeCount, VisibilityData->NodeCount->GetRenderTargetItem().ShaderResourceTexture);
}
// CommandList,ShaderRef,参数名,参数值
SetShaderValue(RHICmdList, ShaderRHI, MaxViewportResolution, VisibilityData->SampleLightingViewportResolution);
}
private:
// 数值类型的shader资源
LAYOUT_FIEL