# GPU SphericalHarmonics Creation

**URL:** <https://forum.babylonjs.com/t/gpu-sphericalharmonics-creation/62341>\
**Category:** Demos and projects\
**Tags:** webgl, performance, gpu, cubetexture\
**Created:** [February 4, 2026, 6:59am UTC](https://forum.babylonjs.com/t/gpu-sphericalharmonics-creation/62341 "2026-02-04T06:59:18Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![kzhsw](https://avatars.discourse-cdn.com/v4/letter/k/848f3c/32.png) [@kzhsw](https://forum.babylonjs.com/u/kzhsw)\
**Post date:** [February 4, 2026, 6:59am UTC](https://forum.babylonjs.com/t/gpu-sphericalharmonics-creation/62341/1 "2026-02-04T06:59:18Z")

</div>

Precision: 4.xxe-6  
Engine: WebGL2 only  
Playground:  
[https://playground.babylonjs.com/#2FDQT5#3056](https://playground.babylonjs.com/#2FDQT5#3056)  
Performance:  
First run very slow, but faster after warmup.

 ![bench](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/d/7/d7dded43f6804544b40e614fa7d78bff877be280.png)  
Use this to benchmark:  
[https://playground.babylonjs.com/#2FDQT5#3058](https://playground.babylonjs.com/#2FDQT5#3058)

Reference a topic here:

> [@GPU Accelerated Creation of HDRCubeTexture](https://forum.babylonjs.com/t/gpu-accelerated-creation-of-hdrcubetexture/53300):
>
> Playground: [Babylon.js Playground](https://playground.babylonjs.com/#0CDDAT) Version: 7.24.0 Engine: WebGL2 Loading HDRCubeTexture is slow, it takes ~5s for a loading a 1k texture, and takes minutes loading 2k ones. I’ve made some profiling on chrome to see if there are ways to optimize it. Loading HDR to a 1k texture, ConvertCubeMapToSphericalPolynomial takes the most, ~54% of the cpu time, most of which is calculation, so it could, at least in theory, be possible to be gpu accelerated, via a post process shader in webgl2, or a comp…

---

<div class="post-metadata">

**Author:** ![Deltakosh](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/deltakosh/32/26635_2.png) [@Deltakosh](https://forum.babylonjs.com/u/Deltakosh)\
**Post date:** [February 4, 2026, 4:20pm UTC](https://forum.babylonjs.com/t/gpu-sphericalharmonics-creation/62341/2 "2026-02-04T16:20:13Z")

</div>

That is something that @sebavan will appreciate for sure

---

<div class="post-metadata">

**Author:** ![sebavan](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/sebavan/32/57_2.png) [@sebavan](https://forum.babylonjs.com/u/sebavan)\
**Post date:** [February 4, 2026, 4:21pm UTC](https://forum.babylonjs.com/t/gpu-sphericalharmonics-creation/62341/3 "2026-02-04T16:21:21Z")

</div>

This is great !!! did you compare the result with the cpu version ?

Would be amazing to have a PR for this 🙂

---

<div class="post-metadata">

**Author:** ![kzhsw](https://avatars.discourse-cdn.com/v4/letter/k/848f3c/32.png) [@kzhsw](https://forum.babylonjs.com/u/kzhsw)\
**Post date:** [February 5, 2026, 12:59am UTC](https://forum.babylonjs.com/t/gpu-sphericalharmonics-creation/62341/4 "2026-02-05T00:59:36Z")

</div>

> [@sebavan](#):
>
> did you compare the result with the cpu version ?

Yes there is, see devtools console of [https://playground.babylonjs.com/#2FDQT5#3056](https://playground.babylonjs.com/#2FDQT5#3056), there is `max diff` and raw gpu result vs cpu result, and first run time.

 ![devtools](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/7/5/7515c6c3b5916108dc4551c3cb4059fc8f27d27f.png)  
The first run on gpu is slower than cpu mainly due to `readPixels` (texture data readback and forced gpu sync).  
To workaround it there are 2 options:

1. use pbo buffered, async readback, delay it for a few frames until it’s done (Edit: the async ver [https://playground.babylonjs.com/#2FDQT5#3059](https://playground.babylonjs.com/#2FDQT5#3059) does not seems to help much)
2. do not readback until serialization (to keep the serialization structure stable), and pass it as a texture to downstream shaders

Also instead of all these complex shaders and draws, webgpu with compute shader, storage buffer, and atomic add can hopefully do the whole thing in a single pass, and the readback is async, might be a more future-proof option while strictly limited to secure context.

---

<div class="post-metadata">

**Author:** ![sebavan](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/sebavan/32/57_2.png) [@sebavan](https://forum.babylonjs.com/u/sebavan)\
**Post date:** [February 5, 2026, 1:22am UTC](https://forum.babylonjs.com/t/gpu-sphericalharmonics-creation/62341/5 "2026-02-05T01:22:10Z")

</div>

maybe we could use it as a texture ?

Last I tried, I had the same readback issues.

---

<div class="post-metadata">

**Author:** ![kzhsw](https://avatars.discourse-cdn.com/v4/letter/k/848f3c/32.png) [@kzhsw](https://forum.babylonjs.com/u/kzhsw)\
**Post date:** [February 5, 2026, 1:29am UTC](https://forum.babylonjs.com/t/gpu-sphericalharmonics-creation/62341/6 "2026-02-05T01:29:38Z")

</div>

But that could be breaking for downstream shader devs, also it could slow down the next readPixels

---

<div class="post-metadata">

**Author:** ![kzhsw](https://avatars.discourse-cdn.com/v4/letter/k/848f3c/32.png) [@kzhsw](https://forum.babylonjs.com/u/kzhsw)\
**Post date:** [February 5, 2026, 2:23am UTC](https://forum.babylonjs.com/t/gpu-sphericalharmonics-creation/62341/7 "2026-02-05T02:23:33Z")

</div>

At least this could be used for batched/massive high-res hdr to env conversion

---

<div class="post-metadata">

**Author:** ![kzhsw](https://avatars.discourse-cdn.com/v4/letter/k/848f3c/32.png) [@kzhsw](https://forum.babylonjs.com/u/kzhsw)\
**Post date:** [February 5, 2026, 8:01am UTC](https://forum.babylonjs.com/t/gpu-sphericalharmonics-creation/62341/8 "2026-02-05T08:01:29Z")

</div>

Oh, wait, something strange happened, if the cpu part moved ahead of the gpu part, it became slower, and the gpu part became faster.  
[https://playground.babylonjs.com/#2FDQT5#3060](https://playground.babylonjs.com/#2FDQT5#3060)

 ![image](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/0/0/007ea3e39a9f9586fbc10ad3d5401d1331804cf4.png)

Edit:  
It might be somewhere else that requires gpu sync, using the no-readPixels `ConvertCubeMapToSphericalPolynomial` directly shows a very different speed.  
[https://playground.babylonjs.com/#2FDQT5#3061](https://playground.babylonjs.com/#2FDQT5#3061)

 ![image](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/4/b/4b808b08a6036dfac05144fc6858cf33f2c26053.png)

Edit2:  
A dummy readPixels cost more than 1s, there must be something wrong with it.  
[https://playground.babylonjs.com/#2FDQT5#3062](https://playground.babylonjs.com/#2FDQT5#3062)

 ![A dummy readPixels](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/e/7/e7256218c88c900b48a6d3da46e984e5fe05025f.png)

---

<div class="post-metadata">

**Author:** ![sebavan](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/sebavan/32/57_2.png) [@sebavan](https://forum.babylonjs.com/u/sebavan)\
**Post date:** [February 5, 2026, 4:32pm UTC](https://forum.babylonjs.com/t/gpu-sphericalharmonics-creation/62341/9 "2026-02-05T16:32:46Z")

</div>

It might wait for the gpu to flush the previous work before reading back ?

---

<div class="post-metadata">

**Author:** ![kzhsw](https://avatars.discourse-cdn.com/v4/letter/k/848f3c/32.png) [@kzhsw](https://forum.babylonjs.com/u/kzhsw)\
**Post date:** [February 6, 2026, 4:00am UTC](https://forum.babylonjs.com/t/gpu-sphericalharmonics-creation/62341/10 "2026-02-06T04:00:49Z")

</div>

Yeah I think so, using gl.fenceSync to wait for gpu sync gives a similar result with this playground [https://playground.babylonjs.com/#2FDQT5#3064](https://playground.babylonjs.com/#2FDQT5#3064) .

 ![fenceSync](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/7/5/757b407a65b61cb01a7ebf8cf654bfd1c1b17c51.png)  
And profiler shows dropped frame without any cpu or gpu activity during fenceSync.  
 ![dropped frame](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/3/0/30499592087ed4516140c48069ecd24e43e7619f.png)  
 ![without any cpu or gpu activity](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/9/9/994ab17ae755be8e15ed40f1da2c823ac6ee7a9b.png)
