开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

蛮牛译馆

关注:579

当前位置:游戏蛮牛 技术专区 蛮牛译馆

查看: 852|回复: 12

[Unreal教程] 如何将全局着色器添加到UE4

[复制链接]  [移动端链接]
排名
7947
昨日变化
5

260

主题

298

帖子

1511

积分

Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15

UID
159865
好友
9
蛮牛币
3908
威望
0
注册时间
2016-8-1
在线时间
623 小时
最后登录
2017-10-15

蛮牛译员

发表于 2017-9-29 14:11:10 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
如何将全局着色器添加到UE4


在虚幻引擎4中,全局着色器是可以从C ++方面使用的渲染后处理效果,调度计算着色器,清除屏幕等的着色器(即,不对材质或网格进行操作的着色器)。 有时,需要更高级的功能来实现

所需的外观,并且需要定制着色器传递。 这样做比较简单,我将在这里解释一下。
UE4从引擎/着色器文件夹中读取.usf文件(虚幻着色器文件)。 任何新的着色器都需要将源文件放在这里。 从4.17开始,着色器也可以从插件(插件/着色器)读取。 我建议在您的ConsoleVariables.ini文件中启用r.ShaderDevelopmentMode = 1以便于开发。 查看文档了解更多信息。

我们先从您的引擎/着色器文件夹中添加一个新的.usf文件。 我们称它为MyTest.usf。 然后添加一个简单的直通顶点着色器和一个返回自定义颜色的像素着色器:

[C++] 纯文本查看 复制代码
// MyTest.usf 

// Simple pass-through vertex shader

void MainVS(
        in float4 InPosition : ATTRIBUTE0,
        out float4 Output : SV_POSITION
)
{
        Output = InPosition;
}

// Simple solid color pixel shader
float4 MyColor;
float4 MainPS() : SV_Target0
{
        return MyColor;
}



现在,为了让UE4拿起着色器并开始编译,我们需要声明一个C ++类。 我们从顶点着色器开始:

定店主搜而起.png

这里有一些要求:



  • 这是FGlobalShader的子类。 因此,它将最终在全球着色器地图(这意味着我们不需要材料找到它)。
  • DECLARE_EXPORTED_SHADER_TYPE()宏的使用将生成着色器类型的序列化所需的导出等。第三个参数是一个外部链接的类型,用于代码模块的外部链接,如果需要,着色器模块将生存(例如C ++代码, t住在渲染器模块中)。
  • 两个构造函数,默认和序列化。
  • 需要决定是否在特定情况下编译这个着色器的ShouldCache()函数(例如,我们可能不希望在具有非计算着色器的RHI上编译计算着色器)。



随着类声明,我们现在可以将着色器类型注册到UE4的列表中:

[C++] 纯文本查看 复制代码
// This needs to go on a cpp file
IMPLEMENT_SHADER_TYPE(, FMyTestVS, TEXT("MyTest"), TEXT("MainVS"), SF_Vertex);



该宏将类型(FMyTestVS)映射到.usf文件(MyTest.usf),着色器入口点(MainVS)和频率/着色器阶段(SF_Vertex)。 只要它的ShouldCache()方法返回true,它也会使着色器被添加到编译列表中。

注意:无论您将FGlobalShader添加到实际引擎启动前必须加载的模块,或者您将得到一个assert,如“引擎初始化之后加载着色器类型,在模块上使用ELoadingPhase :: PostConfigInit以使其早期加载 “我们目前不允许在游戏或编辑器启动后加载自己的着色器类型的动态模块。



现在我们来宣布更有趣的Pixel Shader:

[C++] 纯文本查看 复制代码
class FMyTestPS : public FGlobalShader
{
        DECLARE_EXPORTED_SHADER_TYPE(FMyTestPS, Global, /*MYMODULE_API*/);
 
        FShaderParameter MyColorParameter;
 
        FMyTestPS() { }
        FMyTestPS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
                : FGlobalShader(Initializer)
        {
                MyColorParameter.Bind(Initializer.ParameterMap, TEXT("MyColor"), SPF_Mandatory);
        }
 
        static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
        {
                FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
                // Add your own defines for the shader code
                OutEnvironment.SetDefine(TEXT("MY_DEFINE"), 1);
        }
 
        static bool ShouldCache(EShaderPlatform Platform)
        {
                // Could skip compiling for Platform == SP_METAL for example
                return true;
        }
 
        // FShader interface.
        virtual bool Serialize(FArchive& Ar) override
        {
                bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
                Ar << MyColorParameter;
                return bShaderHasOutdatedParameters;
        }
 
        void SetColor(FRHICommandList& RHICmdList, const FLinearColor& Color)
        {
                SetShaderValue(RHICmdList, GetPixelShader(), MyColorParameter, Color);
        }
};

// Same source file as before, different entry point
IMPLEMENT_SHADER_TYPE(, FMyTestPS, TEXT("MyTest"), TEXT("MainPS"), SF_Pixel);



在这个类中,我们现在正在从.usf文件中显示着色器参数MyColor:


  • FShaderParameter MyColorParameter成员被添加到类中,该类将保存运行时的信息,以便能够找到绑定,允许在运行时设置参数的值。
  • 在序列化构造函数中,我们通过名称将参数绑定到ParameterMap,这必须匹配.usf文件的名称。
  • 当相同的C ++类定义不同的行为并且能够在着色器中设置#define值时,将使用新的ModifyCompilationEnvironment()函数。
  • Serialize()方法是必需的。 这是从着色器的绑定(在序列化构造函数中匹配)的编译/烹饪时间信息在运行时被加载和存储的地方。
  • 最后,我们有一个自定义的SetColor()方法,它显示了如何在运行时使用指定的值设置MyColor参数。




现在,我们用一个简单的函数来绘制一个使用这些着色器类型的全屏四边形:

[C++] 纯文本查看 复制代码
void RenderMyTest(FRHICommandList& RHICmdList, ERHIFeatureLevel::Type FeatureLevel, const FLinearColor& Color)
{
        // Get the collection of Global Shaders
        auto ShaderMap = GetGlobalShaderMap(FeatureLevel);

        // Get the actual shader instances off the ShaderMap
        TShaderMapRef MyVS(ShaderMap);
        TShaderMapRef MyPS(ShaderMap);

        // Declare a bound shader state using those shaders and apply it to the command list
        static FGlobalBoundShaderState MyTestBoundShaderState;
        SetGlobalBoundShaderState(RHICmdList, FeatureLevel, MyTestBoundShaderState, GetVertexDeclarationFVector4(), *MyVS, *MyPS);

        // Call our function to set up parameters
        MyPS->SetColor(RHICmdList, Color);
 
        // Setup the GPU in prep for drawing a solid quad
        RHICmdList.SetRasterizerState(TStaticRasterizerState::GetRHI());
        RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
        RHICmdList.SetDepthStencilState(TStaticDepthStencilState::GetRHI(), 0);
 
        // Setup the vertices
        FVector4 Vertices[4];
        Vertices[0].Set(-1.0f, 1.0f, 0, 1.0f);
        Vertices[1].Set(1.0f, 1.0f, 0, 1.0f);
        Vertices[2].Set(-1.0f, -1.0f, 0, 1.0f);
        Vertices[3].Set(1.0f, -1.0f, 0, 1.0f);

        // Draw the quad
        DrawPrimitiveUP(RHICmdList, PT_TriangleStrip, 2, Vertices, sizeof(Vertices[0]));
}



如果你想在你的代码库中测试这个,你可以尝试声明一个控制台变量,这样它就可以像运行时那样切换:

[C++] 纯文本查看 复制代码
static TAutoConsoleVariable CVarMyTest(
        TEXT("r.MyTest"),
        0,
        TEXT("Test My Global Shader, set it to 0 to disable, or to 1, 2 or 3 for fun!"),
        ECVF_RenderThreadSafe
);
 
void FDeferredShadingSceneRenderer::RenderFinish(FRHICommandListImmediate& RHICmdList)
{
        [...]
        // ***
        // Inserted code, just before finishing rendering, so we can overwrite the screen’s contents!
        int32 MyTestValue = CVarMyTest.GetValueOnAnyThread();
        if (MyTestValue != 0)
        {
                FLinearColor Color(MyTestValue == 1, MyTestValue == 2, MyTestValue == 3, 1);
                RenderMyTest(RHICmdList, FeatureLevel, Color);
        }
        // End Inserted code
        // ***
        FSceneRenderer::RenderFinish(RHICmdList);
        [...]
}



在这一点上,您应该可以测试我们的新的全球着色器! 运行您的项目,然后使用波浪号(〜)拉起控制台并输入r.MyTest 1.然后键入r.MyTest 2和/或r.MyTest 3来更改颜色。 使用r.MyTest 0禁用通行证。


调试生成的源代码
看看博客文章调试着色器编译过程,如果你想能够调试.usf文件的编译和/或看到处理的文件。


总结
您可以在一个未用的游戏/编辑器运行时修改.usf文件,然后按Ctrl + Shift +。 (期间)或类型重编译器在控制台中更改,以拾取并重建您的着色器以进行快速迭代!






原文标题:How to Add Global Shaders to UE4



回复

使用道具 举报

7日久生情
1975/5000
排名
6332
昨日变化
48

4

主题

1622

帖子

1975

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
209186
好友
3
蛮牛币
2561
威望
0
注册时间
2017-3-1
在线时间
191 小时
最后登录
2017-10-23
发表于 2017-9-29 16:04:22 | 显示全部楼层
谢谢分享

回复

使用道具 举报

排名
28225
昨日变化
22

0

主题

6

帖子

25

积分

Rank: 1

UID
239875
好友
0
蛮牛币
25
威望
0
注册时间
2017-8-26
在线时间
9 小时
最后登录
2017-10-23
发表于 2017-9-29 19:15:39 | 显示全部楼层
666666666厉害了

回复 支持 反对

使用道具 举报

排名
51807
昨日变化
16

0

主题

14

帖子

25

积分

Rank: 1

UID
151000
好友
0
蛮牛币
54
威望
0
注册时间
2016-6-6
在线时间
9 小时
最后登录
2017-10-23
发表于 2017-9-30 09:53:31 | 显示全部楼层
感谢分享

回复

使用道具 举报

3偶尔光临
186/300
排名
10667
昨日变化
154

1

主题

61

帖子

186

积分

Rank: 3Rank: 3Rank: 3

UID
241851
好友
0
蛮牛币
405
威望
0
注册时间
2017-9-6
在线时间
56 小时
最后登录
2017-10-23
发表于 2017-9-30 13:10:24 | 显示全部楼层
感谢分享

回复

使用道具 举报

5熟悉之中
611/1000
排名
3000
昨日变化
27

0

主题

53

帖子

611

积分

Rank: 5Rank: 5

UID
97454
好友
1
蛮牛币
1897
威望
0
注册时间
2015-5-4
在线时间
180 小时
最后登录
2017-10-23
发表于 2017-9-30 15:05:05 | 显示全部楼层
在虚幻引擎4中,全局着色器是可以从C ++方面使用的渲染后处理效果,调度计算着色器,清除屏幕等的着色器(即,不对材质或网格进行操作的着色器)。 有时,需要更高级的功能来实现

所需的外观,并且需要定制着色器传递。 这样做比较简单,我将在这里解释一下。
UE4从引擎/着色器文件夹中读取.usf文件(虚幻着色器文件)。 任何新的着色器都需要将源文件放在这里。 从4.17开始,着色器也可以从插件(插件/着色器)读取。 我建议在您的ConsoleVariables.ini文件中启用r.ShaderDevelopmentMode = 1以便于开发。 查看文档了解更多信息。

回复 支持 反对

使用道具 举报

7日久生情
2114/5000
排名
255
昨日变化

2

主题

61

帖子

2114

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
71116
好友
0
蛮牛币
11036
威望
0
注册时间
2015-1-26
在线时间
477 小时
最后登录
2017-10-23
发表于 2017-10-1 10:51:03 | 显示全部楼层
好帖留名

回复

使用道具 举报

5熟悉之中
751/1000
排名
8884
昨日变化
122

2

主题

547

帖子

751

积分

Rank: 5Rank: 5

UID
241666
好友
0
蛮牛币
2889
威望
0
注册时间
2017-9-6
在线时间
108 小时
最后登录
2017-10-24
发表于 2017-10-6 06:36:15 来自Mobile--- | 显示全部楼层
感谢分享

回复

使用道具 举报

排名
13195
昨日变化
2

0

主题

31

帖子

93

积分

Rank: 2Rank: 2

UID
229748
好友
0
蛮牛币
113
威望
0
注册时间
2017-7-1
在线时间
18 小时
最后登录
2017-10-16
发表于 2017-10-9 09:26:07 | 显示全部楼层
学习了 收藏了
[发帖际遇]: 苏洛 乐于助人,奖励 3 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

0

主题

5

帖子

5

积分

Rank: 1

UID
247608
好友
0
蛮牛币
6
威望
0
注册时间
2017-10-9
在线时间
3 小时
最后登录
2017-10-17
发表于 2017-10-9 13:10:22 | 显示全部楼层
666666666666

回复

使用道具 举报

5熟悉之中
611/1000
排名
3000
昨日变化
27

0

主题

53

帖子

611

积分

Rank: 5Rank: 5

UID
97454
好友
1
蛮牛币
1897
威望
0
注册时间
2015-5-4
在线时间
180 小时
最后登录
2017-10-23
发表于 2017-10-10 10:07:06 | 显示全部楼层

如何将全局着色器添加到UE4


在虚幻引擎4中,全局着色器是可以从C ++方面使用的渲染后处理效果,调度计算着色器,清除屏幕等的着色器(即,不对材质或网格进行操作的着色器)。 有时,需要更高级的功能来实现

所需的外观,并且需要定制着色器传递。 这样做比较简单,我将在这里解释一下。
UE4从引擎/着色器文件夹中读取.usf文件(虚幻着色器文件)。 任何新的着色器都需要将源文件放在这里。 从4.17开始,着色器也可以从插件(插件/着色器)读取。 我建议在您的ConsoleVariables.ini文件中启用r.ShaderDevelopmentMode = 1以便于开发。 查看文档了解更多信息

回复 支持 反对

使用道具 举报

6蛮牛粉丝
1293/1500
排名
902
昨日变化

1

主题

46

帖子

1293

积分

Rank: 6Rank: 6Rank: 6

UID
100193
好友
1
蛮牛币
3041
威望
0
注册时间
2015-5-14
在线时间
318 小时
最后登录
2017-10-12
发表于 2017-10-10 17:34:58 | 显示全部楼层
这种东西是用来做PostProcess后处理的吧,叫全局不是太贴切。暂时还不懂。这类着色器不要传递什么参数,确实用用其他插件做也可以

回复 支持 反对

使用道具 举报

排名
25393
昨日变化
14

0

主题

18

帖子

38

积分

Rank: 1

UID
224027
好友
0
蛮牛币
3
威望
0
注册时间
2017-5-27
在线时间
10 小时
最后登录
2017-10-12
发表于 2017-10-11 15:39:35 | 显示全部楼层
感谢分享

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

快速回复 返回顶部 返回列表