# \[SOLVED\] How do we use map uniform with custom ShaderMaterial?

**URL:** <https://discourse.threejs.org/t/solved-how-do-we-use-map-uniform-with-custom-shadermaterial/1919>\
**Category:** Questions\
**Tags:** shader-material, custom-material, textures, materials\
**Created:** [February 22, 2018, 10:03pm UTC](https://discourse.threejs.org/t/solved-how-do-we-use-map-uniform-with-custom-shadermaterial/1919 "2018-02-22T22:03:59Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![trusktr](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/trusktr/32/13726_2.png) [@trusktr](https://discourse.threejs.org/u/trusktr)\
**Post date:** [February 22, 2018, 10:03pm UTC](https://discourse.threejs.org/t/solved-how-do-we-use-map-uniform-with-custom-shadermaterial/1919/1 "2018-02-22T22:03:59Z")

</div>

I’d like to pass a `map` options that holds a texture to my custom ShaderMaterial but I get an error, like this:

```auto
const material = new ShaderMaterial({
  // ... literally copied MeshLambertMaterial shader here, verbatim ...

  map: texture, // and I want to use a texture
})

// ...

renderer.render(scene, camera)

```

But when I try to do this, i get an error in console like

```auto
gl.getShaderInfoLog() fragment ERROR: 0:884: 'map' : undeclared identifier

```

When I check the shader output in the console, I see that `USE_MAP` is not defined.

I also tried this:

```auto
const material = new ShaderMaterial({
  // ... literally copied MeshLambertMaterial shader here, verbatim ...

  map: texture, // and I want to use a texture
})

// RIGHT HERE
material.uniforms.map.value = texture

// ...

renderer.render(scene, camera)

```

so set the uniform, which I thought would cause WebGLProgram to see the map and therefore to `#define USE_MAP`, but that doesn’t seem to happen.

I basically made an exact replica of `MeshLambertMaterial` by concatenating `ShaderChunk`s, etc, so the result shader code is identical to MeshLambertMaterial’s shader code).

How do we apply a texture to a this shader that is built using all the default `pars` as MeshLambertMaterial, so that USE\_MAP will be defined and the `map` variable will exist?

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/trusktr/32/13726_2.png) [@trusktr](https://discourse.threejs.org/u/trusktr)\
**Post date:** [February 22, 2018, 10:07pm UTC](https://discourse.threejs.org/t/solved-how-do-we-use-map-uniform-with-custom-shadermaterial/1919/2 "2018-02-22T22:07:14Z")

</div>

Here seems to be someone with possibly the exact same problem, but no solution yet: [https://stackoverflow.com/questions/34542508/custom-shadermaterial-map-issue](https://stackoverflow.com/questions/34542508/custom-shadermaterial-map-issue)

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/trusktr/32/13726_2.png) [@trusktr](https://discourse.threejs.org/u/trusktr)\
**Post date:** [February 22, 2018, 10:33pm UTC](https://discourse.threejs.org/t/solved-how-do-we-use-map-uniform-with-custom-shadermaterial/1919/3 "2018-02-22T22:33:59Z")

</div>

Ah, seems all I had to add was:

```auto
material.map = texture

```

and it works! So,

```auto
const material = new ShaderMaterial({
  // ... literally copied MeshLambertMaterial shader here, verbatim ...

  map: texture, // and I want to use a texture
})

material.uniforms.map.value = texture
material.map = texture

// ...

renderer.render(scene, camera)

```

[SOLVED]

---

<div class="post-metadata">

**Author:** ![titansoftime](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/titansoftime/32/1044_2.png) [@titansoftime](https://discourse.threejs.org/u/titansoftime)\
**Post date:** [May 3, 2018, 1:47am UTC](https://discourse.threejs.org/t/solved-how-do-we-use-map-uniform-with-custom-shadermaterial/1919/4 "2018-05-03T01:47:22Z")

</div>

This worked. Thanks. Although the console yells at me =]

`THREE.ShaderMaterial: 'map' is not a property of this material.`

---

<div class="post-metadata">

**Author:** ![Atul\_Mourya](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/atul_mourya/32/1155_2.png) [@Atul\_Mourya](https://discourse.threejs.org/u/Atul_Mourya)\
**Post date:** [June 1, 2018, 10:45am UTC](https://discourse.threejs.org/t/solved-how-do-we-use-map-uniform-with-custom-shadermaterial/1919/5 "2018-06-01T10:45:35Z")

</div>

Ahh!!! It worked for me as well. Cheers!!

> [@\[Solved\] Recreating build-in materials using ShaderMaterial](https://discourse.threejs.org/t/recreating-build-in-materials-using-shadermaterial/2965):
>
> Hi Everyone. I have been trying to recreate an existing MeshPhysicalMaterial using ShaderMaterial. The base code is extracted from the ShaderChunk wherever required. Not sure what’s wrong in my implementation. I can only see black colored object. Here’s the [link](https://jsfiddle.net/atulmourya/zyrke6hr/10/) of my implementation. Any help will be deeply appreciated.

---

<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:** [June 1, 2018, 5:55pm UTC](https://discourse.threejs.org/t/solved-how-do-we-use-map-uniform-with-custom-shadermaterial/1919/6 "2018-06-01T17:55:32Z")

</div>

I’m super confused as to how this works.

```javascript
const material = new ShaderMaterial({
  map: texture, //this should cause absolutely nothing to happen 
})

```

This should cause nothing:

> <https://github.com/mrdoob/three.js/blob/dev/src/materials/Material.js#L106>

```javascript
material.uniforms.map.value = texture //THIS is how you set a value on a uniform in a ShaderMaterial

```

This just slaps it onto the material. It is possible that `WebGLRenderer` gets confused about this and does your injection

```javascript
material.map = texture

```

> How do we apply a texture to a this shader that is built using all the default pars as MeshLambertMaterial, so that USE\_MAP will be defined and the map variable will exist?

**If you need a `USE_MAP` define in your `ShaderMaterial` a better way would be to provide that define.**

```javascript
new ShaderMaterial({defines: { USE_MAP: '' } })

```

---

<div class="post-metadata">

**Author:** ![titansoftime](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/titansoftime/32/1044_2.png) [@titansoftime](https://discourse.threejs.org/u/titansoftime)\
**Post date:** [June 1, 2018, 8:02pm UTC](https://discourse.threejs.org/t/solved-how-do-we-use-map-uniform-with-custom-shadermaterial/1919/7 "2018-06-01T20:02:13Z")

</div>

Turns out the only things that are necessary are setting `uniforms.map` and `defines.USE_MAP`.

`material.map` does nothing except cause a console warning.

This should be better documented imo. One has to search forums / SO to find the answer to what I would imagine to be a somewhat common use case.

---

<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:** [June 1, 2018, 8:21pm UTC](https://discourse.threejs.org/t/solved-how-do-we-use-map-uniform-with-custom-shadermaterial/1919/8 "2018-06-01T20:21:58Z")

</div>

Well the only way to do that is to voice some opinions on github. You’ve been part of some discussions but excused yourself eventually. This way there wont be much improvement 😢

---

<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:** [June 1, 2018, 8:24pm UTC](https://discourse.threejs.org/t/solved-how-do-we-use-map-uniform-with-custom-shadermaterial/1919/9 "2018-06-01T20:24:28Z")

</div>

> [@titansoftime](#):
>
> Turns out the only things that are necessary are setting `uniforms.map` and `defines.USE_MAP` .

Also, technically you dont have to use `material.defines` either. Preprocessor directives are just part of GLSL core  
[https://www.khronos.org/opengl/wiki/Core\_Language\_(GLSL)#Preprocessor\_directives](https://www.khronos.org/opengl/wiki/Core_Language_(GLSL)#Preprocessor_directives)

It’s enough to just add that GLSL. If you have a `fragmentShader` string you can do

```javascript
fragmentShader = '#define USE_MAP\n' + fragmentShader 

```

---

<div class="post-metadata">

**Author:** ![titansoftime](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/titansoftime/32/1044_2.png) [@titansoftime](https://discourse.threejs.org/u/titansoftime)\
**Post date:** [June 1, 2018, 9:19pm UTC](https://discourse.threejs.org/t/solved-how-do-we-use-map-uniform-with-custom-shadermaterial/1919/10 "2018-06-01T21:19:03Z")

</div>

I just read a 3 year backlog of `NodeMaterial` and related conversations. I see now why there was pushback on altering materials, seems like the future is not settled, and changes are therefor discouraged it seems.

> [@pailhead](#):
>
> Well the only way to do that is to voice some opinions on github. You’ve been part of some discussions but excused yourself eventually. This way there wont be much improvement 😢

My voice in that was to add instancing chunks (I still plan on mocking up a non-merge PR for that, but honestly just haven’t felt the drive, been busy). This is merely a documentation alteration in which I feel more confident about getting merged =]

---

<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:** [June 1, 2018, 9:27pm UTC](https://discourse.threejs.org/t/solved-how-do-we-use-map-uniform-with-custom-shadermaterial/1919/11 "2018-06-01T21:27:19Z")

</div>

What do you think needs to be added here?

[https://threejs.org/docs/index.html#api/materials/Material.defines](https://threejs.org/docs/index.html#api/materials/Material.defines)

Or here?  
[https://www.khronos.org/opengl/wiki/Core\_Language\_(GLSL)#Preprocessor\_directives](https://www.khronos.org/opengl/wiki/Core_Language_(GLSL)#Preprocessor_directives)

---

<div class="post-metadata">

**Author:** ![titansoftime](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/titansoftime/32/1044_2.png) [@titansoftime](https://discourse.threejs.org/u/titansoftime)\
**Post date:** [June 1, 2018, 9:53pm UTC](https://discourse.threejs.org/t/solved-how-do-we-use-map-uniform-with-custom-shadermaterial/1919/12 "2018-06-01T21:53:07Z")

</div>

I was honestly thinking more here:

[https://threejs.org/docs/#api/materials/ShaderMaterial](https://threejs.org/docs/#api/materials/ShaderMaterial)

It’s the first placed I looked, before just googling the problem.

People are probably not going to know to look in defines, as they may not know that’s part of the issue. Plus you also have to set a uniform.

---

<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:** [June 1, 2018, 10:12pm UTC](https://discourse.threejs.org/t/solved-how-do-we-use-map-uniform-with-custom-shadermaterial/1919/13 "2018-06-01T22:12:05Z")

</div>

You don’t actually have to set a uniform, it will just be the same as having value: null.

My point is that, this is a ShaderMaterial, you use it almost exclusively to write glsl, with some additional three specific syntax (include).

OP correctly identified that some branch of that GLSL program does not exist, why, because it’s behind a preprocessor directive.

`defines` is just a convenient threejs thing.

---

<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:** [June 1, 2018, 10:14pm UTC](https://discourse.threejs.org/t/solved-how-do-we-use-map-uniform-with-custom-shadermaterial/1919/14 "2018-06-01T22:14:03Z")

</div>

> [@titansoftime](#):
>
> People are probably not going to know to look in defines,

My advice for people would be to read the GLSL spec before working with GLSL. Not everything has to be understood straight away, but knowing what you can encounter in code helps…

> I was honestly thinking more here:
> 
> [three.js docs](https://threejs.org/docs/#api/materials/ShaderMaterial)

It’s actually not that super obvious but there is a mention that this is a sub class of `Material`

> parameters - (optional) an object with one or more properties defining the material’s appearance. Any property of the material (including any property inherited from Material) can be passed in here.

This also indicates that relationship i think:  
 ![28%20PM](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/2X/8/8cd98f11326de6422edcecb7f130dd6503cd7dfa.png)

The point being it’s not enough to read the docs of `ShaderMaterial` if it inherits from `Material` in order to see the entire picture you need to read both.

Odd, but `Material` docs don’t actually mention that it inherits from `EventDispatcher`

> <https://github.com/mrdoob/three.js/blob/master/src/materials/Material.js#L72>

---

<div class="post-metadata">

**Author:** ![titansoftime](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/titansoftime/32/1044_2.png) [@titansoftime](https://discourse.threejs.org/u/titansoftime)\
**Post date:** [June 2, 2018, 9:25pm UTC](https://discourse.threejs.org/t/solved-how-do-we-use-map-uniform-with-custom-shadermaterial/1919/15 "2018-06-02T21:25:36Z")

</div>

I’m sure you are 100% correct and from the perspective of a seasoned three.js dev.

But for someone like myself who does VERY little actual glsl and just want to extend a shader or something, it would be nice to have an easy look up doc.

If something like “Trying to use a texture map? Do this:…” was on the Shadermaterial docs, I’m sure it would reduce the amount of SO questions being asked.

But, yea to get a full understanding of all the underlying mechanisms, they would need to read up on Material and all that.

> You don’t actually have to set a uniform, it will just be the same as having value: null.

How do you push texture2d data to the shader without using a uniform?

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/trusktr/32/13726_2.png) [@trusktr](https://discourse.threejs.org/u/trusktr)\
**Post date:** [June 2, 2018, 10:35pm UTC](https://discourse.threejs.org/t/solved-how-do-we-use-map-uniform-with-custom-shadermaterial/1919/16 "2018-06-02T22:35:41Z")

</div>

Hi @pailhead, before posting this thread, I was completely aware of `#define` functionality of shaders, which are very similar to C/C++. This isn’t the issue.

The issue is this:

When I use a shader (not a custom one) defining `map` automatically makes the relevant shader code path available. Following this pattern, I thought that if I copied an existing material’s code, that perhaps the same pattern would apply. It’s the expectation that a certain threejs-specific functionality would have still applied in a custom material, but it didn’t.

It would be great if the existing patterns of existing materials could be re-used (inherited from Material or something) so that making custom materials affords certain behavioral patterns like `map` code being automatically enabled when a map is supplied.

That is what the root of the issue is, and not that I didn’t know how to make a define.

Hope that clarifies where we’re coming from. 😊

---

<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:** [June 3, 2018, 12:54am UTC](https://discourse.threejs.org/t/solved-how-do-we-use-map-uniform-with-custom-shadermaterial/1919/17 "2018-06-03T00:54:16Z")

</div>

> [@titansoftime](#):
>
> But for someone like myself who does VERY little actual glsl and just want to extend a shader or something, it would be nice to have an easy look up doc.
> 
> If something like “Trying to use a texture map? Do this:…” was on the Shadermaterial docs, I’m sure it would reduce the amount of SO questions being asked.

This either wouldn’t apply because “Trying to use a texture map” with `ShaderMaterial` is just “please consult a GLSL tutorial / doc” or it would just be too many of these edge cases that would overwhelm the docs.  
A wiki with a bunch of tutorials and extra docs could work, but three’s philosophy seems to be to stick it into poorly documented code examples ☹

So until someone from the community tackles a bunch of these examples, this wont really be documented. Although i dont see whats wrong with specific SO questions, incrementally, this would add up and someone could compile them into one thing or a post here.

---

<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:** [June 3, 2018, 12:57am UTC](https://discourse.threejs.org/t/solved-how-do-we-use-map-uniform-with-custom-shadermaterial/1919/18 "2018-06-03T00:57:48Z")

</div>

> [@trusktr](#):
>
> It would be great if the existing patterns of existing materials could be re-used (inherited from Material or something) so that making custom materials affords certain behavioral patterns like `map` code being automatically enabled when a map is supplied.

This is a tricky thing and unlikely to happen due to a push for `NodeMaterial`. I think it’s actually bad to rely on internals of `WebGLRender` to set something like this, if it does indeed happen. You seem to have tricked it into doing so when you provided the map param. If a define is controlling that branch, it should be somehow documented and obvious. I still think that in this case it would have been more beneficial for you to have been aware of `Material.defines` but i think it wasn’t as obvious as it should be.

---

<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:** [June 3, 2018, 1:00am UTC](https://discourse.threejs.org/t/solved-how-do-we-use-map-uniform-with-custom-shadermaterial/1919/19 "2018-06-03T01:00:23Z")

</div>

> [@trusktr](#):
>
> When I use a shader (not a custom one) defining `map` automatically makes the relevant shader code path available.

This part is tricky, i think the issue is that this happens, hence you make assumptions on other things. `ShaderMaterial` is pretty raw, it just injects some things but you still have to work with GLSL (define is part of that) and `material.uniforms` rather than properties. I’d be really confused if i saw code like that. I’d expect map to be `uniforms: { map: texture }`.

---

<div class="post-metadata">

**Author:** ![titansoftime](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/titansoftime/32/1044_2.png) [@titansoftime](https://discourse.threejs.org/u/titansoftime)\
**Post date:** [June 3, 2018, 4:10am UTC](https://discourse.threejs.org/t/solved-how-do-we-use-map-uniform-with-custom-shadermaterial/1919/20 "2018-06-03T04:10:45Z")

</div>

I think I see your point. setting uniforms.map and expecting it to work would be odd as generally with shadermaterial you are writing your own glsl anyway. Having uniforms.map really only applies when extending existing three.js shaders. Right?

[Next page](https://discourse.threejs.org/t/solved-how-do-we-use-map-uniform-with-custom-shadermaterial/1919.md?page=2)
