Using C++ shaders from within a plugin

Right now, the official recommended way to use a specific shader from C++ is via the IMPLEMENT_SHADER_TYPE macro. This macro (once all is said and done) looks for a specific filename within the Engine/Shaders directory.

This is a very awkward place for plugins, since it requires that any user of the plugin install the plugin and then install all used shaders. It also means that multiple projects with different plugins cannot transparently use the same UE4 installation.

Ideally, it should be possible to put shaders inside the plugin itself so they can be read via IMPLEMENT_SHADER_TYPE. There’s presumably a way to include content, but shaders themselves don’t seem to work this way - the code appears to always append the root engine directory, and there’s no way to retrieve a plugin directory or otherwise refer to the contents of a plugin.

Is there something important I’m missing, or is this a feature that would need to be implemented?

This is a feature that would need to be developed, I know I read somewhere that they were in fact investigating a way to accomplish this, so in future we may have “Engine/Shaders” for engine shaders, then “[PLUGIN]/Shaders” for specific plugin shaders.

Hi guys! Any update on that?

New: Global Shader Support For Plugins

You can now add new global shaders
inside of Plugins and Projects! Taking
advantage of changes made to the
shader compiler and shader directory
file structure, Plugins and Projects
can provide their own Shaders. You can
look at the LensDistortion plugin for
a simple example
(Engine/Plugins/Compositing/LensDistortion).

Notes:

Plugin and Project modules that have
global shaders require use of the
PostConfigInit loading phase. Shader
support in Plugins and Projects is
still experimental. Plugins and
Projects can include other plugins’
USH files in the Public directory
freely. It is the responsibility of
the Plugin author to handle
inter-plugin dependencies correctly.
USF files should only be located in
the Private directory. All calls to
IMPLEMENT_SHADER_TYPE, should now
include the full path of the USF
shader file (e.g.
“/Engine/Private/Foo.usf” or
“/Plugin/FooBar/Private/MyComputeShader.usf”).
C++ Generated files should be mapped
within the /Engine/Generated/ virtual
directory. Shaders/ directory requires
at least a Private/ or Public/
directory. The Generated/ directory
should not exist.

4.17 release notes

More on that: An official blog post with not many information, hard to make it compile, a little.

In fact, I have a comment to add here:
"“/Plugin/FooBar/Private/MyComputeShader.usf” ← is not working for me. I checked typos, but It’s not able to find it… I’ll update the answer when I find out what’s going on

You should also add something like this to your FFooModule::StartupModule() for your Foo plugin:

{

FString PluginShaderDir = FPaths::Combine(IPluginManager::Get().FindPlugin(TEXT("Foo"))->GetBaseDir(), TEXT("Shaders"));
AddShaderSourceDirectoryMapping(TEXT("/Plugin/Foo"), PluginShaderDir);

}

Thanks, that comment saved me a lot of debugging.
It’s a shame it’s not written in the ShaderInPlugin documentation.

Hello all, when adding compute shaders in plugin, I encountered some error"LogModuleManager Unable to load dll There may be an operating system error or the module may not be properly set up.
I tried to narrow down the issue, and found it’s related with c++ shader class and IMPLEMENT_GLOBAL_SHADER pair. Defining only first pair of shader looks good

EDIT: fixed for myself, cause of bool type in shader parameter struct