# Apply shadow in ShaderMaterial

**URL:** <https://discourse.threejs.org/t/apply-shadow-in-shadermaterial/53833>\
**Category:** Questions\
**Tags:** shader-material, textures, materials, shaders\
**Created:** [July 13, 2023, 5:45am UTC](https://discourse.threejs.org/t/apply-shadow-in-shadermaterial/53833 "2023-07-13T05:45:24Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ammar\_Kayali](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/ammar_kayali/32/24212_2.png) [@Ammar\_Kayali](https://discourse.threejs.org/u/Ammar_Kayali)\
**Post date:** [July 13, 2023, 5:45am UTC](https://discourse.threejs.org/t/apply-shadow-in-shadermaterial/53833/1 "2023-07-13T05:45:24Z")

</div>

Hi All,

I want to active shadow in shaderMaterial , How can I do that?  
My code :

```javascript
   const shaderMaterial = new ShaderMaterial({
      vertexShader: `
    varying vec2 vUv;
    
    void main() {
      vUv = uv;
      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
  `,
      fragmentShader: `
    uniform sampler2D texture1;
    uniform sampler2D texture2;
    uniform float xCount;
    uniform float yCount;
    varying vec2 vUv;
    
    void main() {
      vec2 dynamicUV = vec2(mod(vUv.x * xCount, 1.0) , mod(vUv.y * yCount, 1.0));
      vec4 color;
       
      if( ((vUv.y < (1.0 / yCount)) || (vUv.y > 1.0 - ( 1.0 / yCount ))) && (vUv.x < ( 1.0 / xCount ) || vUv.x > 1.0 - ( 1.0 / xCount ) )){
        color = texture2D(texture1, dynamicUV);
      }else{
        color = texture2D(texture2, dynamicUV);
      }
      
      gl_FragColor = color;
    }
  `,
      uniforms: UniformsUtils.merge([
        UniformsLib.shadowmap,
        UniformsLib.lights,
        UniformsLib.ambient,
        {
          texture1: { value: texture1 },
          texture2: { value: texture2 },
          xCount: { value: 3.0 },
          yCount: { value: 3.0 },
        },
      ]),

      lights: true,
      blending: NoBlending

    });

```

But the shadow and light were not applied.

---

<div class="post-metadata">

**Author:** ![Oxyn](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/oxyn/32/12902_2.png) [@Oxyn](https://discourse.threejs.org/u/Oxyn)\
**Post date:** [July 13, 2023, 7:36am UTC](https://discourse.threejs.org/t/apply-shadow-in-shadermaterial/53833/2 "2023-07-13T07:36:16Z")

</div>

With the recent changes on color management and soon lighting, I strongly recommend to inject your GLSL code into native three shaders using `onBeforeCompile` instead.  
Because shaders chunks have become so convoluted (r151-154 is borderline pure madness), it’s not worth it to use `shaderMaterial` anymore **if you seek shadows an light** s. There is litterally hundreds of lines spread in 10+ chunks, to get it working.

_For the defense of three maintainers, it’s an unavoidable situation as they try to transition to webGPU and nodes while avoiding potential technical debts from the decade old webGL_

---

<div class="post-metadata">

**Author:** ![Ammar\_Kayali](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/ammar_kayali/32/24212_2.png) [@Ammar\_Kayali](https://discourse.threejs.org/u/Ammar_Kayali)\
**Post date:** [July 15, 2023, 5:23am UTC](https://discourse.threejs.org/t/apply-shadow-in-shadermaterial/53833/3 "2023-07-15T05:23:05Z")

</div>

Thank you @Oxyn ,

I tried to import it in function OnBeforeCompile but I get the same result, the shadow does not appear:

```javascript
let material = new ShaderMaterial({
      onBeforeCompile: (shader) => {
        shader.vertexShader = ` 
        varying vec2 vUv;
    
        void main() {
          vUv = uv;
          gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    } 
        `;
  
        shader.fragmentShader = `
        uniform sampler2D anglesTexture;
        uniform sampler2D texture2;
        uniform sampler2D textureShape;
        uniform float xCount;
        uniform float yCount;
        varying vec2 vUv;
        
        void main() {
          vec4 color1 ;
          vec2 dynamicUV = vec2(mod(vUv.x * xCount, 1.0) , mod(vUv.y * yCount, 1.0));
          vec4 color;
           
          if( ((vUv.y < (1.0 / yCount)) || (vUv.y > 1.0 - ( 1.0 / yCount ))) && (vUv.x < ( 1.0 / xCount ) || vUv.x > 1.0 - ( 1.0 / xCount ) )){
            color = texture2D(anglesTexture, dynamicUV);
          }else{
            color = texture2D(texture2, dynamicUV);
          }
          
          if( (vUv.y > 0.1 && vUv.y < 0.9) && (vUv.x > 0.2 && vUv.x < 0.45) ){
            color1 = texture2D(textureShape, dynamicUV);
          }
           

          
          // Custom blending logic
          vec4 blendedColor = mix(color, color1, 0.9);
          
          gl_FragColor = blendedColor;
        }
  
       `;
  
  
        shader.uniforms = UniformsUtils.merge([
          UniformsLib.shadowmap,
          UniformsLib.lights,
          UniformsLib.ambient,
          {
            anglesTexture: { value: anglesTexture },
            texture2: { value: texture2 },
            textureShape: { value: textureShape },
            xCount: { value: 10.0 },
            yCount: { value: 10.0 },
          },
        ]);
  
        shader.lights = true;
      },
    });

```

 ![Screenshot_13](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/5/1/51cb0f3fd12c2517c949f7093accf5bad60681a4.jpeg)

Here the wall does not have a shadow from the cabinet.

---

<div class="post-metadata">

**Author:** ![Oxyn](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/oxyn/32/12902_2.png) [@Oxyn](https://discourse.threejs.org/u/Oxyn)\
**Post date:** [July 15, 2023, 9:47am UTC](https://discourse.threejs.org/t/apply-shadow-in-shadermaterial/53833/4 "2023-07-15T09:47:03Z")

</div>

You need to use a native shader, you still use ShaderMaterial.

Something like this:

```javascript
//our new material will use the Phong shader as base
const material = new THREE.MeshPhongMaterial( {
		map: texture,
		color: 0xffffff
} );

//shader injection
material.onBeforeCompile = function ( shader ) {

	//exemple of uniforms definition for fragment
	shader.uniforms.myUniform = { value: myValue };
	shader.fragmentShader = 'uniform float myUniform;\n' + shader.fragmentShader;

	//exemple of replacing phong map_fragment chunk with custom code
	shader.fragmentShader = shader.fragmentShader.replace(
	'#include <map_fragment>',
	[
	//write custom code here
	].join( '\n' )
	);
};

```

To understand exactly which chunks you need to change. Look at the native shaders code here:  
in my exemple I would open `meshphong.glsl.js`

> <https://github.com/mrdoob/three.js/tree/master/src/renderers/shaders/ShaderLib>
>
> //github.com/mrdoob/three.js/tree/master/src/renderers/shaders/ShaderLib

Next look at the detailed code used by chunks here  
In my exemple I need to open `map_fragment.glsl.js` to either edit this code, or replace it.

> <https://github.com/mrdoob/three.js/tree/master/src/renderers/shaders/ShaderChunk>
>
> //github.com/mrdoob/three.js/tree/master/src/renderers/shaders/ShaderChunk

Since native shaders are very fragmented right now, it’s not a simple task either.  
But your shader will work with every features available.

---

<div class="post-metadata">

**Author:** ![Fyrestar](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/fyrestar/32/52793_2.png) [@Fyrestar](https://discourse.threejs.org/u/Fyrestar)\
**Post date:** [July 17, 2023, 7:35pm UTC](https://discourse.threejs.org/t/apply-shadow-in-shadermaterial/53833/6 "2023-07-17T19:35:42Z")

</div>

I made a plugin to make it much easier and cleaner to extend native shader. Also those with custom vertex transformations (see templates). If you only do minor changes you can also use ’ onBeforeCompile’ the `patchShader` of this lib however will also give you the cleaner patching functionality.

If you want to properly access uniforms you might want your materials to be based on `ShaderMaterial` then.

> [@Function to extend Materials](https://discourse.threejs.org/t/function-to-extend-materials/7882):
>
> This is a little helper function to create a THREE.ShaderMaterial extending a standard material. The second parameter is optional. Instead the constructor of a standard material, you can also pass a instance of a shader material and extend it the same way. Usage To extend materials: THREE.extendMaterial( constructor|material|shaderMaterial [, options]) For patching in onBeforeCompile: THREE.patchShader( object [, options]) const myMaterial = THREE.extendMaterial(THR…

---

<div class="post-metadata">

**Author:** ![Ammar\_Kayali](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/ammar_kayali/32/24212_2.png) [@Ammar\_Kayali](https://discourse.threejs.org/u/Ammar_Kayali)\
**Post date:** [July 18, 2023, 5:23am UTC](https://discourse.threejs.org/t/apply-shadow-in-shadermaterial/53833/7 "2023-07-18T05:23:45Z")

</div>

Thank you @Fyrestar ,

I tried your plugin , but I get white plane also , the code:

```javascript
const myMaterial = extendMaterial(MeshPhongMaterial, {

	// Will be prepended to vertex and fragment code
	header: 'varying vec2 vUv;',

	// Will be prepended to vertex code
	headerVertex: 'varying vec2 vUv;',

	// Will be prepended to fragment code
	headerFragment: `uniform sampler2D anglesTexture; \n
  uniform sampler2D texture2; \n
  uniform sampler2D textureShape; \n
  uniform float xCount; \n
  uniform float yCount; \n
  varying vec2 vUv;`,

	// Insert code lines by hinting at a existing
	vertex: {

	

		'#include <fog_vertex>': 'vUv = uv;',

		
	},
	fragment: {
	
      '@gl_FragColor': `vec4 color1 ;
      vec2 dynamicUV = vec2(mod(vUv.x * xCount, 1.0) , mod(vUv.y * yCount, 1.0));
      vec4 color;

      if( ((vUv.y < (1.0 / yCount)) || (vUv.y > 1.0 - ( 1.0 / yCount ))) && (vUv.x < ( 1.0 / xCount ) || vUv.x > 1.0 - ( 1.0 / xCount ) )){
      color = texture2D(anglesTexture, dynamicUV);
       }else{
        color = texture2D(texture2, dynamicUV);
      }

      if( (vUv.y > 0.1 && vUv.y < 0.9) && (vUv.x > 0.2 && vUv.x < 0.45) ){
      vec2 offsetUV = vec2(0.0001, 0.0001);
      vec2 modifiedUV = dynamicUV + offsetUV;
      color1 = texture2D(textureShape, modifiedUV);
      }
      vec4 blendedColor;

      const float borderSize = 0.01; // Adjust the border size as needed

      // Check if the UV coordinates are near the border
      bool nearBorder = (vUv.x < borderSize || vUv.x > 1.0 - borderSize || vUv.y < borderSize || vUv.y > 1.0 - borderSize);

      if (nearBorder) {
      // Apply blending factor based on the distance to the border
      float blendFactor = smoothstep(0.0, borderSize, min(min(vUv.x, 1.0 - vUv.x), min(vUv.y, 1.0 - vUv.y)));
      blendedColor = mix(color, color1, blendFactor);
      } else {
      blendedColor = color * (1.0 - color1.a) + color1 * color1.a;
      }

      gl_FragColor = blendedColor;

      
      `
	},

	// Properties to apply to the new THREE.ShaderMaterial
	material: {
		skinning: true
	},

	// Uniforms (will be applied to existing or added) as value or uniform object
	uniforms: {

    anglesTexture : { value: anglesTexture },  
    texture2 : { value: texture2 },
    textureShape : { value: textureShape },
    xCount : { value: 9.0 },
    yCount : { value: 9.0 }

	}

});

```

---

<div class="post-metadata">

**Author:** ![Fyrestar](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/fyrestar/32/52793_2.png) [@Fyrestar](https://discourse.threejs.org/u/Fyrestar)\
**Post date:** [July 18, 2023, 6:08am UTC](https://discourse.threejs.org/t/apply-shadow-in-shadermaterial/53833/8 "2023-07-18T06:08:09Z")

</div>

You’d need to provide a [codepen like this](https://codepen.io/Fyrestar/pen/jOqyppp), you can fork as template.

---

<div class="post-metadata">

**Author:** ![Ammar\_Kayali](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/ammar_kayali/32/24212_2.png) [@Ammar\_Kayali](https://discourse.threejs.org/u/Ammar_Kayali)\
**Post date:** [July 18, 2023, 6:40am UTC](https://discourse.threejs.org/t/apply-shadow-in-shadermaterial/53833/9 "2023-07-18T06:40:59Z")

</div>

This is the link : [Apply shadow and shader](https://codepen.io/Ammar-Kayali/pen/XWyqdxq?editors=0010)

Thank you @Fyrestar

---

<div class="post-metadata">

**Author:** ![Fyrestar](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/fyrestar/32/52793_2.png) [@Fyrestar](https://discourse.threejs.org/u/Fyrestar)\
**Post date:** [July 18, 2023, 7:12am UTC](https://discourse.threejs.org/t/apply-shadow-in-shadermaterial/53833/10 "2023-07-18T07:12:55Z")

</div>

You need to replace a proper line, you only replaced `gl_FragColor`, since you don’t use a built-in map you also need to define `USE_UV` in defines, not declaring vUv yourself as it would conflict.  
https://codepen.io/Fyrestar/embed/preview/KKrRMye?default-tabs=js%2Cresult&height=300&host=https%3A%2F%2Fcodepen.io&slug-hash=KKrRMye

---

<div class="post-metadata">

**Author:** ![Ammar\_Kayali](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/ammar_kayali/32/24212_2.png) [@Ammar\_Kayali](https://discourse.threejs.org/u/Ammar_Kayali)\
**Post date:** [July 18, 2023, 9:02am UTC](https://discourse.threejs.org/t/apply-shadow-in-shadermaterial/53833/11 "2023-07-18T09:02:49Z")

</div>

Thank you very much @Fyrestar ,  
I applied your code but the shadow is not applied.

 ![image](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/3/9/39ad061d64a52951cb567d946dfd2c86fd39f1de.jpeg)

---

<div class="post-metadata">

**Author:** ![Fyrestar](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/fyrestar/32/52793_2.png) [@Fyrestar](https://discourse.threejs.org/u/Fyrestar)\
**Post date:** [July 18, 2023, 9:12am UTC](https://discourse.threejs.org/t/apply-shadow-in-shadermaterial/53833/12 "2023-07-18T09:12:43Z")

</div>

Acutally i forgot shadow is what you wanted, place your code earlier like at

```js
"#include <map_fragment>": "your code"

```

and write to `diffuseColor` **not** `gl_FragColor`

---

<div class="post-metadata">

**Author:** ![Ammar\_Kayali](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/ammar_kayali/32/24212_2.png) [@Ammar\_Kayali](https://discourse.threejs.org/u/Ammar_Kayali)\
**Post date:** [July 18, 2023, 9:29am UTC](https://discourse.threejs.org/t/apply-shadow-in-shadermaterial/53833/13 "2023-07-18T09:29:51Z")

</div>

It worked 💙, Thank you very much @Fyrestar .
