├── .gitattributes ├── .gitignore ├── Config ├── DefaultEditor.ini ├── DefaultEngine.ini └── DefaultGame.ini ├── Content ├── M_ComputeResult.uasset ├── RT_ComputeResult.uasset ├── TestRT.uasset ├── TestRT_Mat.uasset └── VertPositionExample.umap ├── CustomComputeExample.uproject ├── LICENSE ├── Plugins └── CustomComputePlugin │ ├── CustomComputePlugin.uplugin │ ├── Resources │ └── Icon128.png │ ├── Shaders │ └── Private │ │ └── ComputeShader.usf │ └── Source │ ├── CustomComputeModule │ ├── CustomComputeModule.Build.cs │ ├── Private │ │ ├── CustomComputeModule.cpp │ │ └── CustomComputeShader.cpp │ └── Public │ │ ├── CustomComputeModule.h │ │ └── CustomComputeShader.h │ └── SceneObjectsModule │ ├── Private │ ├── MeshActor.cpp │ └── SceneObjectsModule.cpp │ ├── Public │ ├── MeshActor.h │ └── SceneObjectsModule.h │ └── SceneObjectsModule.Build.cs ├── README.md └── Source ├── CustomComputeExample.Target.cs ├── CustomComputeExample ├── CustomComputeExample.Build.cs ├── CustomComputeExample.cpp ├── CustomComputeExample.h ├── CustomComputeExampleGameModeBase.cpp └── CustomComputeExampleGameModeBase.h └── CustomComputeExampleEditor.Target.cs /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Visual Studio 2015 user specific files 2 | .vs/ 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | 22 | # Compiled Static libraries 23 | *.lai 24 | *.la 25 | *.a 26 | *.lib 27 | 28 | # Executables 29 | *.exe 30 | *.out 31 | *.app 32 | *.ipa 33 | 34 | # These project files can be generated by the engine 35 | *.xcodeproj 36 | *.xcworkspace 37 | *.sln 38 | *.suo 39 | *.opensdf 40 | *.sdf 41 | *.VC.db 42 | *.VC.opendb 43 | 44 | # Precompiled Assets 45 | SourceArt/**/*.png 46 | SourceArt/**/*.tga 47 | 48 | # Binary Files 49 | Binaries/* 50 | Plugins/*/Binaries/* 51 | 52 | # Builds 53 | Build/* 54 | 55 | # Whitelist PakBlacklist-.txt files 56 | !Build/*/ 57 | Build/*/** 58 | !Build/*/PakBlacklist*.txt 59 | 60 | # Don't ignore icon files in Build 61 | !Build/**/*.ico 62 | 63 | # Built data for maps 64 | *_BuiltData.uasset 65 | 66 | # Configuration files generated by the Editor 67 | Saved/* 68 | 69 | # Compiled source files for the engine to use 70 | Intermediate/* 71 | Plugins/*/Intermediate/* 72 | 73 | # Cache files for the editor to use 74 | DerivedDataCache/* 75 | -------------------------------------------------------------------------------- /Config/DefaultEditor.ini: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nfgrep/CustomComputeExample/b31404d84d3c128937e42c7261031511d8b7b481/Config/DefaultEditor.ini -------------------------------------------------------------------------------- /Config/DefaultEngine.ini: -------------------------------------------------------------------------------- 1 | 2 | 3 | [/Script/EngineSettings.GameMapsSettings] 4 | GameDefaultMap=/Engine/Maps/Templates/Template_Default.Template_Default 5 | 6 | 7 | [/Script/HardwareTargeting.HardwareTargetingSettings] 8 | TargetedHardwareClass=Desktop 9 | AppliedTargetedHardwareClass=Desktop 10 | DefaultGraphicsPerformance=Maximum 11 | AppliedDefaultGraphicsPerformance=Maximum 12 | 13 | [/Script/Engine.Engine] 14 | +ActiveGameNameRedirects=(OldGameName="TP_Blank",NewGameName="/Script/CustomComputeExample") 15 | +ActiveGameNameRedirects=(OldGameName="/Script/TP_Blank",NewGameName="/Script/CustomComputeExample") 16 | +ActiveClassRedirects=(OldClassName="TP_BlankGameModeBase",NewClassName="CustomComputeExampleGameModeBase") 17 | 18 | -------------------------------------------------------------------------------- /Config/DefaultGame.ini: -------------------------------------------------------------------------------- 1 | 2 | [/Script/EngineSettings.GeneralProjectSettings] 3 | ProjectID=4EF2CD9F4B9669F2F85CA2AED550E7A2 4 | -------------------------------------------------------------------------------- /Content/M_ComputeResult.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nfgrep/CustomComputeExample/b31404d84d3c128937e42c7261031511d8b7b481/Content/M_ComputeResult.uasset -------------------------------------------------------------------------------- /Content/RT_ComputeResult.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nfgrep/CustomComputeExample/b31404d84d3c128937e42c7261031511d8b7b481/Content/RT_ComputeResult.uasset -------------------------------------------------------------------------------- /Content/TestRT.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nfgrep/CustomComputeExample/b31404d84d3c128937e42c7261031511d8b7b481/Content/TestRT.uasset -------------------------------------------------------------------------------- /Content/TestRT_Mat.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nfgrep/CustomComputeExample/b31404d84d3c128937e42c7261031511d8b7b481/Content/TestRT_Mat.uasset -------------------------------------------------------------------------------- /Content/VertPositionExample.umap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nfgrep/CustomComputeExample/b31404d84d3c128937e42c7261031511d8b7b481/Content/VertPositionExample.umap -------------------------------------------------------------------------------- /CustomComputeExample.uproject: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "EngineAssociation": "4.27", 4 | "Category": "", 5 | "Description": "", 6 | "Modules": [ 7 | { 8 | "Name": "CustomComputeExample", 9 | "Type": "Runtime", 10 | "LoadingPhase": "Default" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Nathan Faber-Good 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Plugins/CustomComputePlugin/CustomComputePlugin.uplugin: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "Version": 1, 4 | "VersionName": "1.0", 5 | "FriendlyName": "CustomComputePlugin", 6 | "Description": "", 7 | "Category": "Other", 8 | "CreatedBy": "nfgrep", 9 | "CreatedByURL": "", 10 | "DocsURL": "", 11 | "MarketplaceURL": "", 12 | "SupportURL": "", 13 | "CanContainContent": true, 14 | "IsBetaVersion": false, 15 | "IsExperimentalVersion": false, 16 | "Installed": false, 17 | "Modules": [ 18 | { 19 | "Name": "CustomComputeModule", 20 | "Type": "Runtime", 21 | "LoadingPhase": "PostConfigInit" 22 | }, 23 | { 24 | "Name": "SceneObjectsModule", 25 | "Type": "Runtime", 26 | "LoadingPhase": "Default" 27 | } 28 | 29 | ] 30 | } -------------------------------------------------------------------------------- /Plugins/CustomComputePlugin/Resources/Icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nfgrep/CustomComputeExample/b31404d84d3c128937e42c7261031511d8b7b481/Plugins/CustomComputePlugin/Resources/Icon128.png -------------------------------------------------------------------------------- /Plugins/CustomComputePlugin/Shaders/Private/ComputeShader.usf: -------------------------------------------------------------------------------- 1 | #include "/Engine/Public/Platform.ush" 2 | 3 | StructuredBuffer Vertices; 4 | RWTexture2D OutputTexture; 5 | 6 | [numthreads(32, 32, 1)] 7 | void MainCompute(uint3 ThreadId : SV_DispatchThreadID) 8 | { 9 | // Take the first vertex and normalize it 10 | float3 Vert = normalize(Vertices[0]); 11 | // Use it as this pixel's colour 12 | OutputTexture[ThreadId.xy] = float4(Vert.x, Vert.y, Vert.z, 1); 13 | } -------------------------------------------------------------------------------- /Plugins/CustomComputePlugin/Source/CustomComputeModule/CustomComputeModule.Build.cs: -------------------------------------------------------------------------------- 1 | // Author: nfgrep 2 | // 2021 3 | 4 | using UnrealBuildTool; 5 | 6 | public class CustomComputeModule : ModuleRules 7 | { 8 | public CustomComputeModule(ReadOnlyTargetRules Target) : base(Target) 9 | { 10 | PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; 11 | 12 | PublicIncludePaths.AddRange( 13 | new string[] { 14 | // ... add public include paths required here ... 15 | } 16 | ); 17 | 18 | 19 | PrivateIncludePaths.AddRange( 20 | new string[] { 21 | // ... add other private include paths required here ... 22 | } 23 | ); 24 | 25 | 26 | PublicDependencyModuleNames.AddRange( 27 | new string[] 28 | { 29 | "Core", 30 | // ... add other public dependencies that you statically link with here ... 31 | } 32 | ); 33 | 34 | 35 | PrivateDependencyModuleNames.AddRange( 36 | new string[] 37 | { 38 | "CoreUObject", 39 | "Engine", 40 | "Slate", 41 | "SlateCore", 42 | "RenderCore", 43 | "RHI", 44 | "Projects" 45 | // ... add private dependencies that you statically link with here ... 46 | } 47 | ); 48 | 49 | 50 | DynamicallyLoadedModuleNames.AddRange( 51 | new string[] 52 | { 53 | // ... add any modules that your module loads dynamically here ... 54 | } 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Plugins/CustomComputePlugin/Source/CustomComputeModule/Private/CustomComputeModule.cpp: -------------------------------------------------------------------------------- 1 | // Author: nfgrep 2 | // 2021 3 | 4 | #include "CustomComputeModule.h" 5 | #include "CustomComputeShader.h" 6 | #include "Interfaces/IPluginManager.h" 7 | #include "GlobalShader.h" 8 | #include "ShaderCore.h" 9 | 10 | #define LOCTEXT_NAMESPACE "FCustomComputeModule" 11 | 12 | void FCustomComputeModule::StartupModule() 13 | { 14 | // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module 15 | FString PluginShaderDir = FPaths::Combine(IPluginManager::Get().FindPlugin(TEXT("CustomComputePlugin"))->GetBaseDir(), TEXT("Shaders")); 16 | AddShaderSourceDirectoryMapping(TEXT("/Shaders"), PluginShaderDir); 17 | } 18 | 19 | void FCustomComputeModule::ShutdownModule() 20 | { 21 | // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, 22 | // we call this function before unloading the module. 23 | } 24 | 25 | 26 | void FCustomComputeModule::EnqueueRenderCommand(UTextureRenderTarget2D* RenderTarget, TArray Vertices) 27 | { 28 | TShaderMapRef ComputeShader(GetGlobalShaderMap(GMaxRHIFeatureLevel)); 29 | 30 | UTextureRenderTarget2D* RenderTargetParam = RenderTarget; 31 | TArray VerticesParam = Vertices; 32 | 33 | ENQUEUE_RENDER_COMMAND(ComputeShader)( 34 | [ 35 | ComputeShader, 36 | RenderTargetParam, 37 | VerticesParam 38 | ](FRHICommandListImmediate& RHICmdList) 39 | { 40 | ComputeShader->BuildAndExecuteGraph( 41 | RHICmdList, 42 | RenderTargetParam, 43 | VerticesParam); 44 | }); 45 | } 46 | 47 | #undef LOCTEXT_NAMESPACE 48 | 49 | IMPLEMENT_MODULE(FCustomComputeModule, CustomComputeModule) -------------------------------------------------------------------------------- /Plugins/CustomComputePlugin/Source/CustomComputeModule/Private/CustomComputeShader.cpp: -------------------------------------------------------------------------------- 1 | // Author: nfgrep 2 | // 2021 3 | 4 | #include "CustomComputeShader.h" 5 | #include "RenderGraph.h" 6 | #include "RenderTargetPool.h" 7 | #include "Engine/TextureRenderTarget2D.h" 8 | 9 | // Associating the FCustomComputeShader class with the custom HLSL shader code 10 | IMPLEMENT_GLOBAL_SHADER(FCustomComputeShader, "/Shaders/Private/ComputeShader.usf", "MainCompute", SF_Compute); 11 | 12 | 13 | // This method builds and calls .Execute() on a render-graph for a single frame 14 | void FCustomComputeShader::BuildAndExecuteGraph(FRHICommandListImmediate &RHICmdList, UTextureRenderTarget2D* RenderTarget, TArray InVerts) 15 | { 16 | // Our main point of contant with the RDG 17 | // We will use this to add resources (buffers) and passes to the render-graph 18 | FRDGBuilder GraphBuilder(RHICmdList); 19 | 20 | 21 | // This is a pointer to the shader-parameters we declared in the .h 22 | FParameters* PassParameters; 23 | // We ask the RDG to allocate some memory for our shader-parameters 24 | PassParameters = GraphBuilder.AllocParameters(); 25 | 26 | 27 | // --- Creating an SRV filled with vertex data --- 28 | // 1. Create a structured buffer 29 | FRDGBufferRef VerticesBuffer = CreateStructuredBuffer( 30 | GraphBuilder, 31 | TEXT("Vertices_StructuredBuffer"), 32 | sizeof(FVector), 33 | InVerts.Num(), 34 | InVerts.GetData(), 35 | sizeof(FVector) * InVerts.Num() 36 | ); 37 | // 2. Create an RDG-tracked SRV from our structured buffer 38 | FRDGBufferSRVRef VerticesSRV = GraphBuilder.CreateSRV(VerticesBuffer, PF_R32_UINT); 39 | // 3. Set our pass params 40 | PassParameters->Vertices = VerticesSRV; 41 | 42 | 43 | // --- Creating a texture for the compute shader to write to --- 44 | // 1. Make a texture description 45 | FRDGTextureDesc OutTextureDesc = FRDGTextureDesc::Create2D( 46 | FIntPoint(RenderTarget->SizeX, RenderTarget->SizeY), 47 | PF_FloatRGBA, 48 | FClearValueBinding(), 49 | TexCreate_UAV, 50 | 1, 51 | 1); 52 | // 2. Allocate memory with above desc and get a ref to it 53 | FRDGTextureRef OutTextureRef = GraphBuilder.CreateTexture(OutTextureDesc, TEXT("Compute_Out_Texture")); 54 | // 3. Make a UAV description from our Texture Ref 55 | FRDGTextureUAVDesc OutTextureUAVDesc(OutTextureRef); 56 | // 4. Initialize it as our OutputTexture in our pass params 57 | PassParameters->OutputTexture = GraphBuilder.CreateUAV(OutTextureUAVDesc); 58 | 59 | 60 | // ------ Add the compute pass ------ 61 | // Get a reference to our global shader class 62 | TShaderMapRef ComputeShader(GetGlobalShaderMap(GMaxRHIFeatureLevel)); 63 | // Add the compute shader pass to the render graph 64 | FComputeShaderUtils::AddPass(GraphBuilder, RDG_EVENT_NAME("Compute Pass"), ComputeShader, PassParameters, FIntVector(32, 32, 1)); 65 | 66 | 67 | // ------ Extracting to pooled render target ------ 68 | TRefCountPtr PooledComputeTarget; 69 | // Copy the result of compute shader from UAV to pooled renderT-target 70 | GraphBuilder.QueueTextureExtraction(OutTextureRef, &PooledComputeTarget); 71 | 72 | // Execute the graph 73 | GraphBuilder.Execute(); 74 | 75 | // Queue the UAV we wrote to for extraction 76 | RHICmdList.CopyToResolveTarget(PooledComputeTarget.GetReference()->GetRenderTargetItem().TargetableTexture, RenderTarget->GetRenderTargetResource()->TextureRHI, FResolveParams()); 77 | } 78 | 79 | -------------------------------------------------------------------------------- /Plugins/CustomComputePlugin/Source/CustomComputeModule/Public/CustomComputeModule.h: -------------------------------------------------------------------------------- 1 | // Author: nfgrep 2 | // 2021 3 | 4 | #pragma once 5 | 6 | #include "CoreMinimal.h" 7 | #include "Modules/ModuleManager.h" 8 | 9 | // We'll use this class as the API for our CustomComputeModule 10 | // This will be the only class exposed to other modules via the CUSTOMCOMPUTEMODULE_API 11 | class CUSTOMCOMPUTEMODULE_API FCustomComputeModule : public IModuleInterface 12 | { 13 | public: 14 | 15 | virtual void StartupModule() override; 16 | virtual void ShutdownModule() override; 17 | 18 | void EnqueueRenderCommand(UTextureRenderTarget2D* RenderTarget, TArray Vertices); 19 | }; 20 | -------------------------------------------------------------------------------- /Plugins/CustomComputePlugin/Source/CustomComputeModule/Public/CustomComputeShader.h: -------------------------------------------------------------------------------- 1 | // Author: nfgrep 2 | // 2021 3 | 4 | #pragma once 5 | 6 | #include "CoreMinimal.h" 7 | #include "GlobalShader.h" 8 | #include "ShaderParameterStruct.h" 9 | 10 | // This is the class that represents our shader within the engine 11 | // This class is associated with shader-code in the corresponding .cpp 12 | class FCustomComputeShader : public FGlobalShader 13 | { 14 | DECLARE_GLOBAL_SHADER(FCustomComputeShader) 15 | SHADER_USE_PARAMETER_STRUCT(FCustomComputeShader, FGlobalShader) 16 | BEGIN_SHADER_PARAMETER_STRUCT(FParameters, ) 17 | 18 | SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, Vertices) 19 | 20 | SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, OutputTexture) 21 | 22 | END_SHADER_PARAMETER_STRUCT() 23 | 24 | static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) 25 | { 26 | return IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM5); 27 | } 28 | 29 | void BuildAndExecuteGraph(FRHICommandListImmediate& RHICmdList, UTextureRenderTarget2D* RenderTarget, TArray InVerts); 30 | }; -------------------------------------------------------------------------------- /Plugins/CustomComputePlugin/Source/SceneObjectsModule/Private/MeshActor.cpp: -------------------------------------------------------------------------------- 1 | // Author: nfgrep 2 | // 2021 3 | 4 | #include "MeshActor.h" 5 | 6 | 7 | // Sets default values 8 | AMeshActor::AMeshActor() 9 | { 10 | PrimaryActorTick.bCanEverTick = true; 11 | 12 | // Setup a static mesh component for this actor 13 | ExampleMesh = CreateDefaultSubobject(TEXT("Example Mesh")); 14 | // Set the static mesh to the cube included with the engine 15 | static ConstructorHelpers::FObjectFinder CubeMesh(TEXT("StaticMesh'/Engine/BasicShapes/Cube.Cube'")); 16 | ExampleMesh->SetStaticMesh(CubeMesh.Object); 17 | // Make the static mesh component the root of this actor 18 | RootComponent = ExampleMesh; 19 | 20 | // Get a reference to the CustomeComputeModule 21 | ComputeModule = FModuleManager::LoadModuleChecked("CustomComputeModule"); 22 | } 23 | 24 | void AMeshActor::BeginPlay() 25 | { 26 | Super::BeginPlay(); 27 | 28 | if (!RenderTarget) 29 | { 30 | GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Red, TEXT("No Render Target")); 31 | this->SetActorTickEnabled(false); 32 | } 33 | else if (!ExampleMesh) 34 | { 35 | GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Red, TEXT("No Static Mesh Property")); 36 | this->SetActorTickEnabled(false); 37 | } 38 | } 39 | 40 | void AMeshActor::Tick(float DeltaTime) 41 | { 42 | Super::Tick(DeltaTime); 43 | 44 | ComputeModule.EnqueueRenderCommand(RenderTarget, GetVerts(this)); 45 | } 46 | 47 | // Returns the vertices for the given actor in world-space 48 | TArray AMeshActor::GetVerts(AActor* Actor) 49 | { 50 | // The array we'll return 51 | TArray MeshVerts; 52 | 53 | // Get a static mesh from the first component 54 | TArray StaticMeshComponents = TArray(); 55 | Actor->GetComponents(StaticMeshComponents); 56 | UStaticMesh* StaticMesh = StaticMeshComponents[0]->GetStaticMesh(); 57 | 58 | // Check if the static mesh is null 59 | if (!StaticMesh) 60 | { 61 | GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Red, FString::Printf(TEXT("StaticMesh[0] was null for actor: ")).Append(Actor->GetName())); 62 | return MeshVerts; 63 | } 64 | 65 | // Check if this static mesh has a LOD 66 | if (!(StaticMesh->GetRenderData()->LODResources.Num() > 0)) 67 | { 68 | GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Red, TEXT("Each mesh must have the supplied LOD To Use")); 69 | return MeshVerts; 70 | } 71 | 72 | // Get the vertices 73 | FPositionVertexBuffer* VertexBuffer = &StaticMesh->GetRenderData()->LODResources[0].VertexBuffers.PositionVertexBuffer; 74 | for (uint32 VertIdx = 0; VertIdx < VertexBuffer->GetNumVertices(); VertIdx++) 75 | { 76 | // Get this vertex 77 | FVector VertexLS = VertexBuffer->VertexPosition(VertIdx); 78 | 79 | // Transform from local to world space 80 | FVector VertexWS = Actor->GetTransform().TransformPosition(VertexLS); 81 | 82 | // Add it to the array we'll return 83 | MeshVerts.Add(VertexWS); // NOTE: .Add can be pretty slow! 84 | } 85 | 86 | return MeshVerts; 87 | } 88 | 89 | 90 | -------------------------------------------------------------------------------- /Plugins/CustomComputePlugin/Source/SceneObjectsModule/Private/SceneObjectsModule.cpp: -------------------------------------------------------------------------------- 1 | // Author: nfgrep 2 | // 2021 3 | 4 | #include "SceneObjectsModule.h" 5 | 6 | #define LOCTEXT_NAMESPACE "FSceneObjectseModule" 7 | 8 | void FSceneObjectsModule::StartupModule() 9 | { 10 | // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module 11 | } 12 | 13 | void FSceneObjectsModule::ShutdownModule() 14 | { 15 | // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, 16 | // we call this function before unloading the module. 17 | } 18 | 19 | #undef LOCTEXT_NAMESPACE 20 | 21 | IMPLEMENT_MODULE(FSceneObjectsModule, SceneObjectsModule) -------------------------------------------------------------------------------- /Plugins/CustomComputePlugin/Source/SceneObjectsModule/Public/MeshActor.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CustomComputeModule.h" 6 | #include "CoreMinimal.h" 7 | #include "GameFramework/Actor.h" 8 | #include "MeshActor.generated.h" 9 | 10 | 11 | UCLASS() 12 | class SCENEOBJECTSMODULE_API AMeshActor : public AActor 13 | { 14 | GENERATED_BODY() 15 | 16 | public: 17 | AMeshActor(); 18 | 19 | // The mesh we'll get the data from 20 | UPROPERTY(VisibleAnywhere) 21 | UStaticMeshComponent* ExampleMesh; 22 | 23 | // The render-target we'll pass onto the GPU to be written to 24 | UPROPERTY(EditAnywhere) 25 | UTextureRenderTarget2D* RenderTarget; 26 | 27 | protected: 28 | virtual void BeginPlay() override; 29 | 30 | public: 31 | virtual void Tick(float DeltaTime) override; 32 | 33 | private: 34 | TArray GetVerts(AActor* Actor); 35 | FCustomComputeModule ComputeModule; 36 | }; 37 | -------------------------------------------------------------------------------- /Plugins/CustomComputePlugin/Source/SceneObjectsModule/Public/SceneObjectsModule.h: -------------------------------------------------------------------------------- 1 | // Author: nfgrep 2 | // 2021 3 | 4 | #pragma once 5 | 6 | #include "CoreMinimal.h" 7 | #include "Modules/ModuleManager.h" 8 | 9 | 10 | class FSceneObjectsModule : public IModuleInterface 11 | { 12 | public: 13 | 14 | /** IModuleInterface implementation */ 15 | virtual void StartupModule() override; 16 | virtual void ShutdownModule() override; 17 | 18 | }; 19 | -------------------------------------------------------------------------------- /Plugins/CustomComputePlugin/Source/SceneObjectsModule/SceneObjectsModule.Build.cs: -------------------------------------------------------------------------------- 1 | // Author: nfgrep 2 | // 2021 3 | 4 | using UnrealBuildTool; 5 | 6 | public class SceneObjectsModule: ModuleRules 7 | { 8 | public SceneObjectsModule(ReadOnlyTargetRules Target) : base(Target) 9 | { 10 | PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; 11 | 12 | PublicIncludePaths.AddRange( 13 | new string[] { 14 | // ... add public include paths required here ... 15 | } 16 | ); 17 | 18 | 19 | PrivateIncludePaths.AddRange( 20 | new string[] { 21 | // ... add other private include paths required here ... 22 | } 23 | ); 24 | 25 | 26 | PublicDependencyModuleNames.AddRange( 27 | new string[] 28 | { 29 | "Core", 30 | // ... add other public dependencies that you statically link with here ... 31 | } 32 | ); 33 | 34 | 35 | PrivateDependencyModuleNames.AddRange( 36 | new string[] 37 | { 38 | "CoreUObject", 39 | "Engine", 40 | "Slate", 41 | "SlateCore", 42 | "CustomComputeModule", 43 | // ... add private dependencies that you statically link with here ... 44 | } 45 | ); 46 | 47 | 48 | DynamicallyLoadedModuleNames.AddRange( 49 | new string[] 50 | { 51 | // ... add any modules that your module loads dynamically here ... 52 | } 53 | ); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CustomComputeExample 2 | This is an example of how to write custom compute-shaders in Unreal Engine 4.27 (there is also a 4.26 branch) 3 | The main goal of this project is to provide an example of how to use the RDG to transfer large amounts of data to the GPU. 4 | The [Wiki](https://github.com/nfgrep/CustomComputeExample/wiki) of this project contains an explaination of the code. 5 | 6 | The implementation and usage of the shader lies entirely in the plugin of this project. 7 | To demonstrate the use of compute-shaders, the project just colours a texture with the position of the first vertex of a given mesh. 8 | -------------------------------------------------------------------------------- /Source/CustomComputeExample.Target.cs: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | using System.Collections.Generic; 5 | 6 | public class CustomComputeExampleTarget : TargetRules 7 | { 8 | public CustomComputeExampleTarget( TargetInfo Target) : base(Target) 9 | { 10 | Type = TargetType.Game; 11 | DefaultBuildSettings = BuildSettingsVersion.V2; 12 | ExtraModuleNames.AddRange( new string[] { "CustomComputeExample" } ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Source/CustomComputeExample/CustomComputeExample.Build.cs: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | 5 | public class CustomComputeExample : ModuleRules 6 | { 7 | public CustomComputeExample(ReadOnlyTargetRules Target) : base(Target) 8 | { 9 | PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; 10 | 11 | PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" }); 12 | 13 | PrivateDependencyModuleNames.AddRange(new string[] { }); 14 | 15 | // Uncomment if you are using Slate UI 16 | // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); 17 | 18 | // Uncomment if you are using online features 19 | // PrivateDependencyModuleNames.Add("OnlineSubsystem"); 20 | 21 | // To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Source/CustomComputeExample/CustomComputeExample.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "CustomComputeExample.h" 4 | #include "Modules/ModuleManager.h" 5 | 6 | IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, CustomComputeExample, "CustomComputeExample" ); 7 | -------------------------------------------------------------------------------- /Source/CustomComputeExample/CustomComputeExample.h: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | 7 | -------------------------------------------------------------------------------- /Source/CustomComputeExample/CustomComputeExampleGameModeBase.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | 4 | #include "CustomComputeExampleGameModeBase.h" 5 | 6 | -------------------------------------------------------------------------------- /Source/CustomComputeExample/CustomComputeExampleGameModeBase.h: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "GameFramework/GameModeBase.h" 7 | #include "CustomComputeExampleGameModeBase.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | UCLASS() 13 | class CUSTOMCOMPUTEEXAMPLE_API ACustomComputeExampleGameModeBase : public AGameModeBase 14 | { 15 | GENERATED_BODY() 16 | 17 | }; 18 | -------------------------------------------------------------------------------- /Source/CustomComputeExampleEditor.Target.cs: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | using System.Collections.Generic; 5 | 6 | public class CustomComputeExampleEditorTarget : TargetRules 7 | { 8 | public CustomComputeExampleEditorTarget( TargetInfo Target) : base(Target) 9 | { 10 | Type = TargetType.Editor; 11 | DefaultBuildSettings = BuildSettingsVersion.V2; 12 | ExtraModuleNames.AddRange( new string[] { "CustomComputeExample" } ); 13 | } 14 | } 15 | --------------------------------------------------------------------------------