We are making a 2D pixel perfect game. Our base pixel perfect resolution is 640x360.
This allows us to have a 1280x720 resolution that is pixel perfect (base res multiplied by 2)
This allows us to have a 1920x1080 resolution that is pixel perfect (base res multiplied by 3)
The problem is that we want to support “virtually” every resolution that user has using a rendering viewport that is multiple of our base resolution (640x360) so it’s always pixel perfect and using black “bars” top,down,right and left margins.
We always did that (using our engine) using a combination of glViewport() and glScissor() calls before drawing. But here in unreal we don’t know where to start.
Any experienced programmers with unreal to enlighten us with an elegant solution?
What we have tried:
-
- We tried the keep aspect ratio setting from the camera component. But this is not exactly what we need, because it allows rendering viewports that are not pixel perfect while maintaining the aspect ratio.
DOESN’T WORK.
-
- We tried to modify the Ortho size based on the viewport size inside PlayerCameraManager::UpdateViewTargetInternal using the great info found here https://weareludicrous.com/blog/2018…n-resolutions/
// The native resolution of the pixel art
const FVector2D ReferenceResolution(640.0f, 360.0f);
// The pixels per unit (translation factor from pixels to world units, in our case 32px (a tile) = 100cm)
const float ReferencePixelsPerUnit = 0.32f;
void ASMPlayerCameraManager::UpdateViewTargetInternal(FTViewTarget& OutVT, float DeltaTime) {
Super::UpdateViewTargetInternal(OutVT, DeltaTime);
UpdateCameraWidth(OutVT.POV);
}
void ASMPlayerCameraManager::UpdateCameraWidth(FMinimalViewInfo& OutCameraView) {
if (GEngine == nullptr) {
return;
}
const UGameViewportClient* GameViewport = GEngine->GameViewportForWorld(GetWorld());
if (GameViewport != nullptr && GameViewport->Viewport != nullptr) {
// Get the viewport size
const FVector2D ViewportSize(GameViewport->Viewport->GetSizeXY());
// Calculate the new orthographic width based on pixel art scale and viewport size
OutCameraView.OrthoWidth = (ViewportSize.X / ReferencePixelsPerUnit) / GetPixelArtScale(ViewportSize);
}
}
float ASMPlayerCameraManager::GetPixelArtScale(const FVector2D& InViewportSize) {
// Calculate the new art scale factor
float BasePixelArtScale = (InViewportSize.X / ReferenceResolution.X);
// Round it up or down
BasePixelArtScale = (FMath::Frac(BasePixelArtScale) > 0.9f) ? FMath::CeilToFloat(BasePixelArtScale) : FMath::FloorToFloat(BasePixelArtScale);
// In the extremely rare case where the display resolution is lower than the reference resolution we
// also need to protect against divisions by zero, although in this case the game will be unplayable :)
BasePixelArtScale = FMath::Max(1.0f, BasePixelArtScale);
return BasePixelArtScale;
}
This is pixel perfect 640x360:
Now we resized the window :
And the ortho fix, works fine for the World! except that it renders things that should not render (we fixed this with glScissor in our own engine, don’t know in unreal…) and the UI is not getting modified by that.
Doesn’t work…
So again… Any experienced programmer with unreal can help us with that? Thank you