# Shader Material

> Learn about the shader material in Babylon.js.

Source: https://doc.babylonjs.com/features/featuresDeepDive/materials/shaders/shaderMaterial

## ShaderMaterial

The ShaderMaterial object has the necessary methods to pass data from your scene to the Vertex and Fragment Shaders and creates a material that can be applied to any mesh. This material affects how the mesh looks based on the code in the shaders.

It is created with:

```javascript
const myShaderMaterial = new BABYLON.ShaderMaterial(name, scene, route, options);
```

- `name`: A string, naming the shader
- `scene`: The scene in which the shader is to be used
- `route`: The route to the shader code. It can be any one of these:

  1. object: `{ vertex: "custom", fragment: "custom" }`, used with `BABYLON.Effect.ShadersStore["customVertexShader"]` and `BABYLON.Effect.ShadersStore["customFragmentShader"]`.
  2. object: `{ vertexElement: "vertexShaderCode", fragmentElement: "fragmentShaderCode" }`, used with shader code in `<script>` tags.
  3. object: `{ vertexSource: "vertex shader code string", fragmentSource: "fragment shader code string" }`, used with strings containing the shader code.
  4. string: `"./COMMON_NAME"`, used with external files _COMMON_NAME.vertex.fx_ and _COMMON_NAME.fragment.fx_, accessible through a file server (local or remote).

- `options`: An object containing `attributes` and `uniforms` arrays, with their names as strings.

An example:

```javascript
const myShaderMaterial = new BABYLON.ShaderMaterial("shader", scene, "./COMMON_NAME",
{
  attributes: ["position", "normal", "uv"],
  uniforms: ["world", "worldView", "worldViewProjection", "view", "projection", "time", "direction" ],
  samplers: ["textureSampler"],
  defines: ["MyDefine"],
  needAlphaBlending: true,
  needAlphaTesting: true
});
```

- Any attribute in the Vertex Shader code **must** appear in the `attributes` array.
- The uniform `worldViewProjection` **must** be declared in the Vertex Shader as type `mat4` and **must** be in the `uniforms` array, if it is to be used.
- Attributes and uniforms named in the arrays and not used in the shader code are ignored.
- If your shader code contains #define values, you can specify the ones you want to activate in the `defines` array.
- Uniforms assigned to textures in the shader code must be present in the samplers array. All other uniforms must be present in the uniforms array.

- [Playground: Simplest Shader Material](https://playground.babylonjs.com/#5T8G3I) - Most basic example of ShaderMaterial

- [Playground: Accessing a shader code file from Github](https://playground.babylonjs.com/#2TGH43) - Showing how to refer to shader files stored in a Github repository

An example of passing a texture:

```javascript
const myShaderMaterial = new BABYLON.ShaderMaterial("shader", scene, "./COMMON_NAME", {
  "attributes": ["position", "uv"],
  "uniforms": ["worldViewProjection"],
  "samplers": ["textureSampler"]
});
const amigaTexture = new BABYLON.Texture("amiga.jpg", scene);
myShaderMaterial.setTexture("textureSampler", amigaTexture);
```

- [Playground: Passing a texture sampler to a shader](https://playground.babylonjs.com/#D8IDR8) - Demonstrating how to pass a texture sampler to a shader

Other uniforms are passed, for example, as

```javascript
myShaderMaterial.setFloat("time", 0);
myShaderMaterial.setVector3("direction", BABYLON.Vector3.Zero());
```

where the set method's name depends on the type.

- [Playground: Passing and updating a Color3 uniform to a shader](https://playground.babylonjs.com/#5T8G3I#16) - Demonstrating how to pass a Color3 uniform to a shader

## Troubleshoot

When working with shaders, it is very useful to have a debug tool that can show the values passed to the shaders. For that purpose, you can use the Babylon Spector.js tool: https://github.com/BabylonJS/Spector.js, which works for any shader code, not just Babylon.js.

In some specific cases when you use post-processes, you might notice a slightly brighter color output than what you implemented in your shader. Read [this](https://doc.babylonjs.com/features/featuresDeepDive/materials/shaders/image_processing) if you want to know how to fix it.

## Further reading

- [Introduction To Shaders in Babylon.js](https://doc.babylonjs.com/features/featuresDeepDive/materials/shaders/introToShaders)
- [How To Put Shader Code in Babylon.js](https://doc.babylonjs.com/features/featuresDeepDive/materials/shaders/shaderCodeInBjs)
