我的专栏目录:
小IVan:专题概述及目录前面介绍了一般数据的传输方式,这一卷我们将一起来使用更高级的数据传输方式UniformBuffer。这个问题困扰了我两天,查了很多资料,翻了很多论坛也没找到解决办法。这里要特别感谢一位QQ昵称是“August”的朋友的指点帮助。
先看下效果吧
可以看到这次是使用一个UniformBuffer在控制整个颜色的变换了。虽然效果很简单,但是最重要的其实是如何上传UniformBuffer。
关于UE4的Uniform buffer(CPU写,GPU只读),在D3D里相当于constbuffer,在OpenGL里相当于uniformbuffer,而UE4的Uniform buffer比较特殊的是: 在usf并没有采用hlsl的const buffer语法去定义uniformbuffer,从一些资料得知,可能的原因是为了统一和跨平台。如OpenGL的阉割版OpenGL es 2.0不支持uniformbuffer相关的语法。也就是说,UE4的Uniform buffer是epic自己封装,在某些平台上,是用模拟的方式达到uniformbuffer的功能,在usf里没有直接的uniformbuffer定义语法,这方面是UE的shader编译器动态生成相关的定义代码。Uniform buffer在c++用以下几个宏实现:
BEGIN_UNIFORM_BUFFER_STRUCT
DECLARE_UNIFORM_BUFFER_STRUCT_MEMBER
END_UNIFORM_BUFFER_STRUCT
IMPLEMENT_UNIFORM_BUFFER_STRUCT
在代码里是这样的(如下图所示)(注意那个逗号):
这样就声明了一个uniformbuffer。这几个宏回帮我们在渲染线程实现一些类的声明和渲染资源的准备。下面就是我们需要在c++层来设置这个uniformbuffer了,既然需要设置,那么我们就在c++层声明一个结构体用来设置这个uniformbuffer
再用SetUniformBufferParameterImmediatehan函数设置一下:
这样便完成了c++层的uniformbuffer的数据传输。
这里需要值得注意的是我们HLSL代码可以直接使用这个uniformbuffer,虚幻4会自动给我们生成一个uniformbuffer的HLSL代码然后给我们include到Common.usf里面,所以shader代码必须包含Common.ush。
我们再来捋一下思路。首先我们用虚幻的那几个宏,声明并准备一个UniformBuffer。这个UniformBuffer并不需要在HLSL文件里声明对应的变量。因为虚幻考虑到优化和跨平台,所以会帮我们封装然后生成这个UniformBuffer的HLSL代码,我们在shader里直接调用即可。但是虚幻生成的这些HLSL代码是被Common.usf包含的,所以我们需要在我们自己的shader文件里包含Common.ush才行,如果不做这一步会导致HLSL编译失败。我们在c++层声明了一个和Uniform数据结构类似的结构体用于c++层向渲染层传数据。再用SetUniformBufferParameterImmediatehan设置buffer的值。
下面是完整代码:
MyShaderTest.h
#pragma once
#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "Classes/Kismet/BlueprintFunctionLibrary.h"
#include "MyShaderTest.generated.h"