I’ve been pondering over this thread from time to time and wanted to add some thoughts that might be useful.
From my understanding of what has been written the main issue is that when setting the Unity output resolution to some small dimension ( say 640x480 ) via applying screen.setResolution() and using fullscreen set to true, text becomes understandably blurry.
Fixing this in Unity does not seem possible since using setResolution in fullscreen mode will be changing the display/monitor resolution directly, whereby the monitor will be stretching the input to fill the physical dimension of the display. This obviously means any blur caused by this is out of the hands of Unity at this point. Its simply not addressable and looking to try and improve the text rendering and maybe enforcing a limit to how low you can set the resolution is just trying to work around the problem instead of solving the cause - more on that later.
Now to be fair it does seem there is a bug that has been fixed in TMP where changes to screen resolution were not always reflected, but beyond that it doesn’t seem to be anything that can be solved on Unity’s end. As to why IMGUI looks sharper, its probably due to the difference in how the font characters are rendered, since IMGUI will render out AA characters at a specific resolution, while TMPro is using SDF we are just observing the inherent differences in sharpness between the methods at low resolutions.
I would imagine that the TMPro font rendering could be improved at these lower resolutions with some tweaking, but its never going to be great and possibly couldn’t match the old pre-rendered Unity fonts due to differences in how they are displayed. However again in my opinion its the wrong place to focus on as its not solving the cause of the problem.
With all this in mind the obvious approach to fix the issue would be to separate the rendering resolution of the game vs the UI. This is standard practice these days as dynamically altering the render resolution of the game but not the UI can provide a good solution to performance where fillrate is an issue.
The basic premise is to render your main game camera to a custom renderTexture where you can set its dimensions to reflect the size that you would have previously set via SetResolution. Then this renderTexture is rendered back to the screen either in a second camera postRender method or maybe by applying it to a RawImage in another canvas that is rendered before the UI canvas.
In this fashion you have made the UI resolution independent to the main game renderer and thus you can keep the screen resolution to match the native display resolution ( the UI renders at this resolution ) whilst the game itself can be rendered at any other resolution for the performance gains of reducing fillrate. You can still change the output resolution though in practice it shouldn’t be required.
Unity does offer this ability natively via ScalableBufferManager that can be enabled directly on cameras and avoid the whole RenderTexture aspect, but sadly this is not support for older 3d api’s or older devices which is usually precisely where you need this functionality!
Setting up the custom RenderTexture is heavily project dependent though and you’ll have to read up in the forums for the best way to approach it for your specific project.