PBR Refraction roughness (blurriness)

This might be related to KHR_materials_transmission & roughness? but I’m not sure.

I’m trying to change the blurriness of the refraction based on the PBR roughness of the material.
In the sandbox, the roughness works out of the box.
PG: https://playground.babylonjs.com/#22KZUW#261

However, I’m not able to find the values/attributes needed to create the same kind blurriness.
Any idea what I might be missing in the playground?

You can somehow use the lodGenerationOffset property of the refraction texture to simulate the roughness by using some lower mipmaps:
https://playground.babylonjs.com/#22KZUW#262

It will become blocky when using some higher values, however.

You could try to use some ReflectionProbe instead of refraction textures. You would need to use realtime filtering, though, which could be a bit taxing on performance… We are using a transmission helper class to handle transmission with glTF files, but this class is not exposed because we are not sure it will stay for the 5.0 release.

1 Like

Hi @Evgeni_Popov, thanks again for the quick response.

That definitely looks too blocky for my taste.
Got the reflection probe working in the playground https://playground.babylonjs.com/#22KZUW#273 (and it is indeed super heavy) but the roughness doesn’t affect the blurriness as well.

You need to enable generation of mipmaps for the probes, as well as adding a reflection texture (env map - see line 4), else the realtime filtering feature is not enabled:

https://playground.babylonjs.com/#22KZUW#274

I have also enabled the local cube map feature on the refraction textures (by setting the boundingBoxPosition and boundingBoxSize properties), as it is a little better.

1 Like

Hi @Evgeni_Popov , I see, thanks! So the reflectionprobe seems to work with LODoffsets to some degree. The blurry versions do look pixelated.

I do think the performance struggle is a bit to much with these three reflectionprobes. Is there a way to use some kind of BlurPostProcess on a RefractionTexture? They all seem to need a camera in the constructor.

You can try to do what the shadow generator does to blur the shadow map when using the blur exponential/blur close exponential filtering methods. It attaches to the onAfterUnbindObservable and does a direct render of the blur post process.

Relevant code:

The blur post processes are created here:

Hi @Evgeni_Popov thanks for pointing me in the right direction.
Seems just repeating the logic in the ShadowMap does not seem enough…
When disabling the textureSampler I do get a black sphere though so something must be happening.
https://playground.babylonjs.com/#22KZUW#284

You can’t render the blur pass into the same texture you are reading from, you get a “Feedback loop formed between Framebuffer and active Texture.” error because of that. So, you must create an additional texture T that you will render into, and bind this texture as the refraction texture of your material:

Some comments about this PG:

  • I commented the packFloat = true thing, I don’t know the purpose of this in the shadow generator code and it makes the blurring fail
  • Now that the pbr.refractionTexture property is set with the new T texture, you must add the regular refractionTexture in the scene.customRenderTargets array so that it gets generated. Indeed, RTTs (like T) assigned to some texture properties of the standard/PBR material are automatically generated each frame, but RTTs that are not are not automatically generated, you must tell the system you want them to be generated by adding them to scene.customRenderTargets
  • T is a regular RenderTargetTexture, so it gets generated each frame, meaning it is cleared and the meshes from its renderList are rendered into this texture. As this list is empty we are fine in that area, but the texture still gets cleared, something we don’t want as it happens after the blur have been generated, nullifying this processing. To avoid this clearing, we add an observer to T.onClearObservable that does nothing.

Came across this older threat, with the same desire to create a blurry RefractionTexture. Using a probe does not work well for me, as I want to simulate a pane of glass, and only RefractionTexture gives me correctly looking refractions…

So, first the PG you posted above @Evgeni_Popov does not work anymore for BJS 5 (it does for 4.2!). Any idea what needs to change?

And second, is there any inherent reason why just using PBR’s roughness in conjunction with a RefractionTexture does not work, while it does (as in one of the later examples) for a cube texture (regular one or via ReflectionProbe)? Or is it just a missing feature?

I applied the blur post process suggestion to a similar PG (https://playground.babylonjs.com/#22KZUW#312) for a flat pane of glass, which gives the desired looks. But it took me a while to find this threat and apply the post process stuff, so I think it would be cool if it would “just work” using roughness, as one might (naively?) expect!

Since 5.0, postProcessManager.directRender() is taking a RenderTargetWrapper instead of an InternalTexture as the output object (change in line 153):

I don’t really remember how we ended with this PG, but if you found an easier way to achieve what you want all the better!

2 Likes

Cool, thanks for the fix!

And what about my second question, do you have any insights there?

Actually it somewhat works but you need to set some sensible values for refractionTexture.lodGenerationScale and refractionTexture.lodGenerationOffset (which are both 0 by default):

1 and -4 are the default values used by the glTF transmission helper.

The formula is: final LOD=LOD_computed_from_roughness*scale+offset.

Of course, as it is using LOD to fake bluriness it may appear blocky and is not very precise, but it works as a crude approximation.

1 Like

@Evgeni_Popov I came across this very useful thread when searching for techniques to achieving accurate blurry refractions. The below PG example seems to work great. But my question is how do we achieve a gassuan blur. According to the docs you can use this effect twice once in x and y but my attempt so far has failed .

think I figured it out. Just do : var postprocesses = [blurXPostprocess,blurYPostprocess];

If there are any caveats to this let me know.

2 Likes

It seems ok to me!

1 Like