├── .gitignore ├── Resources ├── Icon128.ai └── Icon128.png ├── Shaders └── Private │ ├── CombineCS.usf │ ├── ConvertCS.usf │ └── QuadUVVS.usf ├── ShadersPlus.uplugin └── Source └── ShadersPlus ├── Private ├── Combine.cpp ├── Convert.cpp ├── Definitions │ ├── CombineCS.cpp │ ├── ConvertCS.cpp │ └── QuadUVVS.cpp ├── ImageWriter.cpp ├── Polyfills │ └── ImageWriteQueue │ │ └── ImagePixelData.h ├── ShaderInstance.cpp ├── ShadersPlusModule.cpp ├── ShadersPlusModule.h └── ShadersPlusUtilities.cpp ├── Public ├── Combine.h ├── Convert.h ├── Definitions │ ├── CombineCS.h │ ├── ConvertCS.h │ └── QuadUVVS.h ├── IShadersPlusModule.h ├── ImageWriter.h ├── ShaderInstance.h ├── ShadersPlusMacros.h └── ShadersPlusUtilities.h └── ShadersPlus.Build.cs /.gitignore: -------------------------------------------------------------------------------- 1 | # Visual Studio 2015 user specific files 2 | .vs/ 3 | 4 | # Visual Studio 2015 database file 5 | *.VC.db 6 | 7 | # Compiled Object files 8 | *.slo 9 | *.lo 10 | *.o 11 | *.obj 12 | 13 | # Precompiled Headers 14 | *.gch 15 | *.pch 16 | 17 | # Compiled Dynamic libraries 18 | *.so 19 | *.dylib 20 | *.dll 21 | 22 | # Fortran module files 23 | *.mod 24 | 25 | # Compiled Static libraries 26 | *.lai 27 | *.la 28 | *.a 29 | *.lib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.ipa 36 | 37 | # These project files can be generated by the engine 38 | *.xcodeproj 39 | *.xcworkspace 40 | *.sln 41 | *.suo 42 | *.opensdf 43 | *.sdf 44 | *.VC.db 45 | *.VC.opendb 46 | 47 | # Precompiled Assets 48 | SourceArt/**/*.png 49 | SourceArt/**/*.tga 50 | 51 | # Binary Files 52 | Binaries/* 53 | Plugins/*/Binaries/* 54 | 55 | # Builds 56 | Build/* 57 | 58 | # Whitelist PakBlacklist-.txt files 59 | !Build/*/ 60 | Build/*/** 61 | !Build/*/PakBlacklist*.txt 62 | 63 | # Don't ignore icon files in Build 64 | !Build/**/*.ico 65 | 66 | # Built data for maps 67 | *_BuiltData.uasset 68 | 69 | # Configuration files generated by the Editor 70 | Saved/* 71 | 72 | # Compiled source files for the engine to use 73 | Intermediate/* 74 | Plugins/*/Intermediate/* 75 | 76 | # Cache files for the editor to use 77 | DerivedDataCache/* 78 | -------------------------------------------------------------------------------- /Resources/Icon128.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeorgeR/ShadersPlus/2399f437d996d7294a1bc481193a27f44308cadb/Resources/Icon128.ai -------------------------------------------------------------------------------- /Resources/Icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeorgeR/ShadersPlus/2399f437d996d7294a1bc481193a27f44308cadb/Resources/Icon128.png -------------------------------------------------------------------------------- /Shaders/Private/CombineCS.usf: -------------------------------------------------------------------------------- 1 | #ifndef INPUT_COMPONENTS 2 | #define INPUT_COMPONENTS 4 3 | #endif 4 | 5 | #if INPUT_COMPONENTS == 1 6 | #define INPUT_TYPE float 7 | #elif INPUT_COMPONENTS == 2 8 | #define INPUT_TYPE float2 9 | #elif INPUT_COMPONENTS == 3 10 | #define INPUT_TYPE float3 11 | #elif INPUT_COMPONENTS == 4 12 | #define INPUT_TYPE float4 13 | #endif 14 | 15 | Texture2D InputX; 16 | Texture2D InputY; 17 | Texture2D InputZ; 18 | Texture2D InputW; 19 | 20 | RWTexture2D Output; 21 | 22 | [numthreads(32, 32, 1)] 23 | void MainCS(uint3 GlobalThreadIndex : SV_DispatchThreadID) 24 | { 25 | const int3 InputIndex = int3(GlobalThreadIndex.xy, 0); 26 | const int2 OutputIndex = InputIndex.xy; 27 | 28 | float X = InputX.Load(InputIndex).x; 29 | float Y = InputY.Load(InputIndex).x; 30 | float Z = InputZ.Load(InputIndex).x; 31 | float W = InputW.Load(InputIndex).x; 32 | 33 | Output[OutputIndex] = float4(X, Y, Z, W); 34 | } -------------------------------------------------------------------------------- /Shaders/Private/ConvertCS.usf: -------------------------------------------------------------------------------- 1 | #ifndef INPUT_COMPONENTS 2 | #define INPUT_COMPONENTS 4 3 | #endif 4 | 5 | #ifndef OUTPUT_COMPONENTS 6 | #define OUTPUT_COMPONENTS 1 7 | #endif 8 | 9 | #if INPUT_COMPONENTS == 1 10 | #define INPUT_TYPE float 11 | #elif INPUT_COMPONENTS == 2 12 | #define INPUT_TYPE float2 13 | #elif INPUT_COMPONENTS == 3 14 | #define INPUT_TYPE float3 15 | #elif INPUT_COMPONENTS == 4 16 | #define INPUT_TYPE float4 17 | #endif 18 | 19 | #if OUTPUT_COMPONENTS == 1 20 | #define OUTPUT_TYPE float 21 | #elif OUTPUT_COMPONENTS == 2 22 | #define OUTPUT_TYPE float2 23 | #elif OUTPUT_COMPONENTS == 3 24 | #define OUTPUT_TYPE float3 25 | #elif OUTPUT_COMPONENTS == 4 26 | #define OUTPUT_TYPE float4 27 | #endif 28 | 29 | Texture2D Input; 30 | RWTexture2D Output; 31 | 32 | [numthreads(32, 32, 1)] 33 | void MainCS(uint3 GlobalThreadIndex : SV_DispatchThreadID) 34 | { 35 | const int3 InputIndex = int3(GlobalThreadIndex.xy, 0); 36 | const int2 OutputIndex = InputIndex.xy; 37 | 38 | #if INPUT_COMPONENTS == 1 39 | #if OUTPUT_COMPONENTS == 1 40 | Output[OutputIndex] = Input.Load(InputIndex); 41 | #elif OUTPUT_COMPONENTS != 1 42 | float InputValue = Input.Load(InputIndex); 43 | #if OUTPUT_COMPONENTS == 2 44 | Output[OutputIndex] = float2(InputValue, InputValue); 45 | #elif OUTPUT_COMPONENTS == 3 46 | Output[OutputIndex] = float3(InputValue, InputValue, InputValue); 47 | #elif OUTPUT_COMPONENTS == 4 48 | Output[OutputIndex] = float4(InputValue, InputValue, InputValue, 1.0f); 49 | #endif 50 | #endif 51 | #elif INPUT_COMPONENTS == 2 52 | #if OUTPUT_COMPONENTS == 2 53 | Output[OutputIndex] = Input.Load(InputIndex); 54 | #elif OUTPUT_COMPONENTS != 2 55 | float2 InputValue = Input.Load(InputIndex); 56 | #if OUTPUT_COMPONENTS == 1 57 | Output[OutputIndex] = InputValue.x; 58 | #elif OUTPUT_COMPONENTS == 3 59 | Output[OutputIndex] = float3(InputValue, 0.0f); 60 | #elif OUTPUT_COMPONENTS == 4 61 | Output[OutputIndex] = float4(InputValue, 0.0f, 1.0f); 62 | #endif 63 | #endif 64 | #elif INPUT_COMPONENTS == 3 65 | #if OUTPUT_COMPONENTS == 3 66 | Output[OutputIndex] = Input.Load(InputIndex); 67 | #elif OUTPUT_COMPONENTS != 3 68 | float3 InputValue = Input.Load(InputIndex); 69 | #if OUTPUT_COMPONENTS == 1 70 | Output[OutputIndex] = InputValue.x; 71 | #elif OUTPUT_COMPONENTS == 2 72 | Output[OutputIndex] = InputValue.xy; 73 | #elif OUTPUT_COMPONENTS == 4 74 | Output[OutputIndex] = float4(InputValue, 1.0f); 75 | #endif 76 | #endif 77 | #elif INPUT_COMPONENTS == 4 78 | #if OUTPUT_COMPONENTS == 4 79 | Output[OutputIndex] = Input.Load(InputIndex); 80 | #elif OUTPUT_COMPONENTS != 4 81 | float4 InputValue = Input.Load(InputIndex); 82 | #if OUTPUT_COMPONENTS == 1 83 | Output[OutputIndex] = InputValue.x; 84 | #elif OUTPUT_COMPONENTS == 2 85 | Output[OutputIndex] = InputValue.xy; 86 | #elif OUTPUT_COMPONENTS == 3 87 | Output[OutputIndex] = InputValue.x; 88 | #endif 89 | #endif 90 | #endif 91 | } -------------------------------------------------------------------------------- /Shaders/Private/QuadUVVS.usf: -------------------------------------------------------------------------------- 1 | #include "/Engine/Public/Platform.ush" 2 | #include "/Engine/Private/Common.ush" 3 | 4 | void MainVS( 5 | float4 Position : ATTRIBUTE0, 6 | float2 UV : ATTRIBUTE1, 7 | out float2 OutUV : TEXCOORD0, 8 | out float4 OutPosition : SV_POSITION) 9 | { 10 | OutPosition = Position; 11 | OutUV = UV; 12 | } -------------------------------------------------------------------------------- /ShadersPlus.uplugin: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "Version": 1, 4 | "VersionName": "1.0", 5 | "FriendlyName": "ShadersPlus", 6 | "Description": "Extensions, utilities and base classes for shaders.", 7 | "Category": "Rendering", 8 | "CreatedBy": "George Rolfe", 9 | "CreatedByURL": "", 10 | "DocsURL": "https://github.com/georger/shadersplus", 11 | "MarketplaceURL": "", 12 | "SupportURL": "", 13 | "CanContainContent": true, 14 | "IsBetaVersion": false, 15 | "Installed": false, 16 | "Modules": [ 17 | { 18 | "Name": "ShadersPlus", 19 | "Type": "Developer", 20 | "LoadingPhase": "PostConfigInit" 21 | } 22 | ] 23 | } -------------------------------------------------------------------------------- /Source/ShadersPlus/Private/Combine.cpp: -------------------------------------------------------------------------------- 1 | #include "Combine.h" -------------------------------------------------------------------------------- /Source/ShadersPlus/Private/Convert.cpp: -------------------------------------------------------------------------------- 1 | #include "Convert.h" 2 | -------------------------------------------------------------------------------- /Source/ShadersPlus/Private/Definitions/CombineCS.cpp: -------------------------------------------------------------------------------- 1 | #include "CombineCS.h" 2 | 3 | FCombineCS::FCombineCS(const ShaderMetaType::CompiledShaderInitializerType& Initializer) 4 | : FGlobalShader(Initializer) 5 | { 6 | BIND(InputX); 7 | BIND(InputY); 8 | BIND(InputZ); 9 | BIND(InputW); 10 | BIND(Output); 11 | } 12 | 13 | IMPLEMENT_SET_PARAMETER_SRV(FCombineCS, InputX, Compute) 14 | IMPLEMENT_SET_PARAMETER_SRV(FCombineCS, InputY, Compute) 15 | IMPLEMENT_SET_PARAMETER_SRV(FCombineCS, InputZ, Compute) 16 | IMPLEMENT_SET_PARAMETER_SRV(FCombineCS, InputW, Compute) 17 | IMPLEMENT_SET_PARAMETER_UAV(FCombineCS, Output, Compute) 18 | 19 | void FCombineCS::Unbind(FRHICommandList& RHICmdList) 20 | { 21 | const auto ComputeShaderRHI = GetComputeShader(); 22 | 23 | UNBIND_SRV(InputX, Compute); 24 | UNBIND_SRV(InputY, Compute); 25 | UNBIND_SRV(InputZ, Compute); 26 | UNBIND_SRV(InputW, Compute); 27 | UNBIND_UAV(Output, Compute); 28 | } 29 | 30 | bool FCombineCS::Serialize(FArchive& Ar) 31 | { 32 | const auto bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar); 33 | 34 | Ar << InputX << InputY << InputZ << InputW << Output; 35 | 36 | return bShaderHasOutdatedParameters; 37 | } 38 | 39 | IMPLEMENT_SHADER_TYPE(, FCombineCS, TEXT("/Plugin/ShadersPlus/Private/CombineCS.usf"), TEXT("MainCS"), SF_Compute); 40 | 41 | #ifndef IMPLEMENT_PERMUTATION 42 | #define IMPLEMENT_PERMUTATION(InputComponents) typedef TCombineCS TCombineCS##InputComponents##; \ 43 | IMPLEMENT_SHADER_TYPE(template<> SHADERSPLUS_API, TCombineCS##InputComponents##, TEXT("/Plugin/ShadersPlus/Private/CombineCS.usf"), TEXT("MainCS"), SF_Compute); 44 | 45 | IMPLEMENT_PERMUTATION(1) 46 | IMPLEMENT_PERMUTATION(2) 47 | IMPLEMENT_PERMUTATION(3) 48 | IMPLEMENT_PERMUTATION(4) 49 | 50 | #undef IMPLEMENT_PERMUTATION 51 | #endif -------------------------------------------------------------------------------- /Source/ShadersPlus/Private/Definitions/ConvertCS.cpp: -------------------------------------------------------------------------------- 1 | #include "ConvertCS.h" 2 | 3 | FConvertCS::FConvertCS(const ShaderMetaType::CompiledShaderInitializerType& Initializer) 4 | : FGlobalShader(Initializer) 5 | { 6 | BIND(Input); 7 | BIND(Output); 8 | } 9 | 10 | IMPLEMENT_SET_PARAMETER_SRV(FConvertCS, Input, Compute) 11 | IMPLEMENT_SET_PARAMETER_UAV(FConvertCS, Output, Compute) 12 | 13 | void FConvertCS::Unbind(FRHICommandList& RHICmdList) 14 | { 15 | const auto ComputeShaderRHI = GetComputeShader(); 16 | 17 | UNBIND_SRV(Input, Compute); 18 | UNBIND_UAV(Output, Compute); 19 | } 20 | 21 | bool FConvertCS::Serialize(FArchive& Ar) 22 | { 23 | const auto bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar); 24 | 25 | Ar << Input << Output; 26 | 27 | return bShaderHasOutdatedParameters; 28 | } 29 | 30 | IMPLEMENT_SHADER_TYPE(, FConvertCS, TEXT("/Plugin/ShadersPlus/Private/ConvertCS.usf"), TEXT("MainCS"), SF_Compute); 31 | 32 | #ifndef IMPLEMENT_PERMUTATION 33 | #define IMPLEMENT_PERMUTATION(InputComponents, OutputComponents) typedef TConvertCS TConvertCS##InputComponents##OutputComponents##; \ 34 | IMPLEMENT_SHADER_TYPE(template<> SHADERSPLUS_API, TConvertCS##InputComponents##OutputComponents##, TEXT("/Plugin/ShadersPlus/Private/ConvertCS.usf"), TEXT("MainCS"), SF_Compute); 35 | 36 | IMPLEMENT_PERMUTATION(1, 1) 37 | IMPLEMENT_PERMUTATION(1, 2) 38 | IMPLEMENT_PERMUTATION(1, 3) 39 | IMPLEMENT_PERMUTATION(1, 4) 40 | 41 | IMPLEMENT_PERMUTATION(2, 1) 42 | IMPLEMENT_PERMUTATION(2, 2) 43 | IMPLEMENT_PERMUTATION(2, 3) 44 | IMPLEMENT_PERMUTATION(2, 4) 45 | 46 | IMPLEMENT_PERMUTATION(3, 1) 47 | IMPLEMENT_PERMUTATION(3, 2) 48 | IMPLEMENT_PERMUTATION(3, 3) 49 | IMPLEMENT_PERMUTATION(3, 4) 50 | 51 | IMPLEMENT_PERMUTATION(4, 1) 52 | IMPLEMENT_PERMUTATION(4, 2) 53 | IMPLEMENT_PERMUTATION(4, 3) 54 | IMPLEMENT_PERMUTATION(4, 4) 55 | 56 | #undef IMPLEMENT_PERMUTATION 57 | #endif -------------------------------------------------------------------------------- /Source/ShadersPlus/Private/Definitions/QuadUVVS.cpp: -------------------------------------------------------------------------------- 1 | #include "QuadUVVS.h" 2 | 3 | TGlobalResource GTextureVertexDeclaration; 4 | 5 | FQuadUVVS::FQuadUVVS(const ShaderMetaType::CompiledShaderInitializerType& Initializer) 6 | : FGlobalShader(Initializer) { } 7 | 8 | IMPLEMENT_SHADER_TYPE(, FQuadUVVS, TEXT("/Plugin/ShadersPlus/Private/QuadUVVS.usf"), TEXT("MainVS"), SF_Vertex); -------------------------------------------------------------------------------- /Source/ShadersPlus/Private/ImageWriter.cpp: -------------------------------------------------------------------------------- 1 | #include "ImageWriter.h" 2 | #include "ScopeLock.h" 3 | #include "Async.h" 4 | #include "FileHelper.h" 5 | #include "ModuleManager.h" 6 | #include "IImageWrapperModule.h" 7 | 8 | void FImageWriter::Enqueue(FImageSaveTask&& Task) 9 | { 10 | //FScopeLock WriteLock(&QueueLock); 11 | 12 | //Test.Add(Task); 13 | Tasks.Enqueue(Task); 14 | TryWrite(); 15 | } 16 | 17 | void FImageWriter::TryWrite() 18 | { 19 | FScopeLock WriteLock(&WriteLock); 20 | 21 | if (Tasks.IsEmpty()) 22 | return; 23 | 24 | while (!Tasks.IsEmpty()) 25 | { 26 | FImageSaveTask Task; 27 | Tasks.Dequeue(Task); 28 | if (!Task.IsValid()) 29 | continue; 30 | 31 | AsyncTask(ENamedThreads::GameThread, [Task = MoveTemp(Task)]{ 32 | const void* RawPtr = nullptr; 33 | int32 SizeInBytes = 0; 34 | 35 | if (Task.Data->GetRawData(RawPtr, SizeInBytes)) 36 | { 37 | uint8 BitDepth = Task.Data->GetBitDepth(); 38 | FIntPoint Size = Task.Data->GetSize(); 39 | ERGBFormat PixelLayout = Task.Data->GetPixelLayout(); 40 | 41 | auto ImageWrapper = FImageWriter::GetImageWrapperForFormat(EImageFormat::EXR); 42 | ImageWrapper->SetRaw(RawPtr, SizeInBytes, Size.X, Size.Y, PixelLayout, BitDepth); 43 | FFileHelper::SaveArrayToFile(ImageWrapper->GetCompressed(), *Task.FilePath); 44 | } 45 | }); 46 | } 47 | } 48 | 49 | TSharedPtr FImageWriter::GetImageWrapperForFormat(EImageFormat Format) 50 | { 51 | auto ImageWrapperModule = FModuleManager::GetModulePtr(TEXT("ImageWrapper")); 52 | return ImageWrapperModule->CreateImageWrapper(Format); 53 | } -------------------------------------------------------------------------------- /Source/ShadersPlus/Private/Polyfills/ImageWriteQueue/ImagePixelData.h: -------------------------------------------------------------------------------- 1 | #if (ENGINE_MINOR_VERSION < 21) 2 | 3 | // Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. 4 | 5 | #pragma once 6 | 7 | #include "Misc/CoreDefines.h" 8 | #include "Math/IntPoint.h" 9 | #include "IImageWrapper.h" 10 | #include "Templates/UniquePtr.h" 11 | 12 | class FFloat16Color; 13 | template struct TImagePixelDataTraits; 14 | 15 | 16 | enum class EImagePixelType 17 | { 18 | Color, 19 | Float16, 20 | Float32, 21 | }; 22 | 23 | struct FImagePixelData 24 | { 25 | virtual ~FImagePixelData() {} 26 | 27 | /** 28 | * Retrieve the type of this data 29 | */ 30 | EImagePixelType GetType() const 31 | { 32 | return Type; 33 | } 34 | 35 | /** 36 | * Retrieve the size of this data 37 | */ 38 | FIntPoint GetSize() const 39 | { 40 | return Size; 41 | } 42 | 43 | /** 44 | * Retrieve the pixel layout of this data 45 | */ 46 | ERGBFormat GetPixelLayout() const 47 | { 48 | return PixelLayout; 49 | } 50 | 51 | /** 52 | * Retrieve the number of bits per each channel of color in the data 53 | */ 54 | uint8 GetBitDepth() const 55 | { 56 | return BitDepth; 57 | } 58 | 59 | /** 60 | * Retrieve the number of channels in the data 61 | */ 62 | uint8 GetNumChannels() const 63 | { 64 | return NumChannels; 65 | } 66 | 67 | /** 68 | * Check that this data is the size it should be 69 | */ 70 | bool IsDataWellFormed() const 71 | { 72 | const void* RawPtr = nullptr; 73 | int32 SizeBytes = 0; 74 | 75 | return GetRawData(RawPtr, SizeBytes); 76 | } 77 | 78 | /** 79 | * Get the data and its size only if it is well formed 80 | */ 81 | bool GetRawData(const void*& OutRawData, int32& OutSizeBytes) const 82 | { 83 | const void* RawPtr = nullptr; 84 | int32 SizeBytes = 0; 85 | 86 | RetrieveData(RawPtr, SizeBytes); 87 | 88 | if (RawPtr && SizeBytes == Size.X*Size.Y*BitDepth / 8 * NumChannels) 89 | { 90 | OutRawData = RawPtr; 91 | OutSizeBytes = SizeBytes; 92 | return true; 93 | } 94 | return false; 95 | } 96 | 97 | /** 98 | * Copy this whole image buffer. This can be very costly for large images. 99 | */ 100 | TUniquePtr CopyImageData() const 101 | { 102 | return Copy(); 103 | } 104 | 105 | /** 106 | * Move this whole image buffer to a new allocation. 107 | */ 108 | TUniquePtr MoveImageDataToNew() 109 | { 110 | return Move(); 111 | } 112 | 113 | protected: 114 | 115 | FImagePixelData(const FIntPoint& InSize, EImagePixelType InPixelType, ERGBFormat InPixelLayout, uint8 InBitDepth, uint8 InNumChannels) 116 | : Size(InSize) 117 | , Type(InPixelType) 118 | , PixelLayout(InPixelLayout) 119 | , BitDepth(InBitDepth) 120 | , NumChannels(InNumChannels) 121 | {} 122 | 123 | private: 124 | 125 | /** 126 | * Retrieve the raw pixel data 127 | */ 128 | virtual void RetrieveData(const void*& OutDataPtr, int32& OutSizeBytes) const = 0; 129 | virtual TUniquePtr Copy() const = 0; 130 | virtual TUniquePtr Move() = 0; 131 | 132 | /** The size of the pixel data */ 133 | FIntPoint Size; 134 | 135 | /** The type of the derived data */ 136 | EImagePixelType Type; 137 | 138 | /** The pixel layout of this data */ 139 | ERGBFormat PixelLayout; 140 | 141 | /** The number of bits per each channel of color in the data */ 142 | uint8 BitDepth; 143 | 144 | /** Number of channels in the data */ 145 | uint8 NumChannels; 146 | }; 147 | 148 | /** 149 | * Templated pixel data - currently supports FColor, FFloat16Color and FLinearColor 150 | */ 151 | template 152 | struct TImagePixelData : FImagePixelData 153 | { 154 | TArray Pixels; 155 | 156 | TImagePixelData(const FIntPoint& InSize) 157 | : FImagePixelData(InSize, TImagePixelDataTraits::PixelType, TImagePixelDataTraits::PixelLayout, TImagePixelDataTraits::BitDepth, TImagePixelDataTraits::NumChannels) 158 | {} 159 | 160 | TImagePixelData(const FIntPoint& InSize, TArray&& InPixels) 161 | : FImagePixelData(InSize, TImagePixelDataTraits::PixelType, TImagePixelDataTraits::PixelLayout, TImagePixelDataTraits::BitDepth, TImagePixelDataTraits::NumChannels) 162 | , Pixels(MoveTemp(InPixels)) 163 | {} 164 | 165 | virtual TUniquePtr Move() override 166 | { 167 | return MakeUnique>(MoveTemp(*this)); 168 | } 169 | 170 | virtual TUniquePtr Copy() const override 171 | { 172 | return MakeUnique>(*this); 173 | } 174 | 175 | virtual void RetrieveData(const void*& OutDataPtr, int32& OutSizeBytes) const override 176 | { 177 | OutDataPtr = static_cast(&Pixels[0]); 178 | OutSizeBytes = Pixels.Num() * sizeof(PixelType); 179 | } 180 | }; 181 | 182 | template<> struct TImagePixelDataTraits 183 | { 184 | static const ERGBFormat PixelLayout = ERGBFormat::BGRA; 185 | static const EImagePixelType PixelType = EImagePixelType::Color; 186 | 187 | enum { BitDepth = 8, NumChannels = 4 }; 188 | }; 189 | 190 | template<> struct TImagePixelDataTraits 191 | { 192 | static const ERGBFormat PixelLayout = ERGBFormat::RGBA; 193 | static const EImagePixelType PixelType = EImagePixelType::Float16; 194 | 195 | enum { BitDepth = 16, NumChannels = 4 }; 196 | }; 197 | 198 | template<> struct TImagePixelDataTraits 199 | { 200 | static const ERGBFormat PixelLayout = ERGBFormat::RGBA; 201 | static const EImagePixelType PixelType = EImagePixelType::Float32; 202 | 203 | enum { BitDepth = 32, NumChannels = 4 }; 204 | }; 205 | 206 | #endif -------------------------------------------------------------------------------- /Source/ShadersPlus/Private/ShaderInstance.cpp: -------------------------------------------------------------------------------- 1 | #include "ShaderInstance.h" 2 | 3 | FShaderInstance::FShaderInstance(const ERHIFeatureLevel::Type FeatureLevel) 4 | { 5 | this->FeatureLevel = FeatureLevel; 6 | 7 | bIsExecuting = false; 8 | bIsUnloading = false; 9 | } 10 | 11 | FShaderInstance::~FShaderInstance() 12 | { 13 | bIsUnloading = true; 14 | } 15 | 16 | bool FShaderInstance::CanExecute() 17 | { 18 | check(IsInGameThread()); 19 | 20 | return !bIsUnloading && !bIsExecuting; 21 | } 22 | 23 | FComputeShaderInstance::FComputeShaderInstance(const ERHIFeatureLevel::Type FeatureLevel) 24 | : FShaderInstance(FeatureLevel) 25 | { 26 | bHasBeenRun = false; 27 | } 28 | 29 | void FComputeShaderInstance::DispatchOnce() 30 | { 31 | if (!CanExecute() || bHasBeenRun) 32 | return; 33 | 34 | bIsExecuting = true; 35 | OnDispatchOnce(); 36 | bIsExecuting = false; 37 | 38 | bHasBeenRun = true; 39 | } -------------------------------------------------------------------------------- /Source/ShadersPlus/Private/ShadersPlusModule.cpp: -------------------------------------------------------------------------------- 1 | #include "ShadersPlusModule.h" 2 | 3 | #include "Interfaces/IPluginManager.h" 4 | #include "Logging/LogMacros.h" 5 | #include "Misc/Paths.h" 6 | #include "ShaderCore.h" 7 | 8 | #define LOCTEXT_NAMESPACE "FShadersPlusModule" 9 | 10 | void FShadersPlusModule::StartupModule() 11 | { 12 | #if (ENGINE_MINOR_VERSION >= 21) 13 | auto ShaderDirectory = FPaths::Combine(IPluginManager::Get().FindPlugin(TEXT("ShadersPlus"))->GetBaseDir(), TEXT("Shaders")); 14 | AddShaderSourceDirectoryMapping(TEXT("/Plugin/ShadersPlus"), ShaderDirectory); 15 | #endif 16 | } 17 | 18 | void FShadersPlusModule::ShutdownModule() 19 | { 20 | } 21 | 22 | #undef LOCTEXT_NAMESPACE 23 | 24 | IMPLEMENT_MODULE(FShadersPlusModule, ShadersPlus) -------------------------------------------------------------------------------- /Source/ShadersPlus/Private/ShadersPlusModule.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "IShadersPlusModule.h" 4 | 5 | #include "CoreMinimal.h" 6 | #include "ModuleManager.h" 7 | 8 | class FImageWriteQueue; 9 | 10 | class FShadersPlusModule 11 | : public IShadersPlusModule 12 | { 13 | public: 14 | virtual void StartupModule() override; 15 | virtual void ShutdownModule() override; 16 | }; -------------------------------------------------------------------------------- /Source/ShadersPlus/Private/ShadersPlusUtilities.cpp: -------------------------------------------------------------------------------- 1 | #include "ShadersPlusUtilities.h" 2 | 3 | #include "Engine/Texture.h" 4 | #include "Engine/Texture2D.h" 5 | #include "Engine/TextureRenderTarget2D.h" 6 | 7 | #include 8 | #include "FileManager.h" 9 | #include "FileHelper.h" 10 | 11 | #include "IImageWrapperModule.h" 12 | #include "ModuleManager.h" 13 | #include "ImageWriteQueue/Public/ImagePixelData.h" 14 | #include "ConvertCS.h" 15 | #include "Async.h" 16 | #include "TextureResource.h" 17 | #include "QuadUVVS.h" 18 | 19 | #define NUM_THREADS_PER_GROUP_DIMENSION 32 20 | 21 | TUniquePtr FShadersPlusUtilities::ImageWriter = MakeUnique(); 22 | 23 | FVertexBufferRHIRef FShadersPlusUtilities::CreateQuadVertexBuffer() 24 | { 25 | FRHIResourceCreateInfo CreateInfo; 26 | FVertexBufferRHIRef VertexBufferRHI = RHICreateVertexBuffer(sizeof(FTextureVertex) * 4, BUF_Volatile, CreateInfo); 27 | void* VoidPtr = RHILockVertexBuffer(VertexBufferRHI, 0, sizeof(FTextureVertex) * 4, RLM_WriteOnly); 28 | 29 | FTextureVertex* Vertices = (FTextureVertex*)VoidPtr; 30 | Vertices[0].Position = FVector4(-1.0f, 1.0f, 0, 1.0f); 31 | Vertices[1].Position = FVector4(1.0f, 1.0f, 0, 1.0f); 32 | Vertices[2].Position = FVector4(-1.0f, -1.0f, 0, 1.0f); 33 | Vertices[3].Position = FVector4(1.0f, -1.0f, 0, 1.0f); 34 | Vertices[0].UV = FVector2D(0, 0); 35 | Vertices[1].UV = FVector2D(1, 0); 36 | Vertices[2].UV = FVector2D(0, 1); 37 | Vertices[3].UV = FVector2D(1, 1); 38 | RHIUnlockVertexBuffer(VertexBufferRHI); 39 | 40 | return VertexBufferRHI; 41 | } 42 | 43 | // TODO: Return false if Texture has no resource 44 | bool FShadersPlusUtilities::CreateSRV(UTexture2D* Texture, FShaderResourceViewRHIRef& OutSRV) 45 | { 46 | check(IsInGameThread()); 47 | check(Texture); 48 | 49 | ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER( 50 | CreateSRV, 51 | UTexture2D*, Texture, Texture, 52 | FShaderResourceViewRHIRef&, OutSRV, OutSRV, 53 | { 54 | auto RHIRef = StaticCast(Texture->Resource)->GetTexture2DRHI(); 55 | OutSRV = RHICreateShaderResourceView(RHIRef, 0); 56 | }); 57 | 58 | FlushRenderingCommands(); 59 | 60 | return true; 61 | } 62 | 63 | bool FShadersPlusUtilities::CreateUAV(UTexture2D* Texture, FUnorderedAccessViewRHIRef& OutUAV) 64 | { 65 | check(IsInGameThread()); 66 | check(Texture); 67 | 68 | ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER( 69 | CreateUAV, 70 | UTexture2D*, Texture, Texture, 71 | FUnorderedAccessViewRHIRef&, OutUAV, OutUAV, 72 | { 73 | auto RHIRef = StaticCast(Texture->Resource)->GetTexture2DRHI(); 74 | OutUAV = RHICreateUnorderedAccessView(RHIRef); 75 | }); 76 | 77 | FlushRenderingCommands(); 78 | 79 | return true; 80 | } 81 | 82 | bool FShadersPlusUtilities::CreateUAV(UTextureRenderTarget2D* Texture, FUnorderedAccessViewRHIRef& OutUAV) 83 | { 84 | check(IsInGameThread()); 85 | check(Texture); 86 | 87 | ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER( 88 | CreateUAV, 89 | FTextureRenderTargetResource*, Resource, Texture->GameThread_GetRenderTargetResource(), 90 | FUnorderedAccessViewRHIRef&, OutUAV, OutUAV, 91 | { 92 | auto RHIRef = Resource->GetRenderTargetTexture(); 93 | OutUAV = RHICreateUnorderedAccessView(RHIRef); 94 | }); 95 | 96 | FlushRenderingCommands(); 97 | 98 | return true; 99 | } 100 | 101 | void FShadersPlusUtilities::SaveScreenshot(UTexture2D* Texture, const FString& FilePath) 102 | { 103 | check(IsInGameThread()); 104 | check(Texture); 105 | 106 | auto TextureResource = (FTexture2DResource*)(Texture->Resource); 107 | auto TextureReference = TextureResource->GetTexture2DRHI(); 108 | 109 | SaveScreenshot(TextureReference, FilePath); 110 | } 111 | 112 | void FShadersPlusUtilities::SaveScreenshot(UTextureRenderTarget2D* Texture, const FString& FilePath) 113 | { 114 | check(IsInGameThread()); 115 | check(Texture); 116 | 117 | auto TextureResource = Texture->GameThread_GetRenderTargetResource(); 118 | auto TextureReference = TextureResource->GetRenderTargetTexture(); 119 | 120 | SaveScreenshot(TextureReference, FilePath); 121 | } 122 | 123 | // This doesn'tw ork, dont use it 124 | void FShadersPlusUtilities::SaveScreenshot(FShaderResourceViewRHIRef SRV, const FString& FilePath) 125 | { 126 | check(IsInGameThread()); 127 | check(SRV); 128 | 129 | auto Texture = (FRHITexture2D*)(SRV.GetReference()); 130 | 131 | SaveScreenshot(Texture, FilePath); 132 | } 133 | 134 | void FShadersPlusUtilities::SaveScreenshot(FTexture2DRHIRef Texture, const FString& FilePath) 135 | { 136 | check(IsInGameThread()); 137 | check(Texture); 138 | 139 | ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER( 140 | SaveScreenshot, 141 | FTexture2DRHIRef, Texture, Texture, 142 | const FString&, FilePath, FilePath, 143 | { 144 | FShadersPlusUtilities::SaveScreenshot_RenderThread(RHICmdList, Texture, FilePath); 145 | } 146 | ); 147 | 148 | FlushRenderingCommands(); 149 | } 150 | 151 | void FShadersPlusUtilities::SaveScreenshot_RenderThread(FRHICommandListImmediate& RHICmdList, FTexture2DRHIRef Texture, const FString& FilePath) 152 | { 153 | check(IsInRenderingThread()); 154 | 155 | auto SourceRect = FIntRect(0, 0, Texture->GetSizeX(), Texture->GetSizeY()); 156 | 157 | FReadSurfaceDataFlags ReadDataFlags(RCM_MinMax); 158 | ReadDataFlags.SetLinearToGamma(false); 159 | ReadDataFlags.SetOutputStencil(false); 160 | ReadDataFlags.SetMip(0); 161 | 162 | TUniquePtr PixelData; 163 | 164 | auto Format = Texture->GetFormat(); 165 | switch (Format) 166 | { 167 | case PF_G32R32F: 168 | { 169 | FRHIResourceCreateInfo CreateInfo; 170 | auto ConvertedOutput = RHICreateTexture2D(SourceRect.Width(), SourceRect.Height(), PF_A32B32G32R32F, 1, 1, TexCreate_UAV, CreateInfo); 171 | auto ConvertedOutput_UAV = RHICreateUnorderedAccessView(ConvertedOutput); 172 | 173 | auto Input_SRV = RHICreateShaderResourceView(Texture, 0); 174 | 175 | TShaderMapRef> ComputeShader(GetGlobalShaderMap(GMaxRHIFeatureLevel)); 176 | RHICmdList.SetComputeShader(ComputeShader->GetComputeShader()); 177 | 178 | ComputeShader->SetInput(RHICmdList, Input_SRV); 179 | ComputeShader->SetOutput(RHICmdList, ConvertedOutput_UAV); 180 | 181 | DispatchComputeShader(RHICmdList, *ComputeShader, SourceRect.Width() / NUM_THREADS_PER_GROUP_DIMENSION, SourceRect.Height() / NUM_THREADS_PER_GROUP_DIMENSION, 1); 182 | ComputeShader->Unbind(RHICmdList); 183 | 184 | Texture = ConvertedOutput; 185 | 186 | break; 187 | } 188 | } 189 | 190 | Format = Texture->GetFormat(); 191 | switch (Format) 192 | { 193 | case PF_FloatRGBA: 194 | { 195 | TUniquePtr> BitmapData = MakeUnique>(SourceRect.Size()); 196 | RHICmdList.ReadSurfaceFloatData(Texture, SourceRect, BitmapData->Pixels, ECubeFace::CubeFace_PosX, 0, 0); 197 | 198 | PixelData = MoveTemp(BitmapData); 199 | 200 | break; 201 | } 202 | 203 | case PF_A32B32G32R32F: 204 | { 205 | TUniquePtr> BitmapData = MakeUnique>(SourceRect.Size()); 206 | RHICmdList.ReadSurfaceData(Texture, SourceRect, BitmapData->Pixels, ReadDataFlags); 207 | 208 | PixelData = MoveTemp(BitmapData); 209 | 210 | break; 211 | } 212 | 213 | case PF_R8G8B8A8: 214 | case PF_B8G8R8A8: 215 | { 216 | TUniquePtr> BitmapData = MakeUnique>(SourceRect.Size()); 217 | RHICmdList.ReadSurfaceData(Texture, SourceRect, BitmapData->Pixels, ReadDataFlags); 218 | 219 | PixelData = MoveTemp(BitmapData); 220 | 221 | break; 222 | } 223 | } 224 | 225 | if (PixelData.IsValid() && PixelData->IsDataWellFormed()) 226 | { 227 | FImageSaveTask Task; 228 | Task.Data = MoveTemp(PixelData); 229 | Task.FilePath = FilePath; 230 | 231 | ImageWriter->Enqueue(MoveTemp(Task)); 232 | 233 | //AsyncTask(ENamedThreads::GameThread, [Task]{ 234 | // auto T = Task; 235 | // ImageWriter->Enqueue(MoveTemp(T)); 236 | //}); 237 | //OnImageSaveRequest.Broadcast(MoveTemp(Task)); 238 | } 239 | } -------------------------------------------------------------------------------- /Source/ShadersPlus/Public/Combine.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ShaderInstance.h" 4 | #include "RenderingThread.h" 5 | 6 | struct FCombineParameters 7 | { 8 | public: 9 | FIntPoint Size; 10 | 11 | /* Inputs */ 12 | FShaderResourceViewRHIRef InputX_SRV; 13 | FShaderResourceViewRHIRef InputY_SRV; 14 | FShaderResourceViewRHIRef InputZ_SRV; 15 | FShaderResourceViewRHIRef InputW_SRV; 16 | 17 | /* Outputs */ 18 | FUnorderedAccessViewRHIRef Output_UAV; 19 | }; 20 | 21 | template 22 | class TCombineInstance 23 | : public TComputeShaderInstance 24 | { 25 | public: 26 | TCombineInstance(const int32 SizeX, const int32 SizeY, const ERHIFeatureLevel::Type FeatureLevel); 27 | virtual ~TCombineInstance() { } 28 | 29 | void OnDispatch(FCombineParameters& Parameters) override; 30 | 31 | FTexture2DRHIRef GetOutput() const { return Output; } 32 | FUnorderedAccessViewRHIRef GetOutput_UAV() const { return Output_UAV; } 33 | FShaderResourceViewRHIRef GetOutput_SRV() const { return Output_SRV; } 34 | 35 | private: 36 | FTexture2DRHIRef Output; 37 | FUnorderedAccessViewRHIRef Output_UAV; 38 | FShaderResourceViewRHIRef Output_SRV; 39 | }; 40 | 41 | template 42 | TCombineInstance::TCombineInstance(const int32 SizeX, const int32 SizeY, const ERHIFeatureLevel::Type FeatureLevel) 43 | : TComputeShaderInstance(FeatureLevel) 44 | { 45 | FRHIResourceCreateInfo CreateInfo; 46 | Output = RHICreateTexture2D(SizeX, SizeY, OutputFormat, 1, 1, TexCreate_ShaderResource | TexCreate_UAV, CreateInfo); 47 | Output_UAV = RHICreateUnorderedAccessView(Output); 48 | Output_SRV = RHICreateShaderResourceView(Output, 0); 49 | } 50 | 51 | template 52 | void TCombineInstance::OnDispatch(FCombineParameters& Parameters) 53 | { 54 | check(Parameters.InputX_SRV.IsValid()); 55 | 56 | Parameters.Size = Output->GetSizeXY(); 57 | Parameters.Output_UAV = Output_UAV; 58 | 59 | typedef TCombineCS FCombineCS; 60 | 61 | ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER( 62 | Convert, 63 | FCombineParameters, Parameters, Parameters, 64 | { 65 | SCOPED_DRAW_EVENT(RHICmdList, Convert); 66 | 67 | TShaderMapRef ComputeShader(GetGlobalShaderMap(GMaxRHIFeatureLevel)); 68 | RHICmdList.SetComputeShader(ComputeShader->GetComputeShader()); 69 | 70 | ComputeShader->SetInputX(RHICmdList, Parameters.InputX_SRV); 71 | ComputeShader->SetInputX(RHICmdList, Parameters.InputY_SRV); 72 | ComputeShader->SetInputX(RHICmdList, Parameters.InputZ_SRV); 73 | ComputeShader->SetInputX(RHICmdList, Parameters.InputW_SRV); 74 | ComputeShader->SetOutput(RHICmdList, Parameters.Output_UAV); 75 | 76 | DispatchComputeShader(RHICmdList, *ComputeShader, Parameters.Size / NUM_THREADS_PER_GROUP_DIMENSION, Parameters.Size / NUM_THREADS_PER_GROUP_DIMENSION, 1); 77 | ComputeShader->Unbind(RHICmdList); 78 | } 79 | ) 80 | } -------------------------------------------------------------------------------- /Source/ShadersPlus/Public/Convert.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ShaderInstance.h" 4 | #include "RenderingThread.h" 5 | 6 | struct FConvertParameters 7 | { 8 | public: 9 | FIntPoint Size; 10 | 11 | /* Inputs */ 12 | FShaderResourceViewRHIRef Input_SRV; 13 | 14 | /* Outputs */ 15 | FUnorderedAccessViewRHIRef Output_UAV; 16 | }; 17 | 18 | template 19 | class TConvertInstance 20 | : public TComputeShaderInstance 21 | { 22 | public: 23 | TConvertInstance(const int32 SizeX, const int32 SizeY, const ERHIFeatureLevel::Type FeatureLevel); 24 | virtual ~TConvertInstance() { } 25 | 26 | void OnDispatch(FConvertParameters& Parameters) override; 27 | 28 | FTexture2DRHIRef GetOutput() const { return Output; } 29 | FUnorderedAccessViewRHIRef GetOutput_UAV() const { return Output_UAV; } 30 | FShaderResourceViewRHIRef GetOutput_SRV() const { return Output_SRV; } 31 | 32 | private: 33 | FTexture2DRHIRef Output; 34 | FUnorderedAccessViewRHIRef Output_UAV; 35 | FShaderResourceViewRHIRef Output_SRV; 36 | 37 | constexpr int32 GetComponentCount(EPixelFormat Format); 38 | }; 39 | 40 | template 41 | TConvertInstance::TConvertInstance(const int32 SizeX, const int32 SizeY, const ERHIFeatureLevel::Type FeatureLevel) 42 | : TComputeShaderInstance(FeatureLevel) 43 | { 44 | FRHIResourceCreateInfo CreateInfo; 45 | Output = RHICreateTexture2D(SizeX, SizeY, OutputFormat, 1, 1, TexCreate_ShaderResource | TexCreate_UAV, CreateInfo); 46 | Output_UAV = RHICreateUnorderedAccessView(Output); 47 | Output_SRV = RHICreateShaderResourceView(Output, 0); 48 | } 49 | 50 | template 51 | void TConvertInstance::OnDispatch(FConvertParameters& Parameters) 52 | { 53 | check(Parameters.Input_SRV.IsValid()); 54 | 55 | Parameters.Size = Output->GetSizeXY(); 56 | Parameters.Output_UAV = Output_UAV; 57 | 58 | typedef TConvertCS FConvertCS; 59 | 60 | ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER( 61 | Convert, 62 | FConvertParameters, Parameters, Parameters, 63 | { 64 | SCOPED_DRAW_EVENT(RHICmdList, Convert); 65 | 66 | TShaderMapRef ComputeShader(GetGlobalShaderMap(GMaxRHIFeatureLevel)); 67 | RHICmdList.SetComputeShader(ComputeShader->GetComputeShader()); 68 | 69 | ComputeShader->SetInput(RHICmdList, Parameters.Input_SRV); 70 | ComputeShader->SetOutput(RHICmdList, Parameters.Output_UAV); 71 | 72 | DispatchComputeShader(RHICmdList, *ComputeShader, Parameters.Size / NUM_THREADS_PER_GROUP_DIMENSION, Parameters.Size / NUM_THREADS_PER_GROUP_DIMENSION, 1); 73 | ComputeShader->Unbind(RHICmdList); 74 | } 75 | ) 76 | } 77 | 78 | template 79 | constexpr int32 TConvertInstance::GetComponentCount(EPixelFormat Format) 80 | { 81 | switch (Format) 82 | { 83 | case PF_Unknown: 84 | case PF_DepthStencil: 85 | case PF_ShadowDepth: 86 | case PF_V8U8: 87 | case PF_X24_G8: 88 | case PF_ETC1: 89 | case PF_ETC2_RGB: 90 | case PF_ASTC_4x4: 91 | case PF_ASTC_6x6: 92 | case PF_ASTC_8x8: 93 | case PF_ASTC_10x10: 94 | case PF_ASTC_12x12: 95 | case PF_BC6H: 96 | case PF_XGXR8: 97 | case PF_PLATFORM_HDR_0: 98 | case PF_PLATFORM_HDR_1: 99 | case PF_PLATFORM_HDR_2: 100 | case PF_MAX: 101 | default: 102 | return -1; 103 | 104 | case PF_G8: 105 | case PF_G16: 106 | case PF_R32_FLOAT: 107 | case PF_D24: 108 | case PF_R16F: 109 | case PF_R16F_FILTER: 110 | case PF_A1: 111 | case PF_A8: 112 | case PF_R32_UINT: 113 | case PF_R32_SINT: 114 | case PF_R16_UINT: 115 | case PF_R16_SINT: 116 | case PF_R8_UINT: 117 | case PF_L8: 118 | return 1; 119 | 120 | case PF_G16R16: 121 | case PF_G16R16F: 122 | case PF_G16R16F_FILTER: 123 | case PF_G32R32F: 124 | case PF_R8G8: 125 | case PF_R16G16_UINT: 126 | return 2; 127 | 128 | case PF_DXT1: 129 | case PF_UYVY: 130 | case PF_B8G8R8A8: 131 | case PF_FloatRGB: 132 | case PF_FloatR11G11B10: 133 | case PF_R5G6B5_UNORM: 134 | case PF_R8G8B8A8_UINT: 135 | case PF_R8G8B8A8_SNORM: 136 | case PF_ATC_RGB: 137 | return 3; 138 | 139 | case PF_DXT3: 140 | case PF_DXT5: 141 | case PF_A32B32G32R32F: 142 | case PF_FloatRGBA: 143 | case PF_A2B10G10R10: 144 | case PF_A16B16G16R16: 145 | case PF_R16G16B16A16_UINT: 146 | case PF_R16G16B16A16_SINT: 147 | case PF_R8G8B8A8: 148 | case PF_A8R8G8B8: 149 | case PF_ATC_RGBA_E: 150 | case PF_ATC_RGBA_I: 151 | case PF_ETC2_RGBA: 152 | case PF_R32G32B32A32_UINT: 153 | case PF_R16G16B16A16_UNORM: 154 | case PF_R16G16B16A16_SNORM: 155 | case PF_BC4: 156 | case PF_BC5: 157 | case PF_BC7: 158 | case PF_PVRTC2: 159 | case PF_PVRTC4: 160 | return 4; 161 | } 162 | } -------------------------------------------------------------------------------- /Source/ShadersPlus/Public/Definitions/CombineCS.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ShadersPlusMacros.h" 4 | #include 5 | 6 | class FCombineCS 7 | : public FGlobalShader 8 | { 9 | DECLARE_EXPORTED_SHADER_TYPE(FCombineCS, Global, SHADERSPLUS_API); 10 | 11 | public: 12 | SHOULD_CACHE_WITH_FEATURE_LEVEL(ERHIFeatureLevel::SM5) 13 | SHOULD_COMPILE_WITH_FEATURE_LEVEL(ERHIFeatureLevel::SM5) 14 | 15 | FCombineCS() = default; 16 | explicit FCombineCS(const ShaderMetaType::CompiledShaderInitializerType& Initializer); 17 | 18 | DECLARE_SET_PARAMETER(FShaderResourceViewRHIRef, InputX); 19 | DECLARE_SET_PARAMETER(FShaderResourceViewRHIRef, InputY); 20 | DECLARE_SET_PARAMETER(FShaderResourceViewRHIRef, InputZ); 21 | DECLARE_SET_PARAMETER(FShaderResourceViewRHIRef, InputW); 22 | DECLARE_SET_PARAMETER(FUnorderedAccessViewRHIRef, Output); 23 | 24 | void Unbind(FRHICommandList& RHICmdList); 25 | 26 | virtual bool Serialize(FArchive& Ar) override; 27 | 28 | private: 29 | FShaderResourceParameter InputX; 30 | FShaderResourceParameter InputY; 31 | FShaderResourceParameter InputZ; 32 | FShaderResourceParameter InputW; 33 | 34 | FShaderResourceParameter Output; 35 | }; 36 | 37 | template 38 | class TCombineCS 39 | : public FCombineCS 40 | { 41 | DECLARE_EXPORTED_SHADER_TYPE(TCombineCS, Global, SHADERSPLUS_API); 42 | 43 | public: 44 | SHOULD_CACHE_WITH_FEATURE_LEVEL(ERHIFeatureLevel::SM5) 45 | SHOULD_COMPILE_WITH_FEATURE_LEVEL(ERHIFeatureLevel::SM5) 46 | static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment); 47 | 48 | TCombineCS() = default; 49 | explicit TCombineCS(const ShaderMetaType::CompiledShaderInitializerType& Initializer) : FCombineCS(Initializer) { } 50 | }; 51 | 52 | template 53 | void TCombineCS::ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment) 54 | { 55 | FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment); 56 | OutEnvironment.SetDefine(TEXT("INPUT_COMPONENTS"), InputComponents); 57 | } -------------------------------------------------------------------------------- /Source/ShadersPlus/Public/Definitions/ConvertCS.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ShadersPlusMacros.h" 4 | #include 5 | 6 | class FConvertCS 7 | : public FGlobalShader 8 | { 9 | DECLARE_EXPORTED_SHADER_TYPE(FConvertCS, Global, SHADERSPLUS_API); 10 | 11 | public: 12 | SHOULD_CACHE_WITH_FEATURE_LEVEL(ERHIFeatureLevel::SM5) 13 | SHOULD_COMPILE_WITH_FEATURE_LEVEL(ERHIFeatureLevel::SM5) 14 | 15 | FConvertCS() = default; 16 | explicit FConvertCS(const ShaderMetaType::CompiledShaderInitializerType& Initializer); 17 | 18 | DECLARE_SET_PARAMETER(FShaderResourceViewRHIRef, Input); 19 | DECLARE_SET_PARAMETER(FUnorderedAccessViewRHIRef, Output); 20 | 21 | void Unbind(FRHICommandList& RHICmdList); 22 | 23 | virtual bool Serialize(FArchive& Ar) override; 24 | 25 | private: 26 | FShaderResourceParameter Input; 27 | FShaderResourceParameter Output; 28 | }; 29 | 30 | template 31 | class TConvertCS 32 | : public FConvertCS 33 | { 34 | DECLARE_EXPORTED_SHADER_TYPE(TConvertCS, Global, SHADERSPLUS_API); 35 | 36 | public: 37 | SHOULD_CACHE_WITH_FEATURE_LEVEL(ERHIFeatureLevel::SM5) 38 | SHOULD_COMPILE_WITH_FEATURE_LEVEL(ERHIFeatureLevel::SM5) 39 | static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment); 40 | 41 | TConvertCS() = default; 42 | explicit TConvertCS(const ShaderMetaType::CompiledShaderInitializerType& Initializer) : FConvertCS(Initializer) { } 43 | }; 44 | 45 | template 46 | void TConvertCS::ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment) 47 | { 48 | FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment); 49 | OutEnvironment.SetDefine(TEXT("INPUT_COMPONENTS"), InputComponents); 50 | OutEnvironment.SetDefine(TEXT("OUTPUT_COMPONENTS"), OutputComponents); 51 | } -------------------------------------------------------------------------------- /Source/ShadersPlus/Public/Definitions/QuadUVVS.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ShadersPlusMacros.h" 4 | #include 5 | 6 | struct FTextureVertex 7 | { 8 | public: 9 | FVector4 Position; 10 | FVector2D UV; 11 | }; 12 | 13 | class FTextureVertexDeclaration 14 | : public FRenderResource 15 | { 16 | public: 17 | FVertexDeclarationRHIRef VertexDeclarationRHI; 18 | 19 | void InitRHI() override 20 | { 21 | FVertexDeclarationElementList Elements; 22 | const auto Stride = sizeof(FTextureVertex); 23 | Elements.Add(FVertexElement(0, STRUCT_OFFSET(FTextureVertex, Position), VET_Float4, 0, Stride)); 24 | Elements.Add(FVertexElement(0, STRUCT_OFFSET(FTextureVertex, UV), VET_Float2, 1, Stride)); 25 | VertexDeclarationRHI = RHICreateVertexDeclaration(Elements); 26 | } 27 | 28 | void ReleaseRHI() override 29 | { 30 | VertexDeclarationRHI.SafeRelease(); 31 | } 32 | }; 33 | 34 | extern SHADERSPLUS_API TGlobalResource GTextureVertexDeclaration; 35 | 36 | class SHADERSPLUS_API FQuadUVVS 37 | : public FGlobalShader 38 | { 39 | DECLARE_SHADER_TYPE(FQuadUVVS, Global); 40 | 41 | public: 42 | SHOULD_CACHE(true) 43 | SHOULD_COMPILE(true) 44 | 45 | FQuadUVVS() = default; 46 | explicit FQuadUVVS(const ShaderMetaType::CompiledShaderInitializerType& Initializer); 47 | }; -------------------------------------------------------------------------------- /Source/ShadersPlus/Public/IShadersPlusModule.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CoreMinimal.h" 4 | #include "ModuleManager.h" 5 | 6 | class IShadersPlusModule 7 | : public IModuleInterface 8 | { 9 | }; -------------------------------------------------------------------------------- /Source/ShadersPlus/Public/ImageWriter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CoreMinimal.h" 4 | 5 | #include "ImagePixelData.h" 6 | #include "CriticalSection.h" 7 | #include "Queue.h" 8 | #include "Array.h" 9 | 10 | struct FImageSaveTask 11 | { 12 | public: 13 | TUniquePtr Data; 14 | FString FilePath; 15 | 16 | FImageSaveTask() = default; 17 | FImageSaveTask(const FImageSaveTask& Other) 18 | { 19 | Data = Other.Data->MoveImageDataToNew(); 20 | FilePath = Other.FilePath; 21 | } 22 | 23 | FImageSaveTask& operator=(const FImageSaveTask& Other) 24 | { 25 | if(Other.Data.IsValid()) 26 | Data = Other.Data->MoveImageDataToNew(); 27 | 28 | FilePath = Other.FilePath; 29 | 30 | return *this; 31 | } 32 | 33 | bool IsValid() const { return Data.IsValid(); } 34 | }; 35 | 36 | class FImageWriter 37 | { 38 | public: 39 | void Enqueue(FImageSaveTask&& Task); 40 | void TryWrite(); 41 | 42 | private: 43 | FCriticalSection WriteLock; 44 | FCriticalSection QueueLock; 45 | 46 | TArray Test; 47 | TQueue Tasks; 48 | 49 | static TSharedPtr GetImageWrapperForFormat(EImageFormat Format); 50 | }; -------------------------------------------------------------------------------- /Source/ShadersPlus/Public/ShaderInstance.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "GlobalShader.h" 4 | #include "UniformBuffer.h" 5 | #include "RHICommandList.h" 6 | #include "ThreadSafeBool.h" 7 | #include "RHIStaticStates.h" 8 | #include "PipelineStateCache.h" 9 | 10 | #include "QuadUVVS.h" 11 | 12 | class UTextureRenderTarget2D; 13 | 14 | class SHADERSPLUS_API FShaderInstance 15 | { 16 | public: 17 | FShaderInstance(const ERHIFeatureLevel::Type FeatureLevel); 18 | virtual ~FShaderInstance(); 19 | 20 | virtual bool CanExecute(); 21 | 22 | FORCEINLINE void SetDebugLabel(const FName Label) { DebugLabel = Label; } 23 | 24 | protected: 25 | TOptional DebugLabel; 26 | 27 | FThreadSafeBool bIsExecuting; 28 | FThreadSafeBool bIsUnloading; 29 | ERHIFeatureLevel::Type FeatureLevel; 30 | }; 31 | 32 | class SHADERSPLUS_API FComputeShaderInstance 33 | : public FShaderInstance 34 | { 35 | public: 36 | FComputeShaderInstance(const ERHIFeatureLevel::Type FeatureLevel); 37 | 38 | virtual ~FComputeShaderInstance() { } 39 | 40 | void Dispatch() 41 | { 42 | if (!CanExecute()) 43 | return; 44 | 45 | bIsExecuting = true; 46 | OnDispatch(); 47 | bIsExecuting = false; 48 | } 49 | 50 | virtual void OnDispatch() { } 51 | 52 | void DispatchOnce(); 53 | virtual void OnDispatchOnce() { } 54 | 55 | protected: 56 | FThreadSafeBool bHasBeenRun; 57 | }; 58 | 59 | template 60 | class TComputeShaderInstance 61 | : public FShaderInstance 62 | { 63 | public: 64 | TComputeShaderInstance(const ERHIFeatureLevel::Type FeatureLevel) 65 | : FShaderInstance(FeatureLevel) { } 66 | 67 | virtual ~TComputeShaderInstance() { } 68 | 69 | void Dispatch(TParameters& Parameters) 70 | { 71 | if (!CanExecute()) 72 | return; 73 | 74 | bIsExecuting = true; 75 | OnDispatch(Parameters); 76 | bIsExecuting = false; 77 | } 78 | 79 | virtual void OnDispatch(TParameters& Parameters) { } 80 | 81 | void DispatchOnce(TParameters& Parameters) 82 | { 83 | if (!CanExecute() || bHasBeenRun) 84 | return; 85 | 86 | bIsExecuting = true; 87 | OnDispatchOnce(Parameters); 88 | bIsExecuting = false; 89 | 90 | bHasBeenRun = true; 91 | } 92 | 93 | virtual void OnDispatchOnce(TParameters& Parameters) { } 94 | 95 | protected: 96 | FThreadSafeBool bHasBeenRun; 97 | }; 98 | 99 | template 100 | class FPixelShaderInstanceBase 101 | : public FShaderInstance 102 | { 103 | public: 104 | FPixelShaderInstanceBase(const ERHIFeatureLevel::Type FeatureLevel) 105 | : FShaderInstance(FeatureLevel) 106 | { 107 | TargetResource = nullptr; 108 | TargetTexture = nullptr; 109 | } 110 | 111 | virtual ~FPixelShaderInstanceBase() { } 112 | 113 | protected: 114 | FThreadSafeBool bHasBeenRun; 115 | 116 | FTexture2DRHIRef TargetResource; 117 | UTextureRenderTarget2D* TargetTexture; 118 | }; 119 | 120 | 121 | struct FDrawToQuadParameters 122 | { 123 | public: 124 | bool bGenerateMips; 125 | 126 | FDrawToQuadParameters() 127 | : bGenerateMips(true) 128 | { 129 | 130 | } 131 | }; 132 | 133 | template 134 | class TDrawToQuadInstance 135 | : public FPixelShaderInstanceBase 136 | { 137 | public: 138 | TDrawToQuadInstance(const ERHIFeatureLevel::Type FeatureLevel) 139 | : FPixelShaderInstanceBase(FeatureLevel) { } 140 | 141 | void DrawToQuad(TParameters& Parameters, UTextureRenderTarget2D* RenderTarget) 142 | { 143 | FDrawToQuadParameters DrawToQuadParameters; 144 | DrawToQuad(Parameters, RenderTarget, DrawToQuadParameters); 145 | } 146 | 147 | void DrawToQuad(TParameters& Parameters, UTextureRenderTarget2D* RenderTarget, FDrawToQuadParameters& DrawToQuadParameters) 148 | { 149 | if (!CanExecute() || RenderTarget == nullptr) 150 | return; 151 | 152 | bIsExecuting = true; 153 | 154 | ENQUEUE_UNIQUE_RENDER_COMMAND_FOURPARAMETER( 155 | DrawToQuad, 156 | TDrawToQuadInstance*, DrawToQuadInstance, this, 157 | FDrawToQuadParameters, DrawToQuadParameters, DrawToQuadParameters, 158 | TParameters, Parameters, Parameters, 159 | FTextureRenderTargetResource*, RenderTarget, RenderTarget->GameThread_GetRenderTargetResource(), 160 | { 161 | FRHICommandListImmediate& RHICmdListImmediate = GRHICommandList.GetImmediateCommandList(); 162 | DrawToQuadInstance->DrawToQuad_RenderThread(RHICmdListImmediate, Parameters, RenderTarget, DrawToQuadParameters); 163 | } 164 | ); 165 | } 166 | 167 | protected: 168 | void DrawToQuad_RenderThread(FRHICommandListImmediate& RHICmdList, TParameters& Parameters, FTextureRenderTargetResource* RenderTarget, FDrawToQuadParameters& DrawToQuadParameters) 169 | { 170 | check(IsInRenderingThread()); 171 | 172 | SCOPED_DRAW_EVENT(RHICmdList, DrawToQuad); 173 | 174 | SetRenderTarget(RHICmdList, RenderTarget->GetRenderTargetTexture(), nullptr); 175 | 176 | TShaderMapRef VertexShader(GetGlobalShaderMap(FeatureLevel)); 177 | TShaderMapRef PixelShader(GetGlobalShaderMap(FeatureLevel)); 178 | 179 | FGraphicsPipelineStateInitializer GraphicsPSOInitializer; 180 | RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInitializer); 181 | GraphicsPSOInitializer.DepthStencilState = TStaticDepthStencilState::GetRHI(); 182 | GraphicsPSOInitializer.BlendState = TStaticBlendState<>::GetRHI(); 183 | GraphicsPSOInitializer.RasterizerState = TStaticRasterizerState<>::GetRHI(); 184 | GraphicsPSOInitializer.PrimitiveType = PT_TriangleStrip; 185 | GraphicsPSOInitializer.BoundShaderState.VertexDeclarationRHI = GTextureVertexDeclaration.VertexDeclarationRHI; 186 | GraphicsPSOInitializer.BoundShaderState.VertexShaderRHI = GETSAFERHISHADER_VERTEX(*VertexShader); 187 | GraphicsPSOInitializer.BoundShaderState.PixelShaderRHI = GETSAFERHISHADER_PIXEL(*PixelShader); 188 | SetGraphicsPipelineState(RHICmdList, GraphicsPSOInitializer); 189 | 190 | OnSetupPixelShader_RenderThread(RHICmdList, PixelShader, Parameters); 191 | 192 | #if (ENGINE_MINOR_VERSION >= 21) 193 | RHICmdList.SetStreamSource(0, FShadersPlusUtilities::CreateQuadVertexBuffer(), 0); 194 | RHICmdList.DrawPrimitive(PT_TriangleStrip, 0, 2, 1); 195 | 196 | //RHICmdList.CopyToResolveTarget( 197 | // RenderTarget->GetRenderTargetTexture(), 198 | // RenderTarget->TextureRHI, 199 | // FResolveParams()); 200 | #else 201 | FTextureVertex Vertices[4]; 202 | Vertices[0].Position = FVector4(-1.0f, 1.0f, 0, 1.0f); 203 | Vertices[1].Position = FVector4(1.0f, 1.0f, 0, 1.0f); 204 | Vertices[2].Position = FVector4(-1.0f, -1.0f, 0, 1.0f); 205 | Vertices[3].Position = FVector4(1.0f, -1.0f, 0, 1.0f); 206 | Vertices[0].UV = FVector2D(0, 0); 207 | Vertices[1].UV = FVector2D(1, 0); 208 | Vertices[2].UV = FVector2D(0, 1); 209 | Vertices[3].UV = FVector2D(1, 1); 210 | 211 | // Deprecated in 4.21 212 | DrawPrimitiveUP(RHICmdList, PT_TriangleStrip, 2, Vertices, sizeof(Vertices[0])); 213 | 214 | //RHICmdList.CopyToResolveTarget( 215 | // RenderTarget->GetRenderTargetTexture(), 216 | // RenderTarget->TextureRHI, 217 | // false, 218 | // FResolveParams()); 219 | #endif 220 | if(DrawToQuadParameters.bGenerateMips) 221 | RHICmdList.GenerateMips(RenderTarget->TextureRHI); 222 | 223 | //RHICmdList.GenerateMips(RenderTarget->GetRenderTargetTexture()); 224 | 225 | OnTeardownPixelShader_RenderThread(RHICmdList, PixelShader); 226 | 227 | bIsExecuting = false; 228 | } 229 | 230 | virtual void OnSetupVertexShader_RenderThread(FRHICommandList& RHICmdList, TShaderMapRef VertexShader, TParameters& Parameters) { } 231 | virtual void OnSetupPixelShader_RenderThread(FRHICommandList& RHICmdList, TShaderMapRef PixelShader, TParameters& Parameters) { } 232 | virtual void OnTeardownPixelShader_RenderThread(FRHICommandList& RHICmdList, TShaderMapRef PixelShader) { } 233 | }; -------------------------------------------------------------------------------- /Source/ShadersPlus/Public/ShadersPlusMacros.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define SHOULD_CACHE(Condition) static bool ShouldCache(EShaderPlatform Platform) { return Condition; } 4 | #define SHOULD_CACHE_WITH_FEATURE_LEVEL(FeatureLevel) SHOULD_CACHE(IsFeatureLevelSupported(Platform, FeatureLevel)) 5 | 6 | #define SHOULD_COMPILE(Condition) static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) \ 7 | { \ 8 | return Condition; \ 9 | } 10 | #define SHOULD_COMPILE_WITH_FEATURE_LEVEL(FeatureLevel) SHOULD_COMPILE(IsFeatureLevelSupported(Parameters.Platform, FeatureLevel)) 11 | 12 | #define DECLARE_SET_PARAMETER(ParameterType, ParameterName) void Set##ParameterName(FRHICommandList& RHICmdList, ParameterType ParameterName) 13 | 14 | #define _IMPLEMENT_SET_PARAMETER(DeclarationType, ParameterType, ParameterName, ShaderType, Setter) void DeclarationType::Set##ParameterName(FRHICommandList& RHICmdList, ParameterType ParameterName) \ 15 | { \ 16 | const auto ShaderType##ShaderRHI = Get##ShaderType##Shader(); \ 17 | if (this->##ParameterName.IsBound()) \ 18 | RHICmdList.##Setter(ShaderType##ShaderRHI, this->##ParameterName.GetBaseIndex(), ##ParameterName); \ 19 | } 20 | 21 | #define IMPLEMENT_SET_PARAMETER_SRV(DeclarationType, ParameterName, ShaderType) _IMPLEMENT_SET_PARAMETER(DeclarationType, FShaderResourceViewRHIRef, ParameterName, ShaderType, SetShaderResourceViewParameter) 22 | #define IMPLEMENT_SET_PARAMETER_UAV(DeclarationType, ParameterName, ShaderType) _IMPLEMENT_SET_PARAMETER(DeclarationType, FUnorderedAccessViewRHIRef, ParameterName, ShaderType, SetUAVParameter) 23 | #define IMPLEMENT_SET_PARAMETER_SAMPLER(DeclarationType, ParameterName, ShaderType) _IMPLEMENT_SET_PARAMETER(DeclarationType, FSamplerStateRHIParamRef, ParameterName, ShaderType, SetShaderSampler) 24 | 25 | #define BIND(ParameterName) ParameterName.Bind(Initializer.ParameterMap, TEXT(#ParameterName)) 26 | 27 | #define _UNBIND(ParameterType, ParameterName, ShaderType, Setter) if(this->##ParameterName##.IsBound()) \ 28 | RHICmdList.##Setter(ShaderType##ShaderRHI, this->##ParameterName##.GetBaseIndex(), ##ParameterType()) \ 29 | 30 | #define UNBIND_SRV(ParameterName, ShaderType) _UNBIND(FShaderResourceViewRHIParamRef, ParameterName, ShaderType, SetShaderResourceViewParameter) 31 | #define UNBIND_UAV(ParameterName, ShaderType) _UNBIND(FUnorderedAccessViewRHIRef, ParameterName, ShaderType, SetUAVParameter) -------------------------------------------------------------------------------- /Source/ShadersPlus/Public/ShadersPlusUtilities.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "RHICommandList.h" 5 | 6 | #include "ImageWriter.h" 7 | 8 | class UTexture2D; 9 | class UTextureRenderTarget2D; 10 | 11 | DECLARE_MULTICAST_DELEGATE_OneParam(FOnImageSaveRequest, FImageSaveTask&&); 12 | 13 | class SHADERSPLUS_API FShadersPlusUtilities 14 | { 15 | public: 16 | static FVertexBufferRHIRef CreateQuadVertexBuffer(); 17 | 18 | static bool CreateSRV(UTexture2D* Texture, FShaderResourceViewRHIRef& OutSRV); 19 | static bool CreateUAV(UTexture2D* Texture, FUnorderedAccessViewRHIRef& OutUAV); 20 | static bool CreateUAV(UTextureRenderTarget2D* Texture, FUnorderedAccessViewRHIRef& OutUAV); 21 | 22 | static void SaveScreenshot(UTexture2D* Texture, const FString& FilePath); 23 | static void SaveScreenshot(UTextureRenderTarget2D* Texture, const FString& FilePath); 24 | static void SaveScreenshot(FTexture2DRHIRef Texture, const FString& FilePath); 25 | static void SaveScreenshot(FShaderResourceViewRHIRef SRV, const FString& FilePath); 26 | 27 | static void SaveScreenshot_RenderThread(FRHICommandListImmediate& RHICmdList, FTexture2DRHIRef Texture, const FString& FilePath); 28 | 29 | private: 30 | static TUniquePtr ImageWriter; 31 | static FOnImageSaveRequest OnImageSaveRequest; 32 | }; -------------------------------------------------------------------------------- /Source/ShadersPlus/ShadersPlus.Build.cs: -------------------------------------------------------------------------------- 1 | using UnrealBuildTool; 2 | 3 | public class ShadersPlus : ModuleRules 4 | { 5 | public ShadersPlus(ReadOnlyTargetRules Target) : base(Target) 6 | { 7 | PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; 8 | 9 | if (Target.Version.MinorVersion <= 19) 10 | { 11 | PublicIncludePaths.AddRange( 12 | new string[] { 13 | "Public" 14 | }); 15 | 16 | PrivateIncludePaths.AddRange( 17 | new string[] { 18 | "Private" 19 | }); 20 | } 21 | 22 | PublicDependencyModuleNames.AddRange( 23 | new string[] { 24 | "Core", 25 | "Engine", 26 | "ImageWrapper", 27 | "Projects", 28 | "RenderCore", 29 | "RHI", 30 | }); 31 | 32 | if (Target.Version.MinorVersion <= 21) 33 | { 34 | PublicDependencyModuleNames.AddRange( 35 | new string[] 36 | { 37 | "ShaderCore", 38 | }); 39 | } 40 | 41 | if (Target.Version.MinorVersion >= 21) 42 | { 43 | PublicDependencyModuleNames.AddRange( 44 | new string[] { 45 | "ImageWriteQueue" 46 | }); 47 | } 48 | 49 | PrivateDependencyModuleNames.AddRange( 50 | new string[] { 51 | "CoreUObject", 52 | "Slate", 53 | "SlateCore" 54 | }); 55 | } 56 | } 57 | --------------------------------------------------------------------------------