# Is it ok to use ES6 template syntax for shaders?

**URL:** <https://discourse.threejs.org/t/is-it-ok-to-use-es6-template-syntax-for-shaders/22981>\
**Category:** Questions\
**Tags:** es6, shaders\
**Created:** [January 30, 2021, 12:56pm UTC](https://discourse.threejs.org/t/is-it-ok-to-use-es6-template-syntax-for-shaders/22981 "2021-01-30T12:56:25Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![Nicholas\_Bilyk](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/nicholas_bilyk/32/15528_2.png) [@Nicholas\_Bilyk](https://discourse.threejs.org/u/Nicholas_Bilyk)\
**Post date:** [January 30, 2021, 12:56pm UTC](https://discourse.threejs.org/t/is-it-ok-to-use-es6-template-syntax-for-shaders/22981/1 "2021-01-30T12:56:25Z")

</div>

I see that in the threejs shaders, there are include statements such as:

```javascript
`
#include <common>

uniform float scale;

`

```

I’m not trying to be too esoteric here, but I was wondering if anybody could think of a reason for me not to use es6 template strings?  
Just a personal preference (I like that I have intellisense for the possible includes), but thought I’d ask in case there were unforeseen problems with this.

e.g.

```javascript
`
${ShaderChunk.common}

uniform float scale;

`

```

---

<div class="post-metadata">

**Author:** ![mjurczyk](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/mjurczyk/32/10995_2.png) [@mjurczyk](https://discourse.threejs.org/u/mjurczyk)\
**Post date:** [January 30, 2021, 1:09pm UTC](https://discourse.threejs.org/t/is-it-ok-to-use-es6-template-syntax-for-shaders/22981/2 "2021-01-30T13:09:59Z")

</div>

Nope, shouldn’t be a problem with that, [considering that’s kinda what three does under the hood 😅](https://github.com/mrdoob/three.js/blob/464efc85ecfda5c03d786d15d8f8eff20d70f256/src/renderers/webgl/WebGLProgram.js#L202)

(In general, regarding templates, keep in mind that you still have to use uniforms for any dynamic values though. Changing variable value in JS won’t change it on the GPU unless you recompile the shader.)

---

<div class="post-metadata">

**Author:** ![Nicholas\_Bilyk](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/nicholas_bilyk/32/15528_2.png) [@Nicholas\_Bilyk](https://discourse.threejs.org/u/Nicholas_Bilyk)\
**Post date:** [January 30, 2021, 1:14pm UTC](https://discourse.threejs.org/t/is-it-ok-to-use-es6-template-syntax-for-shaders/22981/3 "2021-01-30T13:14:45Z")

</div>

Ok Cool. I wasn’t sure if there were special tools people were using for glsl editing that somehow understood those import directives.

🙂 Even if I thought that the shaders recompiled magically, template strings don’t actually change the string value if the variable changes after the string is constructed.

`let v = 3; let str = `${v}`; v = 4; str; // "3"`

---

<div class="post-metadata">

**Author:** ![drcmda](https://avatars.discourse-cdn.com/v4/letter/d/91b2a8/32.png) [@drcmda](https://discourse.threejs.org/u/drcmda)\
**Post date:** [January 30, 2021, 3:39pm UTC](https://discourse.threejs.org/t/is-it-ok-to-use-es6-template-syntax-for-shaders/22981/4 "2021-01-30T15:39:46Z")

</div>

i wish three did this, it would help tree shaking and create explicit contracts between shaders and their parts. i believe currently our bundles always carry the full shader lib, even if you effectively use 1% of it, everything is pulled in. (last time i checked that was the case at least). also makes understanding shaders/reading code really hard because the material classes are just empty shells that are magically filled in later.

---

<div class="post-metadata">

**Author:** ![mjurczyk](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/mjurczyk/32/10995_2.png) [@mjurczyk](https://discourse.threejs.org/u/mjurczyk)\
**Post date:** [January 30, 2021, 3:52pm UTC](https://discourse.threejs.org/t/is-it-ok-to-use-es6-template-syntax-for-shaders/22981/5 "2021-01-30T15:52:34Z")

</div>

> [@drcmda](#):
>
> i wish three did this

Hm, it doesn’t sound like the most complex or breaking change / PR. @Mugen87, do you think there’d be anything preventing it 🤔 (besides taking some time ofc) ?

---

<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:** [January 30, 2021, 4:28pm UTC](https://discourse.threejs.org/t/is-it-ok-to-use-es6-template-syntax-for-shaders/22981/6 "2021-01-30T16:28:00Z")

</div>

If a user writes a custom material by including built-in shader chunks and the material should run in older browsers like IE11, it’s not possible to use ES6 syntax. So the engine needs a backwards compatible way to resolve shader chunks.

---

<div class="post-metadata">

**Author:** ![Nicholas\_Bilyk](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/nicholas_bilyk/32/15528_2.png) [@Nicholas\_Bilyk](https://discourse.threejs.org/u/Nicholas_Bilyk)\
**Post date:** [January 30, 2021, 4:32pm UTC](https://discourse.threejs.org/t/is-it-ok-to-use-es6-template-syntax-for-shaders/22981/7 "2021-01-30T16:32:08Z")

</div>

> So the engine needs a backwards compatible way to resolve shader chunks.

Babel? 😁

---

<div class="post-metadata">

**Author:** ![Nicholas\_Bilyk](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/nicholas_bilyk/32/15528_2.png) [@Nicholas\_Bilyk](https://discourse.threejs.org/u/Nicholas_Bilyk)\
**Post date:** [January 30, 2021, 4:35pm UTC](https://discourse.threejs.org/t/is-it-ok-to-use-es6-template-syntax-for-shaders/22981/8 "2021-01-30T16:35:07Z")

</div>

I personally don’t care that much about the tree shaking problem – in most cases I’m going to use threejs from cdn as you’ll get a decent percent of users getting from cache. three weighs in at less ~160kb which is amazing for what it does.

---

<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:** [January 30, 2021, 4:43pm UTC](https://discourse.threejs.org/t/is-it-ok-to-use-es6-template-syntax-for-shaders/22981/9 "2021-01-30T16:43:09Z")

</div>

The current policy is that the build files `three.js`, `three.min.js` and the code from `examples/js` should run in older browsers so users don’t have to worry about transpiling.

---

<div class="post-metadata">

**Author:** ![drcmda](https://avatars.discourse-cdn.com/v4/letter/d/91b2a8/32.png) [@drcmda](https://discourse.threejs.org/u/drcmda)\
**Post date:** [January 31, 2021, 11:32am UTC](https://discourse.threejs.org/t/is-it-ok-to-use-es6-template-syntax-for-shaders/22981/10 "2021-01-31T11:32:15Z")

</div>

this wouldn’t be a concern: [three.js/rollup.config.js at 464efc85ecfda5c03d786d15d8f8eff20d70f256 · mrdoob/three.js · GitHub](https://github.com/mrdoob/three.js/blob/464efc85ecfda5c03d786d15d8f8eff20d70f256/utils/build/rollup.config.js#L297-L319)

all your dist files are bablified. you already control to which extend by giving it a target, currently

```
// the supported browsers of the three.js browser bundle
// https://browsersl.ist/?q=%3E0.3%25%2C+not+dead
targets: '>0.3%, not dead',

```

you can check your targets in babels repl: [Babel · The compiler for next generation JavaScript](https://babeljs.io/repl#?browsers=%3E0.3%25%2C%20not%20dead&build=&builtIns=false&spec=false&loose=false&code_lz=MYewdgzgLgBAFgUwDZJDAvDABgS1jiGAEgG8wEB3GAEQEMoEAKASgDoBzBKAFRwFsmzAL4wwICliA&debug=false&forceAllTransforms=false&shippedProposals=false&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=module&lineWrap=true&presets=env%2Creact%2Cstage-2&prettier=false&targets=&version=7.12.12&externalPlugins=)

it definitively transpiles string templates and they could be readily used in threes code.

---

<div class="post-metadata">

**Author:** ![looeee](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/looeee/32/59_2.png) [@looeee](https://discourse.threejs.org/u/looeee)\
**Post date:** [January 31, 2021, 11:39am UTC](https://discourse.threejs.org/t/is-it-ok-to-use-es6-template-syntax-for-shaders/22981/11 "2021-01-31T11:39:57Z")

</div>

> [@Nicholas\_Bilyk](#):
>
> I personally don’t care that much about the tree shaking problem – in most cases I’m going to use threejs from cdn as you’ll get a decent percent of users getting from cache.

This isn’t true anymore AFAIK since browsers no longer share the cache between sites.

---

<div class="post-metadata">

**Author:** ![drcmda](https://avatars.discourse-cdn.com/v4/letter/d/91b2a8/32.png) [@drcmda](https://discourse.threejs.org/u/drcmda)\
**Post date:** [January 31, 2021, 11:40am UTC](https://discourse.threejs.org/t/is-it-ok-to-use-es6-template-syntax-for-shaders/22981/12 "2021-01-31T11:40:18Z")

</div>

> [@drcmda](#):
>
> three weighs in at less ~160kb which is amazing for what it does.

still quite big compared to things like ogl (around 20kb). instead of cdns and script tags professional front end web dev revolves entirely around modules (node modules), they mostly expect things to work on slow internet connections which has gotten a much bigger issue with folks coming from countries where fast internet isn’t guaranteed.

---

<div class="post-metadata">

**Author:** ![looeee](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/looeee/32/59_2.png) [@looeee](https://discourse.threejs.org/u/looeee)\
**Post date:** [January 31, 2021, 12:17pm UTC](https://discourse.threejs.org/t/is-it-ok-to-use-es6-template-syntax-for-shaders/22981/13 "2021-01-31T12:17:13Z")

</div>

> it definitively transpiles string templates and they could be readily used in threes code.

This would be a nice change to make. GLSL in `src` was converted to template strings quite recently, so maybe we could move forward to convert `#include` statements as well.

To examine a simple example, [`src\renderers\shaders\ShaderLib\background_frag.glsl.js`](https://github.com/mrdoob/three.js/blob/464efc85ecfda5c03d786d15d8f8eff20d70f256/src/renderers/shaders/ShaderLib/background_frag.glsl.js) would look like this:

```javascript
import tonemapping_fragment from '../ShaderChunk/tonemapping_fragment.glsl.js';
import encodings_fragment from '../ShaderChunk/encodings_fragment.glsl.js';

export default /* glsl */`
uniform sampler2D t2D;

varying vec2 vUv;

void main() {

	vec4 texColor = texture2D( t2D, vUv );

	gl_FragColor = mapTexelToLinear( texColor );

	${tonemapping_fragment}
	${encodings_fragment}

}
`;

```

In `three.module.js` this would become:

```javascript
var background_frag = "uniform sampler2D t2D;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t${tonemapping_fragment}\n\t${encodings_fragment}\n}";

```

While in `three.js` it would become:

```javascript
var background_frag = "\nuniform sampler2D t2D;\n\nvarying vec2 vUv;\n\nvoid main() {\n\n\tvec4 texColor = texture2D( t2D, vUv );\n\n\tgl_FragColor = mapTexelToLinear( texColor );\n\n\t".concat(tonemapping_fragment, "\n\t").concat(encodings_fragment, "\n\n}\n");

```

Or with “loose” mode in babel:

```javascript
var background_frag = "\nuniform sampler2D t2D;\n\nvarying vec2 vUv;\n\nvoid main() {\n\n\tvec4 texColor = texture2D( t2D, vUv );\n\n\tgl_FragColor = mapTexelToLinear( texColor );\n\n\t" + tonemapping_fragment + "\n\t" + encodings_fragment + "\n\n}\n";

```

This seems like a fairly straightforward change. Besides tree-shaking improvements we could also remove the functions from `WebGLProgram.js` that @mjurczyk linked above. @Mugen87 you are more familiar with this part of the code, are there any potential issues here?

---

<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:** [January 31, 2021, 12:35pm UTC](https://discourse.threejs.org/t/is-it-ok-to-use-es6-template-syntax-for-shaders/22981/14 "2021-01-31T12:35:28Z")

</div>

> [@drcmda](#):
>
> all your dist files are bablified.

I was not referring to what `three.js` internally does. I’m talking about the dev who wants to use `three.js` for creating a custom shader material that should run with IE11.

This developer has to use the current `#include` syntax and `three.js` has to resolve it.

> [@looeee](#):
>
> we could also remove the functions from `WebGLProgram.js` that @mjurczyk linked above.

I’m afraid this is not possible for the above reason.

---

<div class="post-metadata">

**Author:** ![looeee](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/looeee/32/59_2.png) [@looeee](https://discourse.threejs.org/u/looeee)\
**Post date:** [January 31, 2021, 12:43pm UTC](https://discourse.threejs.org/t/is-it-ok-to-use-es6-template-syntax-for-shaders/22981/15 "2021-01-31T12:43:43Z")

</div>

> [@Mugen87](#):
>
> I’m afraid this is not possible for the above reason.

Yeah… can’t see an easy way around that. Oh well, back to waiting for `three.js` and `three.min.js` to be removed 😐

---

<div class="post-metadata">

**Author:** ![mjurczyk](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/mjurczyk/32/10995_2.png) [@mjurczyk](https://discourse.threejs.org/u/mjurczyk)\
**Post date:** [January 31, 2021, 12:44pm UTC](https://discourse.threejs.org/t/is-it-ok-to-use-es6-template-syntax-for-shaders/22981/16 "2021-01-31T12:44:35Z")

</div>

Now I’m wondering - wouldn’t this then break all the helpers / shaders / modifiers that depend on replacing `#include <chunk>`? [Fyrestar’s extendMaterial](https://discourse.threejs.org/t/function-to-extend-materials/7882), built-in [CurveModifier](https://github.com/mrdoob/three.js/blob/464efc85ecfda5c03d786d15d8f8eff20d70f256/examples/jsm/modifiers/CurveModifier.js#L135) etc.)

---

<div class="post-metadata">

**Author:** ![looeee](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/looeee/32/59_2.png) [@looeee](https://discourse.threejs.org/u/looeee)\
**Post date:** [January 31, 2021, 12:51pm UTC](https://discourse.threejs.org/t/is-it-ok-to-use-es6-template-syntax-for-shaders/22981/17 "2021-01-31T12:51:13Z")

</div>

> [@mjurczyk](#):
>
> wouldn’t this then break all the helpers / shaders / modifiers that depend on replacing `#include <chunk>` ?

Yes, but in the long run, there might be better ways of doing that than using `.replace`. Seems like a very fragile and unwieldy approach. Would it be possible to have a way to redefine includes like `beginnormal_vertex` instead?

On the other hand, my attitude towards anything like this in the current material system has just been “wait for node materials to replace it”. So I’m not gonna expend too much effort here.

---

<div class="post-metadata">

**Author:** ![drcmda](https://avatars.discourse-cdn.com/v4/letter/d/91b2a8/32.png) [@drcmda](https://discourse.threejs.org/u/drcmda)\
**Post date:** [January 31, 2021, 3:48pm UTC](https://discourse.threejs.org/t/is-it-ok-to-use-es6-template-syntax-for-shaders/22981/18 "2021-01-31T15:48:15Z")

</div>

> [@Mugen87](#):
>
> I was not referring to what `three.js` internally does. I’m talking about the dev who wants to use `three.js` for creating a custom shader material that should run with IE11.
> 
> This developer has to use the current `#include` syntax and `three.js` has to resolve it.

wouldn’t they construct a shader in the exact same way as three would, only without string templates? if the argument is that three doesnt want to break “# import”, ever, then that’s the way it is - but i dont understand the internet explorer thing. it’s not about templates, even if three concetenates strings - that would be good enough. the problem is the “import” thing, which forces it to bundle all shader code.

import { shadows, lights } from “three/shaderlib”

const myShader = shadows + lights + “gl\_frag = whatever”

or the same without import statements and IIEFs. please forgive my asking, it just could be something that would make three less fragile, reduce the bundle, help beginners understand shader code.

---

<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:** [January 31, 2021, 5:01pm UTC](https://discourse.threejs.org/t/is-it-ok-to-use-es6-template-syntax-for-shaders/22981/19 "2021-01-31T17:01:00Z")

</div>

> [@looeee](#):
>
> “wait for node materials to replace it

Node materials are bad for performance, memory and to maintain, the cost of this is way higher than using `.replace` and is rather suited for beginners or non-programmers, asides of the work with this increasing drastically compared to simple code. It’s kinda the `THREE.Geometry` of shader, which is why i not understand why this would be preferable. As a optional feature it makes sense but really not as the default approach.

Patching works perfectly fine, the real issue is rather the missing consistency across all the standard materials, this would be doable to add a more consistent structure using comments asides of the includes, but so far it is already quite consistent, considering the most needed entry points.

The way THREE currently basically uses “includes” is much better than pre-assembling just everything as it makes patching of features that should be separated not possible anymore (asides of blowing up the files with redundant codeblocks). The string of a built-in material is very small currently thanks to these includes what makes patching easy and fast.
