Ability to reuse the PMREM generated texture from scene.environment

Since scene.environment now always uses PMREMGenerator under the hood, I was wondering if the result of that could be reused for other purposes (for example, to display as blurred background).

WebGLRenderer seems to have cubeuvmaps internally only and not accessible, but maybe there’s another way?

For reference, here’s what I’m currently doing to get a blurry background from the environment - requires another duplicate PMREMGenerator right now:

scene.environment = texture;

// TODO can the PMREM from scene.environment be reused?
let pmremGenerator = new THREE.PMREMGenerator( renderer );
let rt = pmremGenerator.fromEquirectangular( texture );
scene.background = rt.texture;

// Workaround: can we get a specific mip level from the PMREMGenerator as new texture?
// Patch envmap_fragment.glsl.js to load background mip level
THREE.ShaderChunk.envmap_fragment = THREE.ShaderChunk.envmap_fragment.replace(
	`vec4 envColor = textureCubeUV( envMap, reflectVec, 0.0 );`,
	`vec4 envColor = textureCubeUV( envMap, reflectVec, 1.0 );`
);

A PMREM should not be used for blurred backgrounds. It is not intended and designed for this use case. I suggest you use the approach from the following PR:

BTW: There is no way to access the internal cube maps and IBLs produce by WebGLCubeMaps and WebGLCubeUVMaps. The user should actually not worry about this kind of stuff.

Thanks! I’ve seen that PR, looking forward to that getting merged. Looks pretty clean!
Also thanks for verifying that there’s no way to access the already generated cube maps.

The user should actually not worry about this kind of stuff.

Some users do worry about this kind of stuff, rendering performance, not doing duplicate work, etc., I’m not sure you can generalize like that.

Side note, pre-convoluted environment maps are sometimes used for blurred backgrounds (e.g. in Unity). They do work pretty well for that usecase actually (in many cases, they yield a much smoother result than regular mipmaps - exactly as for their intended usecase for roughness mipmapping) - whether their additional smoothness is wanted is a design choice.

2 Likes

As a visual example, here’s the quarry_01_1k.hdr background blurred with just mipmaps (on your PR) vs. what I’m doing above:

Using just mipmaps

Using PMREM

Interesting. When the PMREM integration was discussed, it was stated that PMREM is too blocky for background blurriness.

The implementation of my above PR is based on Daniel and Ben PRs which also use the mipmapping approach:

It’s good that you have posted at #23712 so the difference between PMREM and normal mipmapping can be clarified.

1 Like

I see, thanks for the additional links!

At least from working with Unity I can say that the “regular” mipmaps for cube textures are always too blocky, as mipmaps are not really meant to be viewed enlarged - quite to the contrary, they aim to represent a texture at a mapping near 1:1 between “screen pixel” and “mipmap texel”. In contrast, at least from my understanding, PMREM is designed to provide smooth appearance under enlargement (or, phrased differently, accessing a lower mip than what would be used based on texel size).

It might of course be that best results would be achieved with another convolution style (not PMREM but "create mipmaps so that they can be used for different levels of background bluriness) - I’d argue pmrem is closer to that goal than mipmaps but I can see that it could also be argued the other way around :slight_smile:

Can you elaborate a bit on this? I used the shader code to render the PMREM in a cube and it worked fine.

I’ve said that based on previous discussions at GitHub (see above).

1 Like

Not entirely true. WebGLRenderer.properties is public and a reference to the environment map is store there under all standard/physical materials. So you can make a standard/physical material, render it with envMap, then access the prefiltered envMap by renderer.properties.get(material).envMap

3 Likes

Good idea, thanks! Sounds like a kind of hacky but viable workaround to avoid regenerating it.

Do you know if this has been available for a while now? It’s somewhat odd that .properties are public, but it would be really nice if they stay that way.

Earlier PMREM was supposed to be used externally, after that i think it was already there, not sure though.