# Extending Uniforms for customized Instanced Lambert Material

**URL:** <https://discourse.threejs.org/t/extending-uniforms-for-customized-instanced-lambert-material/12466>\
**Category:** Questions\
**Tags:** lambert-material, materials, instanced-mesh\
**Created:** [February 1, 2020, 3:42pm UTC](https://discourse.threejs.org/t/extending-uniforms-for-customized-instanced-lambert-material/12466 "2020-02-01T15:42:15Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![lxiangyun93](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/lxiangyun93/32/8839_2.png) [@lxiangyun93](https://discourse.threejs.org/u/lxiangyun93)\
**Post date:** [February 1, 2020, 3:42pm UTC](https://discourse.threejs.org/t/extending-uniforms-for-customized-instanced-lambert-material/12466/1 "2020-02-01T15:42:15Z")

</div>

Hi all, I created an customized lambert material for instancing (based on: [https://threejs.org/examples/?q=instanc#webgl\_buffergeometry\_instancing\_lambert](https://threejs.org/examples/?q=instanc#webgl_buffergeometry_instancing_lambert)), and I was trying to give extends its uniforms with some parameters relating to clipping, but somehow the material doesn’t seem to recognize it. Maybe the way I add uniform was wrong? could you guys help me here?

```
export function getMoleculeMaterialInstanced(options) {
    var uniforms = THREE.UniformsUtils.merge([
        THREE.ShaderLib.lambert.uniforms,
        {
            xClippingPlaneMax: { type: 'f', value: options.x_high },
            xClippingPlaneMin: { type: 'f', value: options.x_low },
            yClippingPlaneMax: { type: 'f', value: options.y_high },
            yClippingPlaneMin: { type: 'f', value: options.y_low },
            zClippingPlaneMax: { type: 'f', value: options.z_high },
            zClippingPlaneMin: { type: 'f', value: options.z_low },
        }
      ]);
    var material = new THREE.MeshLambertMaterial( {
        uniforms: uniforms,
        vertexColors: THREE.VertexColors,
    } );
    material.onBeforeCompile = function( shader ) {
        shader.vertexShader = `
            #define LAMBERT
            // instanced
            attribute vec3 offset;
            // attribute vec3 instanceColor;
            // attribute float instanceScale;
            varying vec3 vLightFront;
            varying vec3 vIndirectFront;
            varying vec3 slicePosition;
        
            #ifdef DOUBLE_SIDED
                varying vec3 vLightBack;
                varying vec3 vIndirectBack;
            #endif
        
            #include <common>
            #include <uv_pars_vertex>
            #include <uv2_pars_vertex>
            #include <envmap_pars_vertex>
            #include <bsdfs>
            #include <lights_pars_begin>
            #include <color_pars_vertex>
            #include <fog_pars_vertex>
            #include <morphtarget_pars_vertex>
            #include <skinning_pars_vertex>
            #include <shadowmap_pars_vertex>
            #include <logdepthbuf_pars_vertex>
            #include <clipping_planes_pars_vertex>
        
            void main() {
        
                #include <uv_vertex>
                #include <uv2_vertex>
                #include <color_vertex>
        
                // vertex colors instanced
                // #ifdef USE_COLOR
                // vColor.xyz = instanceColor.xyz;
                // #endif
        
                #include <beginnormal_vertex>
                #include <morphnormal_vertex>
                #include <skinbase_vertex>
                #include <skinnormal_vertex>
                #include <defaultnormal_vertex>
        
                #include <begin_vertex>
        
                // position instanced
                // transformed *= instanceScale;
                // transformed = transformed + instanceOffset;
                transformed = transformed + offset;
                slicePosition = transformed;
        
                #include <morphtarget_vertex>
                #include <skinning_vertex>
                #include <project_vertex>
                #include <logdepthbuf_vertex>
                #include <clipping_planes_vertex>
        
                #include <worldpos_vertex>
                #include <envmap_vertex>
                #include <lights_lambert_vertex>
                #include <shadowmap_vertex>
                #include <fog_vertex>
        
            }
            `;

        shader.fragmentShader = `
        uniform vec3 diffuse;
        uniform vec3 emissive;
        uniform float opacity;
        
        varying vec3 vLightFront;
        varying vec3 vIndirectFront;
        varying vec3 slicePosition;
        uniform float xClippingPlaneMax;
        uniform float xClippingPlaneMin;
        uniform float yClippingPlaneMax;
        uniform float yClippingPlaneMin;
        uniform float zClippingPlaneMax;
        uniform float zClippingPlaneMin;
        
        #ifdef DOUBLE_SIDED
            varying vec3 vLightBack;
            varying vec3 vIndirectBack;
        #endif
                
        #include <common>
        #include <packing>
        #include <dithering_pars_fragment>
        #include <color_pars_fragment>
        #include <uv_pars_fragment>
        #include <uv2_pars_fragment>
        #include <map_pars_fragment>
        #include <alphamap_pars_fragment>
        #include <aomap_pars_fragment>
        #include <lightmap_pars_fragment>
        #include <emissivemap_pars_fragment>
        #include <envmap_common_pars_fragment>
        #include <envmap_pars_fragment>
        #include <cube_uv_reflection_fragment>
        #include <bsdfs>
        #include <lights_pars_begin>
        #include <fog_pars_fragment>
        #include <shadowmap_pars_fragment>
        #include <shadowmask_pars_fragment>
        #include <specularmap_pars_fragment>
        #include <logdepthbuf_pars_fragment>
        #include <clipping_planes_pars_fragment>
        
        void main() {
            if(slicePosition.x<xClippingPlaneMin) discard;
            if(slicePosition.x>xClippingPlaneMax) discard;
            if(slicePosition.y<yClippingPlaneMin) discard;
            if(slicePosition.y>yClippingPlaneMax) discard;
            if(slicePosition.z<zClippingPlaneMin) discard;
            if(slicePosition.z>zClippingPlaneMax) discard;
        
            #include <clipping_planes_fragment>
        
            vec4 diffuseColor = vec4( diffuse, opacity );
            ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );
            vec3 totalEmissiveRadiance = emissive;
        
            #include <logdepthbuf_fragment>
            #include <map_fragment>
            #include <color_fragment>
            #include <alphamap_fragment>
            #include <alphatest_fragment>
            #include <specularmap_fragment>
            #include <emissivemap_fragment>
        
            // accumulation
            reflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );
        
            #ifdef DOUBLE_SIDED
        
                reflectedLight.indirectDiffuse += ( gl_FrontFacing ) ? vIndirectFront : vIndirectBack;
        
            #else
        
                reflectedLight.indirectDiffuse += vIndirectFront;
        
            #endif
        
            #include <lightmap_fragment>
        
            reflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );
        
            #ifdef DOUBLE_SIDED
        
                reflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;
        
            #else
        
                reflectedLight.directDiffuse = vLightFront;
        
            #endif
        
            reflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();
        
            // modulation
            #include <aomap_fragment>
        
            vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;
        
            #include <envmap_fragment>
        
            gl_FragColor = vec4( outgoingLight, diffuseColor.a );
        
            #include <tonemapping_fragment>
            #include <encodings_fragment>
            #include <fog_fragment>
            #include <premultiplied_alpha_fragment>
            #include <dithering_fragment>
        }
        `;
    };
    console.log(material, material.uniforms)
    return material;
}
```

---

<div class="post-metadata">

**Author:** ![Mugen87](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/mugen87/32/5645_2.png) [@Mugen87](https://discourse.threejs.org/u/Mugen87)\
**Post date:** [February 3, 2020, 2:19pm UTC](https://discourse.threejs.org/t/extending-uniforms-for-customized-instanced-lambert-material/12466/2 "2020-02-03T14:19:47Z")

</div>

> [@lxiangyun93](#):
>
> var material = new THREE.MeshLambertMaterial( { uniforms: uniforms, vertexColors: THREE.VertexColors, } );

It’s not allowed to pass `uniforms` as a parameter to `MeshLambertMaterial`. This only works for `ShaderMaterial` and `RawShaderMaterial`. When extending a material with `onBeforeCompile()`, there is no need to use `UniformsUtils`. Do it like in this example that shows how to extend `MeshNormalMaterial`:

[https://threejs.org/examples/webgl\_materials\_modified](https://threejs.org/examples/webgl_materials_modified)

---

<div class="post-metadata">

**Author:** ![pailhead](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/pailhead/32/85_2.png) [@pailhead](https://discourse.threejs.org/u/pailhead)\
**Post date:** [February 3, 2020, 7:23pm UTC](https://discourse.threejs.org/t/extending-uniforms-for-customized-instanced-lambert-material/12466/3 "2020-02-03T19:23:12Z")

</div>

Here is an in depth tutorial for using `onBeforeCompile`

> **[Extending three.js materials with GLSL](https://medium.com/@pailhead011/extending-three-js-materials-with-glsl-78ea7bbb9270)**
>
> What are three.js materials?

In short, the way `onBeforeCompile` works is somewhat limited. Three forces you to modify the shader source at runtime. As @Mugen87 pointed out, the built-in `Material` doesn’t know what to do with the uniforms.

The `MeshLambertMaterial` eventually creates a `ShaderMaterial` with uniforms, but this is obscured from you and you’re not allowed to access this instance.  
Despite not being able to see it, you do have access to `properties` in ` new ShaderMaterial(properties)`.

Essentially:

```auto
myLambertMaterial.onBeforeCompile = PROPERTIES => {....}

```

The object you get in this callback looks exactly the same as the object you would pass to the `ShaderMaterial`. Thus, if you do `shader.uniforms = UniformsUtils.merge( shader.uniforms, myUniforms)` it should work.

The syntax in `onBeforeCompile` is very limited. At most you can do things like

```auto
shader.foo = merge(foo,bar)

```
