The goal of this manifesto is to provide an easy to follow and reasonable rules that realtime and video game renderers can follow.
These rules highly prioritize image clarity/stability and pleasant gameplay experience over photorealism and excess graphics fidelity.
Keep in mind that shipping a game has priority over everything else and it is allowed to break the rules of the manifesto when there are no other good options in order to ship the game.
Fractional upscaling makes the game look bad on most monitors, especially if the scale factor changes over time.
What is allowed:
- Rendering to an internal buffer at an integer scale factor followed by blit to native resolution with a point/nearest filtering.
- Integer scale factor that matches the monitor resolution exactly after upscaling.
- The scale factor should be fixed and determined by the quality preset in the settings.
What is not allowed:
- Adjusting the scale factor dynamically at runtime.
- Fractional scale factors.
- Any integer scale factor that doesn't exactly match the monitor/TV resolution after upscale.
- Rendering opaque and translucent objects at different resolutions.
Implementation recommendations:
- Rendering at lower resolution internally, but outputting to native.
- Render at lower resolution render target, then do integer upscale and postprocess at native resolution.
- Use letterboxing to work around weird resolutions.
Low refresh rates (under 60Hz) increase input latency and make the gameplay experience worse for the player.
What is allowed:
- In case of a high refresh rate monitors (90Hz, 120Hz, 244Hz etc) it is allowed to render at 60Hz.
- It is always allowed to render at the highest refresh rate the hardware supports, even if it's lower than 60Hz (for example incorrect cable/HW configuration or user explicitly configured power/battery saving settings).
- Offering alternative graphics presets to reach target refresh rate.
What is not allowed:
- Explicitly targeting 30Hz refresh rate during development.
- Using any kind of frame generation - it does not improve the input latency which is the whole point of having higher refresh rates.
Implementation recommendations:
- Decouple your game logic update from the rendering code.
- Use GPU-driven rendering to avoid CPU bottlenecks.
- Try to target native monitor refresh rate and use the allowed integer scaling to match it.
- Use vendor-specific low-latency input libraries.
If you cannot compute something in the duration of 1 frame then stop and rethink what you are doing.
You are making a game, make sure it looks great in motion first and foremost. Nobody cares how good your game looks on static screenshots.
In many cases bad TAA or unstable temporally amortized effects is an accessibility issue that can cause health issues for your players.
What is allowed:
- Ray tracing is allowed as long as the work is not distributed across multiple frames.
- Any king of lighting or volume integration is allowed as long as it can be computed or converged during 1 rendering frame.
- Variable rate shading is allowed as long as it does not change the shading rate based on the viewing angle and does not introduce aliasing.
What is not allowed:
- Reusing view-dependent computation results from previous frames.
- TAA, including AI-assisted TAA. It never looked good in motion, even with AI it breaks on translucent surfaces and particles.
- Trying to interpolate or denoise missing data in cases of disocclusion or fast camera movement.
Implementation recommendations:
- Prefilter your roughness textures with vMF filtering.
- Use AI-based tools to generate LOD and texture mipmaps.
- Use AI-based tools to assist with roughness texture prefiltering, take supersampled image as an input and train the AI to prefilter it to have less shader aliasing.
- Enforce consistent texel density in the art production pipeline.
- Enforce triangle density constraints in the art production pipeline.
I'm going to just post some of my thoughts here, a bit disorganized.
The problem with any sort of post processed AA is that as an object goes further away from the camera the space between each pixel grows larger and you get shimmer, SMAA can't resolve this as it only sees edges. TAA is able to sort of resolve this with its frame jittering approximating what MSAA does, but the only proper way to get that small detail back is with super sampling or MSAA.
There have also been a string of papers from Square Enix about specular AA, with the latest being from 2021 and its implemented in Godot by default, but it doesn't fully clean everything up since it relies on geometric detail to work.
https://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf
For thin geometry falling apart at a distance, there is this technique from humus https://www.humus.name/index.php?page=3D&ID=89 which never really got used in anything as TAA started being used shortly after. It's currently implemented in Source 2 and is applied to the wire entities, you can see this in heavy use in Half-Life Alyx and Counter-Strike 2. It basically just scales the radius of the wire mesh to be within a pixel, and when the wire would be smaller than a pixel it offsets that by moving it to an MSAA coverage sample to fade it out proportionally.
I want to see work being done to try and resolve various forms of shader aliasing. You can get bad shimmer from normal mapped surfaces when the light is at an extreme angle, you get harsh clipping between the lit and shadowed portions of the surface, made worse when the mip level shifts. I wonder if something could be done in the same vein as the specular anti aliasing and offset the normal map based on the light angle.
I think Voxel Global Illumination should come back, its only used by CryEngine now because Nvidia dropped all work on it when they released their first RTX cards. It updates extremely fast and the results look on par with raytraced GI, it even allows for reflections.
Screen Space Reflection abuse is also something that should be in your manifesto, SSR can be fine for detail reflections, but when it gets used across everything for whole screen reflections it looks terrible and is more distracting than no reflections at all. Cyberpunk is an example of this, they use it as a pseudo GI on every surface and it shimmers and fades in and out randomly. There should always be cubemap fallbacks, and there should always be an option to disable them.