Godot Version
4.3
Question
I am working on a pixel art game and started with viewport stretch mode in a low resolution (640x360) and upscale it as the docs recommend. Now I’d like to apply a screen shader effect, but in the upscaled resolution.
After a lot of painful testing I am fairly certain that shaders are applied before the scaling happens.
How would I get “window resolution” screen shader effects while using viewport stretch mode?
Altenatively: If I use canvas item stretch mode with integer scaling and only allow resolutions that scale reaonably well, would that still lead to potential issues with clean pixel art scaling in the future?
Because that is the way I can easily get a high-res shader.
just use any Control Node type (typically the ColorRect) and set it to FullRect and apply shader to it?
That just gives me a 640x360 shader that gets upscaled and is incredibly blocky because of it. The way it seems to me Godot with viewport stretch mode enabled does viewport render → screen shader → upscaling.
I wanna know if there is a way to use viewport stretch mode while also having the shader use the window resolution. Maybe with using multiple viewports, but I haven’t worked with those yet.
what settings your project use for the stretch mode? i expect it should be expand, also it has to be canvas item
Viewport stretch mode, keep aspect ratio, integer scaling
because that is what the docs say to use for pixel art. Which leads to the aforementioned issue. See Docs and what they recommend for pixel art.
As I said, the issue disappears when I use canvas stretch mode, of course, but it is also what is literally not recommended by the engine itself.
Which is why I’m asking if there is any other workaround to have my shader calculated at the windows resolution instead of the viewport resolution while also using viewport stretch mode.
if the game is using viewport stretch mode and keep aspect ratio, then it will look so small for large screen resolution display?
EDIT: it looks like it will still scale properly, because it’s not disabled.
yeah, i dont see the problem here, your shader wont work or something?
how do you apply the shader for the whole game?
this is exactly what it does, because the screen_texture is just taking what’s on the screen, the viewport stretch mode is just scale it to user screen size, so it keeps the pixels but enlarged it, if you want smoother effect then do set your viewport size higher. but this will still have issue even if you set it to let’s say 1920x1080px. then any screen that’s larger than that can still see the “blocky”
How do I render the 640x360 image, have it be upscaled to the users resolution (which means the window width/height override setting) and then apply the shader so it has the higher resolution to work with?
what kind of shader you want to try? is it a full screen or just some part of the screen? that 640x360px
a crt effect shader, which is why I could really use the shader to be calculated at the higher resolution. obviously as a a full screen overlay.
i think if you insist that it should be using viewport stretch then you will want to actually scale your pixel arts up and also upgrade the viewport size to higher than 640x360.
let’s say you want to scale the pixel art twice large, then the viewport size should be 1280x720px
with that then the crt shader will looks far smoother
Yeah, the more I read on this, the more I think I should just stick with canvas stretch mode and fix any pixel stretching issues with integer scaling and limiting the available resolutions despite what settings the docs recommend. It is causing a lot more headaches than it seems to be saving me right now.
only downside is that sometimes the pixel art will have missing pixels. which is what pixel arts don’t want
else you will want to use shader that actually counter that.
i think the double the asset size and viewport should work though. while keeping the viewport stretch for that crisp pixel
wait i think i know how to actually convert the screen_texture to higher resolution, you just need to double the UV? before feeding to the crt effect. of course the crt effect will put out the exact size like it’s in, then you will need to divide it to go back to original size
I think only allowing integer scaling should preserve the pixels, it just means that some resolutions will get black bars. but I guess that would always happen for the more rare resolutions when I don’t want the game to zoom in.
From the recommended settings for pixel art games in the docs I linked earlier:
“Set the stretch scale mode to integer. This prevents uneven pixel scaling from occurring, which makes pixel art not display as intended.”
oh i forgot about the integer scaling, yeah then that might do it
Sadly it (I mean doubling the uv) doesn’t work, I already tried that and related things a bunch of times. The way it seems to me, Godot calculates the shaders and then scales up the whole image so the shader always gets calculated to the low viewport resolution.
I am going to go with the canvas stretch and integer scaling and hope that doesn’t lead to issues later. I gotta make some progress instead on being stuck on this issue any longer.