S&box Wiki

Revision Difference

Compute_Shaders#551293

<cat>Material.ShaderBasic</cat> <title>Compute Shaders</title> # What can you do with compute shaders? You can use compute shaders to do lots of things, but their most common use is to generate textures at blazing fast speeds; here's an example that shows you how you can do that. ## C# side⤶ ⤶ Let's wrap our compute stuff in a class so it's nice and tidy:⤶ ⤶ ```⤶ // This is what contains our compute shader instance, as well as the texture⤶ // we're going to be rendering to. public class MyTextureGenerator⤶ { private ComputeShader computeShader;⤶ public Texture Texture { get; }⤶ ⤶ public MyTextureGenerator() {⤶ // Create a texture that we can use⤶ Texture = Texture.Create( 512, 512 ) .WithUAVBinding() // Needs to have this if we're using it in a compute shader⤶ .WithFormat( ImageFormat.RGBA16161616F ) // Other formats are available :-)⤶ .Finish();⤶ ⤶ computeShader = new ComputeShader( "my_compute_shader" ); // This should be the name of your shader⤶ }⤶ ⤶ public void Dispatch()⤶ {⤶ // Set up the shader...⤶ computeShader.Attributes.Set( "OutputTexture", Texture );⤶ ⤶ // ...and run it!⤶ computeShader.Dispatch( Texture.Width, Texture.Height, 1 );⤶ }⤶ }⤶ ## Using compute shaders from C#⤶ ⤶ Here's an example of creating a compute shader and populating a texture with it.⤶ ⤶ ```csharp⤶ // Create a compute shader from a .shader file⤶ var computeShader = new ComputeShader( "my_compute_shader" ); ⤶ // Create a texture for the compute shader to use⤶ var texture = Texture.Create( 512, 512 ) .WithUAVBinding() // Needs to have this if we're using it in a compute shader⤶ .WithFormat( ImageFormat.RGBA16161616F ) // Use whatever you need⤶ .Finish(); ⤶ // Attach texture to OutputTexture attribute in shader⤶ computeShader.Attributes.Set( "OutputTexture", texture );⤶ ⤶ // Dispatch computeShader.Dispatch( texture.Width, texture.Height, 1 );⤶ ``` ⤶ You then want to actually use that class in an entity:⤶ ⤶ ```⤶ // This is the game entity we use to draw a model with our generated texture.⤶ public class MyModel : ModelEntity⤶ {⤶ private MyTextureGenerator myTextureGenerator;⤶ ⤶ public override void Spawn()⤶ {⤶ base.Spawn();⤶ ⤶ Transmit = TransmitType.Always;⤶ }⤶ ⤶ public override void ClientSpawn()⤶ {⤶ // Set up our dispatching class.⤶ myTextureGenerator = new();⤶ }⤶ ⤶ [Event.PreRender]⤶ public void OnFrame()⤶ {⤶ // You can call this wherever you want, but we'll update it every frame for now.⤶ myTextureGenerator.Dispatch();⤶ ⤶ // Here's where we assign our generated texture to this entity's model.⤶ SceneObject.Attributes.Set( "Albedo", myTextureGenerator.Texture );⤶ }⤶ }⤶ ```⤶ ⤶ Spawn your entity somewhere, make sure it's visible.⤶ ⤶ ## Shader⤶ ⤶ Compute shaders are similar to normal VS/FS shaders, but they're a bit shorter and you can forego a lot of the includes. ⤶ Here's a really simple one that'll generate a solid pink texture:⤶ ⤶ ## HLSL Shader⤶ ⤶ Compute shaders are HLSL like normal shaders, except everything goes in a CS block and runs a method named MainCs.⤶ ⤶ Here's a really simple one that'll generate a solid pink texture:⤶ ``` //=========================================================================================================================⤶ // Optional⤶ //=========================================================================================================================⤶ HEADER⤶ {⤶ DevShader = true;⤶ Description = "My Cool Compute Shader";⤶ }⤶ ⤶ //=========================================================================================================================⤶ // Optional⤶ //=========================================================================================================================⤶ FEATURES⤶ {⤶ }⤶ ⤶ //=========================================================================================================================⤶ MODES { Default(); } ⤶ //=========================================================================================================================⤶ COMMON⤶ ⤶ COMMON⤶ { #include "common/shared.hlsl" } ⤶ //=========================================================================================================================⤶ CS⤶ ⤶ CS⤶ { // Output texture RWTexture2D<float4> g_tOutput< Attribute( "OutputTexture" ); >; [numthreads(8, 8, 1)] void MainCs( uint uGroupIndex : SV_GroupIndex, uint3 vThreadId : SV_DispatchThreadID ) { g_tOutput[vThreadId.xy] = float4( 1, 0, 1, 1 ); } } ```