Postprocessing adds a lot of pixelation

@new Did you write the comment at the followingChromium bug tracker? 1480965 - chromium - An open-source project to help move the web forward. - Monorail

If so, you should clarify that the comment is unrelated to the actual issue.

Make sure render targets are sized correctly inside of the passes, they do not take pixel ratio of renderer into consideration:

someRenderTarget.setSize(
  width * window.devicePixelRatio,
  height * window.devicePixelRatio
)

If we use values higher than devicePixelRatio, the result will be rendered at higher-than-physical resolution, then downsized, and will look even better (but will cost a lot more).

It is important to note (and maybe unfortunately) the postprocessing passes do not care about the pixel ratio we’ve set on our WebGLRenderer (with renderer.setPixelRatio(devicePixelRatio)) but this is good for keeping effect passes decoupled from renderers when possible (for use with multiple renderers in parallel, for example), and so we must explicitly handle pixel ratio ourselves when we size our effect passes.

BokehPass, for example, does not take pixel ratio into consideration when we set its size and it sets the render target size verbatim:

This means that if we set the pass to the same resolution as our WebGLRenderer, it will be half the resolution if our renderer.getPixelRatio() is 2! So, we need to do this:

const renderer = new WebGLRenderer()
renderer.setSize(width, height)
renderer.setPixelRatio(ratio)

const bokeh = new BokehPass(scene, camera)
bokeh.setSize(width * ratio, height * ratio)
1 Like

Yes, you are right. I deleted the comment.

That is not true anymore. If you call setSize() on EffectComposer, the composer honors the renderer’s pixel ratio and resizes all passes with the new effective width and height.

In general, you shouldn’t resize passes manually. Only resize the composer which cares about pixel ratio and the pass chain.

2 Likes

Ohh nice… TIL.

hi @Mugen87 . I’ve seen your comment about camera.near value in the bug. What’s the suggested min camera near value? I am currently using 0.02 which gives the visual results, but adds pixelation. Should it be higher?

If possible, yes. However, depending on how we fix the issue you can keep using the exiting value.

We have applied a change in three.js to mitigate this issue:

So the white pixel artifacts in the fiddle are gone with r157. It will be released at the end of this month.

3 Likes

This is awesome! Looking forward to upgrading the version asap! Thank you very much!

1 Like

Hi @Mugen87.
It seems the fix solved the problem only partially. If you pass antialias: true to the renderer, the issue is still present. Please see the fiddle here: Edit fiddle - JSFiddle - Code Playground. When I remove antialias: true the issue disappears.

Also, could you please suggest what antialising technique I can use for mobile devices? SSAA is too heavy for that, but I need something since the pixelation is terrible.

I don’t think we can properly fix the issue if you use 0.00000001 as a near value since even a higher depth precision has its limits. You have to increase the scale of your scene instead.

Have you already tried a FXAA? It should be a lightweight AA pass and hopefully mitigate your aliasing issues.

Oh, yes, sorry. However, it is still visible with camera.near = 0.01 which is not too low. Please see here: Edit fiddle - JSFiddle - Code Playground. When I disable antialiasing on the renderer level, the issue disappears.

It also disappears when disabling logarithmic depth buffer: Edit fiddle - JSFiddle - Code Playground

You really don’t need it with this near and far values.

Thanks for your help! For some reason FXAA was making the model blurry, but TAA with 2 level of smoothing works for mobile devices and fixes most of the issues. I will also play with the scale and hopefully make it perfect. Thanks a lot!
PS: But I still believe that the problem with antialising + logarithmic depth buffer is a minor defect :slight_smile:

Now I remember that this is actually a known issue. Unfortunately, we can’t fix this since using logarithmic depth buffer (meaning assigning values to gl_FragDepth) breaks MSAA. You can read more about this here:

1 Like

Thanks a lot for the info! Also, if you are interested. I played with scale and it didn’t give me any visual benefits for mobile devices, pixelation and other stuff was still quite heavy. TAA fixes it, but it causes minor lagging, FXAA - was fast, but blurry (not sure why). I found this discussion FXAAPass causing blurry rendering - #9 by Torben_Van_Assche will try to fix it based on the recommendations.

Just an update. I have fixed FXAA, but it doesn’t fix the pixelation, quite useless in my case.