Problem applying a generated cubemap, prefiltered, to a material

I’m generating a dynamic cubemap runtime. I then want to prefilter that cubemap and apply it to a material, in order to use the cubemap as ambient light source on geometry. But I can’t make it work. Changing the cubemap on a material doesn’t always seem to change the ambient light calculation for some reason.

I’ve made a small test scene here:

The glossy sphere shows the generated cubemap (in this case just a render of the scene, but will be something else). I would like to also apply the cubemap to the diffuse sphere, to get that nice ambient lighting. This requires that the cubemap be prefiltered. Problem 1 is that I’m not sure I prefilter correctly. I use pc.prefilterCubemap, but documentation is only a few words.

Problem 2: To test I also added two different static cube-maps, in both prefiltered and non-prefiltered versions, so 4 in all. I have buttons to change cubemap between all the cubemaps at runtime. But changing between prefiltered and non-prefiltered doesn’t switch the ambient term on and off as expected. Also, changing between the prefiltered cubemaps doesn’t seem to work. It works when changing the cubemap from the editor.

Maybe I’m missing something, but right now I’m stuck, so it would be a great help if you could look at it and see if I need to do something different when applying the cubemap to a material to make the ambient lighting work. Also please let me know if I use pc.prefilterCubemap wrong.

Thanks in advance

1 Like

@mvaligursky @slimbuck Any ideas/gotchas that you can think of for this?

One thing is … to enable material to use cubemap, you need to disable it using the skydome one. something along:

    shinyMat.useSkybox = false;
    shinyMat.cubeMap = shinyBall.script.cubemapRenderer.cubeMap;
    shinyMat.metalness = 1;
    shinyMat.useMetalness = true;

@slimbuck is at the moment creating some nicer wrapper over prefiltering functionality … he’ll have more to say :slight_smile:

Hi @Snupty,

Yeah cubemapping and prefiltering is currently a little tricky.

Thanks for the repro project, I will see what I can do there.


Good idea @mvaligursky, but didn’t help, alas. Also, I don’t want to set metalness. I want the cubemap to supply the ambient color on a diffuse material. Setting useSkybox = false isn’t necessary when setting the cubemap in the editor.

Thanks @slimbuck and @mvaligursky , really appreciate help from you guys!

1 Like

Hi @Snupty,

We’re still working on this, but I thought I’d post a work-in-progress. has dynamically generated prefiltered lighting. The prefiltering is done in IBLProbe.js. This code will ultimately be added to the engine and we will expose the functionality in a nice way.

You will notice it currently runs pretty slowly and the dynamic cubemap is mirrored. I will address both issues in the coming weeks. Sorry it’s taking so long.


Hi @slimbuck, great to see it coming along nicely, thanks! Just a few comments:

  1. I can see that you scene.setSkybox , where I planned on mat.setCubemap, is that just work-in-progress or the only way? I don’t know for sure what’s best in our case, but would like to keep the options open.

  2. I plan to spread the cost over 6 or 7 frames, where I draw one cubemap side per frame, then perhaps in the 7th frame do the prefiltering (or even one side at the time again). Will that be possible?

  3. If we don’t end up using it for reflections (undecided), but just for ambient light, then using a smaller resolution may be enough, eg. 64 x 64 or even smaller. Will that be possible?

Thanks again

Hi @Snupty,

  1. You should be able to use the IBL cubemaps directly on materials, but I’ve not tested this myself.

  2. Yes exactly - spread the work over multiple frames. Ideally IBLProbe would handle much of this for you. I recently submitted to allow prefiltering a single face at a time, just waiting for that to be deployed.

  3. This is not something I’d considered, but will keep it in mind. The engine currently uses the 4x4 prefiltered lighting cubemap for ambient and creating it directly might be quicker.

1 Like

I’ve been using this method successfully, but recently noticed that the code in IBLProbe.js gives a deprecated warning because pc.reprojectTexture no longer takes a graphicsDevice as first parameter. I thought I could just remove that parameter, but the result is not the same, in particular it gives some seams between the cubemap sides. What is the correct solution?

Ah, I needed to also pass the options differently so:

     pc.reprojectTexture(device, this._source, cubemaps[0], 1, 1024);


     pc.reprojectTexture(this._source, cubemaps[0], { specularPower: 1, numSamples: 1024 });

Hi @Snupty,

Yeah unfortunately you bumped into the signature update we did in Updated reprojectTexture by slimbuck · Pull Request #3167 · playcanvas/engine · GitHub.

1 Like