# Custom shaders
Intermediate
Programmer
You can write your own shaders in Visual Studio and use them in [material attributes](../materials/material-attributes.md). For example, you can write a shader to add textures to materials based on the objects' world positions, or generate noise and use it to randomize material properties.
As shaders are text files, you can add comments, enable and disable lines of code, and edit them like any other code file. This makes them easy to maintain and iterate.
You can also use custom shaders to create custom post effects. For more information, see [Custom color transforms](../post-effects/color-transforms/custom-color-transforms.md).
## Create a shader
1. Make sure you have the [Stride Visual Studio extension](../../get-started/visual-studio-extension.md) installed. This is necessary to convert the shader files from SDSL ([Stride shading language](index.md)) to `.cs` files.
2. In Game Studio, in the toolbar, click  (**Open in IDE**) to open your project in Visual Studio.
3. In the Visual Studio **Solution Explorer**, right-click the project (eg *MyGame.Game*) and select **Add > New item**.

4. Select **Class**.

5. In the **Name** field, specify a name with the extension **.sdsl** (eg *MyShader.sdsl*), and click **Add**.

The Stride Visual Studio extension automatically generates a `.cs` file from the `.sdsl` file. The Solution Explorer lists it as a child of the `.sdsl` file.

6. Open the `.sdsl` file, remove the existing lines, and write your shader.
Shaders are written in Stride Shading Language (SDSL), which is based on HLSL. For more information, see [Shading language](index.md).
For example, this shader creates a green color (`RGBA 0;1;0;1`):
```cs
namespace MyGame
{
shader MyShader : ComputeColor
{
override float4 Compute()
{
return float4(0, 1, 0, 1);
}
};
}
```
>[!Note]
>Make sure the shader name in the file (eg `MyShader` above) is the same as the filename.
>[!Note]
>To be accessible from the Game Studio Property Grid, the shader must inherit from `ComputeColor`.
>As `ComputeColor` always returns a float4 value, properties that take float values (eg metalness and gloss maps) use the first component (the red component) of the value returned by `ComputeColor`.
7. Save all the files in the solution (**File > Save All**).
8. In Game Studio, reload the assemblies.

The **Asset View** lists the shader in the same directory as your scripts (eg **MyGame.Game**).

>[!Note]
>In some situations, Game Studio incorrectly identifies the shader as a script, as in the screenshot below:
>
>If this happens, restart Game Studio (**File > Reload project**).
## Use a custom shader
You can use custom shaders in any [material attribute](../materials/material-attributes.md).
1. In the **Asset View**, select the material you want to use the shader in.
2. In the **Property Grid**, next to the property you want to control with the shader, click  (**Change**) and select **Shader**.

3. In the field, type the name of your shader (eg *MyShader*).

The property uses the shader you specify.
> [!Tip]
> When you make a change to the `.sdsl` file in Visual Studio and save it, Game Studio automatically updates the project with your changes. If this doesn't happen, restart Game Studio (**File > Reload project**).
> [!Note]
> If you delete a shader from the project assets, to prevent errors, make sure you also remove it from the properties of materials that use it.
## Arguments and parameters
### Template arguments
[Template arguments](shading-language/templates.md) (generics) don't change at runtime. However, different materials can use different instances of the shader with different values.
When the shaders are compiled, Stride substitutes template arguments with the value you set in the Property Grid.
For example, the code below defines and uses the template argument `Frequency`:
```cs
shader ComputeColorWave : ComputeColor, Texturing
{
override float4 Compute()
{
return sin((Global.Time) * 2 * 3.14 * Frequency);
}
};
```

### Parameters
Parameters can be changed at runtime.
For example, the code below defines and uses the dynamic parameter `Frequency`:
```cs
shader ComputeColorWave: ComputeColor, Texturing
{
cbuffer PerMaterial
{
stage float Frequency = 1.0f;
}
override float4 Compute()
{
return sin(( Global.Time ) * 2 * 3.14 * Frequency);
}
};
```
To modify the value at runtime, access and set it in the material parameter collection. For example, to change the `Frequency`, use:
```cs
myMaterial.Passes[myPassIndex].Parameters.Set(ComputeColorWaveKeys.Frequency, MyFrequency);
```
> [!Note]
> `ComputeColorWaveKeys.Frequency` is generated by the Stride Visual Studio extension from the shader file.
### Compositions
This [composition](shading-language/composition.md) lets you set the `Frequency` in the Game Studio Property Grid:
```cs
shader ComputeColorWave : ComputeColor, Texturing
{
compose ComputeColor Frequency;
override float4 Compute()
{
return sin(( Global.Time ) * 2 * 3.14 * Frequency.Compute().r);
}
};
```
Then you can set the value in the material properties:

## Troubleshooting
You can access the compilation logs of your shaders through the Game Studio's debug window's EffectCompilerCache tab (`Ctrl+Shift+D` or `Help`>`Show debug window`).
The launcher hosts a Visual Studio extension specifically for syntax highlighting and errors you may want to use.
The engine's source also provides a good reference point for how one would write shaders. To that end [Stride.ShaderExplorer](https://github.com/tebjan/Stride.ShaderExplorer) facilitates the act of finding and browsing through the different shaders the source contains.
A common issue you may stumble onto is the following:
> E1202: The mixin X in Y dependency is not in the module
This error often comes about as a result of missing or malformed Generics and Composition nodes.
When that is the case you have two options:
- Either manually fill these in through the material's Yaml file.
- Or remove and add the shader back in.
In both cases, you will have to close the Game Studio before doing those operation, for the former it's to ensure that the asset is reloaded from the disk. And for the latter, it's because the cache used by the property grid needs to be rebuilt.
We're currently in the process of rebuilding the shader system's backend, which should hopefully get rid of these friction.
## Custom shader sample
For an example of a custom shader, see the **custom material shader** sample project included with Stride.

In the project, the **ComputeColorWaveNormal** shader is used in the **displacement map** and **surface** material properties.
## See also
* [Shading language](shading-language/index.md)
* [Custom color transforms](../post-effects/color-transforms/custom-color-transforms.md)
* [Material attributes](../materials/material-attributes.md)
* [Stride Visual Studio extension](../../get-started/visual-studio-extension.md)