# Why might zero Z-coordinates make a custom shader take twice as long?

**URL:** <https://forum.babylonjs.com/t/why-might-zero-z-coordinates-make-a-custom-shader-take-twice-as-long/61350>\
**Category:** Questions\
**Tags:** shader\
**Created:** [November 8, 2025, 5:54pm UTC](https://forum.babylonjs.com/t/why-might-zero-z-coordinates-make-a-custom-shader-take-twice-as-long/61350 "2025-11-08T17:54:32Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![djn24](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/djn24/32/27803_2.png) [@djn24](https://forum.babylonjs.com/u/djn24)\
**Post date:** [November 8, 2025, 5:54pm UTC](https://forum.babylonjs.com/t/why-might-zero-z-coordinates-make-a-custom-shader-take-twice-as-long/61350/1 "2025-11-08T17:54:32Z")

</div>

I have a custom shader (using ShaderMaterial) which generates gl\_Position based on some arbitrary logic I’ve written. The shader takes “position” and “uv” attributes but they aren’t really positions or uvs, they’re just arguments to the custom function. In particular, the “z” coordinate of the position attribute has nothing to do with where vertices are actually going to end up - it’s just an argument.

I’ve spotted an odd behaviour. If the z-coordinates in the position attribute of the mesh input to the shader are all zeroes (or are large random floats) the gpuFrameTimeCounter (part of Babylon’s EngineInstrumentation) is about double - i.e. the GPU rendering time is twice as long. That suggests the something other than my vertex shader is reading those positions and doing something with them which gets expensive if the z-coordinates are all zeroes. Can anyone tell me what that might be?

I’ve verified that it’s not my shader by changing the shader so it doesn’t actually read the z-coordinate - the effect persists. I’ve already tried the following settings:

On the ShaderMaterial:

- needDepthPrePass = false
- disableDepthWrite = true
- separateCullingPass = false
- backFaceCulling = false
- depthFunction = Engine.ALWAYS
- useClipPlane = false

On the mesh:

- alwaysSelectAsActiveMesh = true
- mustDepthSortFacets = false

The ShaderMaterial has alpha blending turned on, and alpha testing turned off, in case that’s relevant.

This will be quite tricky to reproduce in a playground. I can do that if needed though - but I thought I would ask in case somebody more familiar with how Babylon works will just know the answer!

I could of course work around this by moving my parameters to other attributes, e.g. uv2, uv3 etc., however whatever the process is that’s reading position data, it’s definitely not doing anything correct, so it seems better to find out what it is and switch it off if that’s possible.

I’m using Babylon.js v8.18.0 with WebGL2, in Google Chrome on MacOS.

---

<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:** [November 9, 2025, 1:37pm UTC](https://forum.babylonjs.com/t/why-might-zero-z-coordinates-make-a-custom-shader-take-twice-as-long/61350/2 "2025-11-09T13:37:27Z")

</div>

Be careful with `gpuFrameTimeCounter`, as it is not very accurate due to security issues (fingerprinting). If your GPU measurements are low (1 ms or less), it is possible that the difference is solely due to the browser not providing accurate values.

Other than that, I don’t see any reason why the measurements would be different, unless `gl_Position` depends on the `position` values, which means that the triangles will not be the same size and their rasterization will not take the same amount of time (but you said that the z-coordinates are not used in your shader).

You can try using [Spector](https://spector.babylonjs.com/) and see if the snapshots are different when the z coordinates are equal to 0 and when they take other values.

If you can set up a reproduction in the Playground, we will be able to investigate the problem better.

---

<div class="post-metadata">

**Author:** ![djn24](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/djn24/32/27803_2.png) [@djn24](https://forum.babylonjs.com/u/djn24)\
**Post date:** [November 9, 2025, 2:03pm UTC](https://forum.babylonjs.com/t/why-might-zero-z-coordinates-make-a-custom-shader-take-twice-as-long/61350/3 "2025-11-09T14:03:27Z")

</div>

Thanks for the suggestions. The numbers are reasonably high - about 4-5ms when it’s fast, 10ms when it’s slow, so I don’t think it can be just inaccuracy.

I had a look in Spector too and couldn’t see anything obvious. I’ll see if I can reproduce it in a playground.

---

<div class="post-metadata">

**Author:** ![HiGreg](https://avatars.discourse-cdn.com/v4/letter/h/c5a1d2/32.png) [@HiGreg](https://forum.babylonjs.com/u/HiGreg)\
**Post date:** [November 9, 2025, 6:43pm UTC](https://forum.babylonjs.com/t/why-might-zero-z-coordinates-make-a-custom-shader-take-twice-as-long/61350/4 "2025-11-09T18:43:20Z")

</div>

You and @Evgeni_Popov are much more knowledgable than I, but my first thought is “what’s happening in the fragment shader?” Nominally, 0 and large z values are clipped. Do your macro definitions prevent fragment shader from running? If clipping is turned off, does that mean all triangles/elements are sent to fragment shader?

---

<div class="post-metadata">

**Author:** ![djn24](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/djn24/32/27803_2.png) [@djn24](https://forum.babylonjs.com/u/djn24)\
**Post date:** [November 10, 2025, 7:51am UTC](https://forum.babylonjs.com/t/why-might-zero-z-coordinates-make-a-custom-shader-take-twice-as-long/61350/5 "2025-11-10T07:51:10Z")

</div>

Thanks for the suggestion. As I understand it, what happens in the rasteriser and the fragment shader should only be affected by the gl\_Position output by my vertex shader - but those gl\_Positions aren’t changed by the z-coordinates input to the shader.

I got it though! It was the glow layer (apologies, should have mentioned I was using that, only just realised it’s relevant). The problem was visible in Spector, I just needed to know where the look. There was a call to draw with a number of vertices suspiciously equal to my problem mesh with a shader specific to the glow layer, not my shader. A call to glowLayer.addExcludedMesh has solved the problem.
