# How to access raw shader information?

**URL:** <https://forum.babylonjs.com/t/how-to-access-raw-shader-information/27240>\
**Category:** Questions\
**Created:** [January 31, 2022, 7:41am UTC](https://forum.babylonjs.com/t/how-to-access-raw-shader-information/27240 "2022-01-31T07:41:37Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![andyray](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/andyray/32/21767_2.png) [@andyray](https://forum.babylonjs.com/u/andyray)\
**Post date:** [January 31, 2022, 7:41am UTC](https://forum.babylonjs.com/t/how-to-access-raw-shader-information/27240/1 "2022-01-31T07:41:37Z")

</div>

Hi, I’m toying around with Babylon. I’m interested in writing shaders where I take the raw GLSL created by babylon, changing it automatically by a compiler, and putting it back into a babylonjs shader. I want to do this to plug a custom graph editor built on top of a custom compiler, into a raw babylonjs shader.

I’ve been poking around the context at runtime. My first question is: What’s the best way to get the raw GLSL from a babylon shader? I see material.\_effect.\_fragmentSourceCode - is that a reliable place? Does the scene need to render first for this to be populated?

Second: if I take the above fragment and vertex source from a babylon PBR shader, set that to `BABYLON.Effect.ShadersStore['customVertexShader'] =...` and `BABYLON.Effect.ShadersStore['customFragmentShader'] =...` and create a new shader like:

```auto
shaderMaterial = new BABYLON.ShaderMaterial(
        'shader',
        scene,
        {
          vertex: 'custom',
          fragment: 'custom',
        },
        {
          attributes: ['position', 'normal', 'uv'],
          uniforms: [
            'world',
            'worldView',
            'worldViewProjection',
            'view',
            'projection',
            'Scene',
          ],
        }
      );

```

I get nothing rendered, and from WebGL, the warning/error

```auto
[.WebGL-0x7f86a6808200]RENDER WARNING: there is no texture bound to the unit 0
babylon:1
WebGL: too many errors, no more errors will be reported to the console for this context.

```

Is this because I didn’t include enough uniforms and attributes in the shader definition?

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [January 31, 2022, 9:34am UTC](https://forum.babylonjs.com/t/how-to-access-raw-shader-information/27240/2 "2022-01-31T09:34:49Z")

</div>

Welcome aboard!

Using `ShaderMaterial` won’t work because you would need to bind all uniforms/samplers required by the shader as well as handling light binding yourself. See [#include directives in shader code output from Node Material Editor - #2 by Evgeni\_Popov](https://forum.babylonjs.com/t/include-directives-in-shader-code-output-from-node-material-editor/10730/2) for more context. This thread is about using the code from a node material, but the problem is the same.

What you can do instead is override the `material.customShaderNameResolve` function to modify the shader sent to the gpu. See for eg:

- [Recent Material Pipeline Changes - #13 by Evgeni\_Popov](https://forum.babylonjs.com/t/recent-material-pipeline-changes/6885/13)
- [Issue Setting Color of Thin Instance - #8 by Evgeni\_Popov](https://forum.babylonjs.com/t/issue-setting-color-of-thin-instance/14976/8)

---

<div class="post-metadata">

**Author:** ![andyray](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/andyray/32/21767_2.png) [@andyray](https://forum.babylonjs.com/u/andyray)\
**Post date:** [February 1, 2022, 2:22am UTC](https://forum.babylonjs.com/t/how-to-access-raw-shader-information/27240/4 "2022-02-01T02:22:13Z")

</div>

@Evgeni_Popov customShaderNameResolve doesn’t appear to be a method of PBR materials?

```auto
      shaderMaterial = new BABYLON.PBRSpecularGlossinessMaterial('pbr', scene);
      shaderMaterial._saveCustomShaderNameResolve =
        shaderMaterial.customShaderNameResolve.bind(shaderMaterial);

```

Results in

> TypeError: Cannot read properties of undefined (reading ‘bind’)

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [February 1, 2022, 9:56am UTC](https://forum.babylonjs.com/t/how-to-access-raw-shader-information/27240/5 "2022-02-01T09:56:28Z")

</div>

The property does exist but it can be `undefined` (if nobody has registered a custom shader name resolve callback yet), so you should handle this case in your code.

---

<div class="post-metadata">

**Author:** ![andyray](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/andyray/32/21767_2.png) [@andyray](https://forum.babylonjs.com/u/andyray)\
**Post date:** [February 9, 2022, 5:29am UTC](https://forum.babylonjs.com/t/how-to-access-raw-shader-information/27240/6 "2022-02-09T05:29:54Z")

</div>

I have some code like this:

```auto
const shaderMaterial = new BABYLON.PBRMaterial('pbr', scene);
shaderMaterial.customShaderNameResolve = (
  shaderName, uniforms, uniformBuffers, samplers, defines, attributes, options
) => {
  if (options) {
    options.processFinalCode = (type, code) => {
      if (type === 'vertex') {
        return myCustomVertex;
      }
      return myCustomFragment;
    };
  }
  return shaderName;
};
mesh.material = shaderMaterial;

```

The first time my scene renders, the entire above block executes, and `processFinalCode` is called, and the custom shader source code is executed.

Later, I update my custom source code, and re-run the entire block of code above. As in, I create a new `PBRMaterial`, and reassign it to the mesh.

The second time this happens, `customShaderNameResolve` runs, but the `processFinalCode` callback is never called (verified by logging). Am I missing something to make `processFinalCode` run again?

If I re-create the babylon engine+scene entirely, then processFinalCode runs again.

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [February 9, 2022, 7:54am UTC](https://forum.babylonjs.com/t/how-to-access-raw-shader-information/27240/7 "2022-02-09T07:54:01Z")

</div>

`processFinalCode ` won’t be reexecuted if the effect is not recompiled and can be found in the cache. To force a recompilation, you can change the value of a define with a value not used yet (in the `defines` property passed to `customShaderNameResolve`).

---

<div class="post-metadata">

**Author:** ![andyray](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/andyray/32/21767_2.png) [@andyray](https://forum.babylonjs.com/u/andyray)\
**Post date:** [February 9, 2022, 9:45pm UTC](https://forum.babylonjs.com/t/how-to-access-raw-shader-information/27240/8 "2022-02-09T21:45:21Z")

</div>

`id()` generates a new unique number every time it’s called. This doesn’t appear to bust the cache in the sense I see the same behavior. Is this what you’re suggesting?

```auto
shaderMaterial.customShaderNameResolve = (
    shaderName,
    uniforms,
    uniformBuffers,
    samplers,
    defines,
    attributes,
    options
  ) => {
    if (Array.isArray(defines)) {
      defines.push('' + id());
    } else {
      defines['' + id()] = id();
    }

```

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [February 10, 2022, 12:36am UTC](https://forum.babylonjs.com/t/how-to-access-raw-shader-information/27240/9 "2022-02-10T00:36:04Z")

</div>

Yes, but you should give a name to the define. For eg:

```nohighlight
    if (Array.isArray(defines)) {
      defines.push('MYDUMMY' + id());
    } else {
      defines['MYDUMMY' + id()] = id();
    }

```

---

<div class="post-metadata">

**Author:** ![andyray](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/andyray/32/21767_2.png) [@andyray](https://forum.babylonjs.com/u/andyray)\
**Post date:** [February 10, 2022, 1:01am UTC](https://forum.babylonjs.com/t/how-to-access-raw-shader-information/27240/10 "2022-02-10T01:01:34Z")

</div>

That doesn’t appear to have the desired effect of cache busting. This line does appear to work:

```auto
defines.AMBIENTDIRECTUV = 0.0000001 * Math.random();

```

Is this because I’m using a PBRMaterial, so I can only mutate known defines?

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [February 10, 2022, 10:14am UTC](https://forum.babylonjs.com/t/how-to-access-raw-shader-information/27240/11 "2022-02-10T10:14:39Z")

</div>

Indeed, only defines known by `PBRMaterial` are taken into account…

So, another way would be to call `material.markAsDirty(BABYLON.Constants.MATERIAL_AllDirtyFlag)` when you want to regenerate the effect and have `processFinalCode` called.

---

<div class="post-metadata">

**Author:** ![carolhmj](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/carolhmj/32/25918_2.png) [@carolhmj](https://forum.babylonjs.com/u/carolhmj)\
**Post date:** [March 11, 2022, 11:48am UTC](https://forum.babylonjs.com/t/how-to-access-raw-shader-information/27240/12 "2022-03-11T11:48:18Z")

</div>

Hello @andyray just checking in, was your question answered?

---

<div class="post-metadata">

**Author:** ![andyray](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/andyray/32/21767_2.png) [@andyray](https://forum.babylonjs.com/u/andyray)\
**Post date:** [March 11, 2022, 8:17pm UTC](https://forum.babylonjs.com/t/how-to-access-raw-shader-information/27240/13 "2022-03-11T20:17:27Z")

</div>

Yes! I was able to use my experimental tool to take a full shader written for Three.js, update its AST to use Babylon uniforms instead, and then parse the Babylon PBRMaterial megashader and replace Babylon’s normal map uniform with the output of the previous shader!

> <https://twitter.com/andrewray/status/1490935873793556480?s=20&t=FMp92BD0zgUrVX4p901rvg>

---

<div class="post-metadata">

**Author:** ![andyray](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/andyray/32/21767_2.png) [@andyray](https://forum.babylonjs.com/u/andyray)\
**Post date:** [March 14, 2022, 12:20am UTC](https://forum.babylonjs.com/t/how-to-access-raw-shader-information/27240/14 "2022-03-14T00:20:13Z")

</div>

@Evgeni_Popov What is `customShaderNameResolve` supposed to return? See [shaderName in customShaderNameResolve ignores the shader's name? · Issue #12154 · BabylonJS/Babylon.js · GitHub](https://github.com/BabylonJS/Babylon.js/issues/12154)

If I return a different name than `shaderName` then my `processFinalCode` callback isn’t it. I don’t get why this callback is supposed to return anything if the name is hard coded and can’t be changed?

---

<div class="post-metadata">

**Author:** ![jeremy-coleman](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/jeremy-coleman/32/15493_2.png) [@jeremy-coleman](https://forum.babylonjs.com/u/jeremy-coleman)\
**Post date:** [March 14, 2022, 5:33am UTC](https://forum.babylonjs.com/t/how-to-access-raw-shader-information/27240/15 "2022-03-14T05:33:55Z")

</div>

It seems like you set customShaderNameResolve on the instance, with an additional config object named csnrOptions

.[Babylon.js/pbrBaseMaterial.ts at 0b3e860dd88bf14644680a02ef7bd9045b17ea42 · BabylonJS/Babylon.js · GitHub](https://github.com/BabylonJS/Babylon.js/blob/0b3e860dd88bf14644680a02ef7bd9045b17ea42/src/Materials/PBR/pbrBaseMaterial.ts#L1385)

So if customShaderNameResolve is present on the instance, it should override the hard coded name. Thats what it looks like to me at least, but idk.

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [March 14, 2022, 10:20am UTC](https://forum.babylonjs.com/t/how-to-access-raw-shader-information/27240/16 "2022-03-14T10:20:26Z")

</div>

`shaderName` is the name to lookup the shader code in the shader store. The PBR code is in `ShaderStore.ShadersStore["pbrVertexShader"]` and `ShaderStore.ShadersStore["pbrPixelShader"]` so the default name is “pbr” ( **VertexShader** and **PixelShader** are automatically added for the lookups).

If in your `customShaderNameResolve` callback you put your code in your own `ShadersStore` entries, you should return the name corresponding to these entries. That’s what the `CustomMaterial` / `PBRCustomMaterial` is doing:

> <https://github.com/BabylonJS/Babylon.js/blob/master/materialsLibrary/src/custom/customMaterial.ts#L132-L168>

---

<div class="post-metadata">

**Author:** ![andyray](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/andyray/32/21767_2.png) [@andyray](https://forum.babylonjs.com/u/andyray)\
**Post date:** [December 16, 2022, 6:38am UTC](https://forum.babylonjs.com/t/how-to-access-raw-shader-information/27240/17 "2022-12-16T06:38:37Z")

</div>

> [@Evgeni\_Popov](#):
>
> markAsDirty(BABYLON.Constants.MATERIAL\_AllDirtyFlag)

`material.markAsDirty(BABYLON.Constants.MATERIAL_AllDirtyFlag)` has no effect. Neither does `material.markDirty()`. Only the hack of modifying a defines like `defines.AMBIENTDIRECTUV = Math.random()` works. Are these dirty methods just buggy?

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [December 16, 2022, 10:26am UTC](https://forum.babylonjs.com/t/how-to-access-raw-shader-information/27240/18 "2022-12-16T10:26:44Z")

</div>

My bad, `markAsDirty` will only force the system to run the `engine.createEffect` method, but if the effect is found in the cache, it won’t be recreated.

Using a [material plugin](https://doc.babylonjs.com/features/featuresDeepDive/materials/using/materialPlugins) would be the cleanest way to handle custom code injection, as you can inject your own defines and they will be correctly taken into account when checking for effect recompilation. Is this an option for you?

A brute force approach would be to clean the cache of all effects: `engine.releaseEffects();`. This means that all effects will be recreated the first time they are needed…
