# Support custom outputs for ShaderMaterial

**URL:** <https://forum.babylonjs.com/t/support-custom-outputs-for-shadermaterial/42835>\
**Category:** Feature requests\
**Tags:** material, shader, render-target\
**Created:** [July 31, 2023, 6:29am UTC](https://forum.babylonjs.com/t/support-custom-outputs-for-shadermaterial/42835 "2023-07-31T06:29:49Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![OrigamiPete](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/origamipete/32/33982_2.png) [@OrigamiPete](https://forum.babylonjs.com/u/OrigamiPete)\
**Post date:** [July 31, 2023, 6:29am UTC](https://forum.babylonjs.com/t/support-custom-outputs-for-shadermaterial/42835/1 "2023-07-31T06:29:49Z")

</div>

Hi there,

I’m trying to implement a shader that outputs an `ivec4` to a `RenderTargetTexture` with a format of `RGBA_INTEGER` and type of `INT` but at the moment I’m limited by the shader preprocessor which automatically adds an `out vec4 glFragColor` output.

If there’s not currently a way around this, I’m happy to look into making an issue and pull request for this feature.

Thanks!

---

<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:** [July 31, 2023, 9:52am UTC](https://forum.babylonjs.com/t/support-custom-outputs-for-shadermaterial/42835/2 "2023-07-31T09:52:57Z")

</div>

Welcome aboard!

You can override the default behavior of injecting `glFragColor`. See how it is done in this PG:

> **[Babylon.js Playground](https://playground.babylonjs.com/#XSNYAU%2322)**
>
> Babylon.js playground is a live editor for Babylon.js WebGL 3D scenes

---

<div class="post-metadata">

**Author:** ![OrigamiPete](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/origamipete/32/33982_2.png) [@OrigamiPete](https://forum.babylonjs.com/u/OrigamiPete)\
**Post date:** [July 31, 2023, 10:43pm UTC](https://forum.babylonjs.com/t/support-custom-outputs-for-shadermaterial/42835/3 "2023-07-31T22:43:41Z")

</div>

Thanks for this suggestion. I did notice that using `#extension GL_EXT_draw_buffers : require` would suppress the preprocessor from adding the default `glFragColor` target though I’m not super keen on that API as `GL_EXT_draw_buffers` is designed for WebGL1 and doesn’t necessarily express what I’m trying to do when using a single framebuffer.  
I wonder if there would be some value in adding a field to `IShaderMaterialOptions` which would suppress the default output, or perhaps doing something like:

```c
#define CUSTOM_OUTPUT
layout (location = 0) out ivec4 outTarget;

```

This, however, only solves half of the problem though, because at the moment Babylon doesn’t support clearing render targets with an `INT` or `UNSIGNED_INT` type as it requires calling `clearBufferiv` and `clearBufferuiv` respectively.  
I imagine this would only be a small change to `ThinEngine.clear()` along the lines of:

```js
(...)
 if (this._currentRenderTarget) {
                const textureFormat = this._currentRenderTarget.texture?.format;
                if (textureFormat === Constants.TEXTUREFORMAT_R_INTEGER ||
                    textureFormat === Constants.TEXTUREFORMAT_RG_INTEGER ||
                    textureFormat === Constants.TEXTUREFORMAT_RGB_INTEGER || 
                    textureFormat === Constants.TEXTUREFORMAT_RGBA_INTEGER) {

                        const textureType = this._currentRenderTarget.texture?.type;
                        if (textureType === Constants.TEXTURETYPE_UNSIGNED_INTEGER ||
                            textureType === Constants.TEXTURETYPE_UNSIGNED_SHORT) {
                                this._gl.clearBufferuiv(this._gl.COLOR, 0, new Uint32Array([color.r, color.g, color.b, color.a]));
                            } else {
                                this._gl.clearBufferiv(this._gl.COLOR, 0, new Int32Array([color.r, color.g, color.b, color.a]))
                            }

                } else {
                    mode |= this._gl.COLOR_BUFFER_BIT;
                }
            } else {
                mode |= this._gl.COLOR_BUFFER_BIT;
            }
(...)

```

I appreciate your thoughts!

---

<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:** [August 1, 2023, 1:10pm UTC](https://forum.babylonjs.com/t/support-custom-outputs-for-shadermaterial/42835/4 "2023-08-01T13:10:21Z")

</div>



---

<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:** [August 1, 2023, 6:03pm UTC](https://forum.babylonjs.com/t/support-custom-outputs-for-shadermaterial/42835/5 "2023-08-01T18:03:18Z")

</div>

Regarding the fragment output, I think we can detect automatically if there’s already a declaration:

> <https://github.com/BabylonJS/Babylon.js/pull/14108>
>
> With this PR, you no longer need to have \`#extension GL\_EXT\_draw\_buffers require…\` in your shader if you want to provide your own fragment output declaration.
> 
> Simply declare your output (something like \`layout(location = 0) out vec4 myOutput;\`) and it will take precedence over the default \`glFragColor\` output.
> 
> Create the PR in draft mode, to make sure @sebavan sees it when he gets back from vacation.

And I did another PR to handle clearing integer textures:

> <https://github.com/BabylonJS/Babylon.js/pull/14112>
>
> See https://forum.babylonjs.com/t/support-custom-outputs-for-shadermaterial/4283…5/3
> 
> It also fixes a couple of small bugs with WebGPU.
> 
> PG for WebGL: https://playground.babylonjs.com/#XSNYAU#47
> PG for WebGPU: https://playground.babylonjs.com/#XSNYAU#50
> 
> WebGPU has a stricter limitation for the total number of components for the target textures (it's limited to 32 bytes), so I had to make a different PG.

Let me know if it’s ok for you!

---

<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:** [August 1, 2023, 6:09pm UTC](https://forum.babylonjs.com/t/support-custom-outputs-for-shadermaterial/42835/6 "2023-08-01T18:09:46Z")

</div>



---

<div class="post-metadata">

**Author:** ![OrigamiPete](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/origamipete/32/33982_2.png) [@OrigamiPete](https://forum.babylonjs.com/u/OrigamiPete)\
**Post date:** [August 1, 2023, 11:51pm UTC](https://forum.babylonjs.com/t/support-custom-outputs-for-shadermaterial/42835/7 "2023-08-01T23:51:47Z")

</div>

That looks perfect! Thanks for your help.
