I want to manually control (e.g. via a shader) how the viewport configured via the project settings is scaled to window/screen size.
Question
I am developing a pixel art game using pixel-perfect graphics. This is implemented in the following way: In Project Settings → Display → Window, the viewport size is set to the base pixel resolution (in my case: 240x160) on which I do all pixel perfect rendering. This is then scaled up to window size / full screen size via the Stretch settings mode=viewport, aspect=keep, mode=fractional.
It is widely understood that scaling the viewport up to window/screen size causes “pixel wobble” when the window/screen size is not an exact multiple of the viewport size as viewport pixels cannot perfectly be mapped onto the target resolution:
One strategy to mitigate this is called a “Sharp Bilinear Shader” which keeps the pixels apparently square by blurring pixel edges where needed. With this, a square pixel appearance is preserved with minimal blurring. Examples and explanations are here and here.
However, Godot does not seem to provide the functionality to select a filter for the stretching or provide a custom shader for this.
My question is: How can I use a custom filter/shader for upsampling my game from base resolution to window size? Is there some way I can circumvent the Godot default functionality via the settings menu and code the upsampling myself? How can I get control over this process?
@pennyloafers Thanks a lot for your response. I’ve realized that I still lack the knowledge to immediately apply your suggestions.
I looked into screen-reading shaders and post processing. Question: How can I apply such a shader not on my viewport resolution but on the actual stretched screen resolution? I used the setup described in the “Custom post-processing” section, adding an additional CanvasLayer with a ColorRect having the shader attached. But the fragments for which the shader is run are now the pixels of my viewport, not the pixels of the stretched window/screen.
For a technique like the one described in my initial post, I would need to modify each screen pixel, not the pixels of my viewport.