Saturn and N64 didn’t have this issue as much. The Playstation was a bit weaker and could not afford correct calculations. This image is an illustration why the wobble happens (not by me, found it online): https://imgur.com/aGc8WTE
I played both Resident Evil and Tomb Raider in 1997 on the Saturn, and I’m currently replaying Tomb Raider (Saturn), I didn’t remember how much texture wobble and and overall issues as you move along, they aren’t stable at all and there’s a lot of polygon dropouts, say, when there’s a trench with a movable block in between, it can look rough.
This is a classic case of a rushed game, though, many of its issues could have been sorted and even dynamic lighting, overall performance and more could have been fixed/implemented. I still love how it looks and the water warping effects are great.
Yes, most consoles from the 8-bit up to the 6th gen were quite unique, well, even the 7th gen, so there’s a lot of uniqueness to them overall. With that said, I don’t see any reason why such texture perspective improvements couldn’t be implemented in an emulator, as Duckstation does (and even so, it doesn’t work for all games, it depends on each title, but overall improves a lot of titles, including Tomb Raider).
The only thing impossible is the impossible itself, I mean, there were those who thought color television in the early days would never be possible, even CPUs passing the 1mhz mark wouldn’t be possible according to some. We live in an impossible world today, taking into account what wasn’t in the past.
Resident Evil looks stable, because it has mostly prerendered backgrounds and for the remaining 3D elements, the camera is fixed as well. And Tomb Raider does not look as stable as it should be on Saturn, because it is developed for Playstation as the main platform and has not much optimizations for Saturn; according https://segaretro.org/Tomb_Raider#Versions .
Agreed!
BTW, I mentioned “impossible” in my previous comment due to another post up above where someone mentioned something about fixing these texture perspective issues not being possible. So I ended up replying to your comment 
As for Tomb Raider, it’s well known that the PAL version released one month (or more, I think?) before the Playstation version, so the Saturn is where the series debuted, it’s interesting that few people knows this. I also remember reading years before, or watching a video about its development, where it’s stated the PS1 development team was having a hard time hitting a stable 20FPS until Sony themselves intervened and helped them, it’s the better and most stable version, for sure, but the Saturn one was so rushed, Burning Rangers is a more complex and impressive game, but it was also rushed and suffers from graphical glitches, and a few other bugs.
I can’t say about how possible such corrections are, but maybe there is some misunderstanding involved here? I just learned that Saturn is designed for quad based polygons rather than the triangles on Playstation. And PGXP is “probably” an algorithm for triangles and therefore a port is impossible and a new implementation of such corrections is needed? An explanation why this is not possible with Saturn emulation would be nice to know, as I struggle to find one online.
Is it possible to upscale Saturn’s 3D graphics like with Ps1 emulators, eg in VF2 and other 3d games? I’ve only seen it with their PC ports and I wonder why it has not been implemented yet
Yabause and its branches, i.e., Yaba Sanshiro and others are known for allowing 3D upscaling, other, more accurate emulators, Mednafen Saturn (Beetle Saturn core) and Ymir (standalone) don’t offer upscaling as of yet.
Most games wouldn’t look good or right when upscaled, though, most are better off at their native resolution and possibly with shaders.
Sounds right, I’m not much into technical stuff, but indeed the implementation would be different, it seems.
I believe what people want is the duckstation hacks that increase resolution, and fixing polygon wobble, making the games look like early PC games, assuming the Saturn does the same wobble and same rendering.
Personally I’d love to see an equivalent to PGXP for Saturn because that layer allows modding for modern stereoscopic 3D and VR. There are some mods out there to play the original Silent Hill in VR for example.
I didn’t test it but played through that game in stereo 3D and it was a blast. Also played a few Dreamcast games like House of the Dead and Ikaruga in stereo 3D and it was also very fun.
It was me who said that even the impossible is possible 
Going a lil bit into details:
The Saturn uses affine texture mapping, meaning it has no perspective correction. Textures are mapped linearly across polygons, which causes them to “wobble” and distort, especially on large surfaces viewed at an angle. This is a hardware limitation, not a bug.
An emulator has full access to all geometry data before it gets rendered. In principle you could:
- Intercept the polygon data before rendering
- Recalculate the texture coordinates with proper perspective correction
- Output the corrected image
This is what PS1 emulators already do with the pgxp feature. It can be done for saturn as well. However it is more complicated on Saturn.
- Saturn renders quads (4-sided polygons) instead of triangles, which modern GPUs handle less naturally
- It has two separate video chips (VDP1 + VDP2), making the architecture more complex than the PS1
It is technically feasible to make something similar as pgxp for Satur emulators, but nobody has seriously implemented it yet. It’s less a question of whether it’s possible and more a question of who has the time and motivation to build it. the saturn emulation developers and community is pretty small, this is why it takes so long to get a proper emulator.
I have high hopes that the developer for ymir achieves to build a stable, accurate and maintainable saturn emulator. This would attract others to support the project and the likelihood to get graphic enhancement features would rise. This would also make the probabilty higher for texture replacements in the future.
So in summary: with emulation a lot of features are possible. But you only need to find a developer who has the time and motivation to implement stuff.
I can give you even an approach how to implent the feature but I have neither the time nor the motivation to implement it (if you do technical stuff the whole day, the motivation to do it in your spare time is very low)
Step 1 – Parse the VDP1 Command Table Each VDP1 draw command is 32 bytes and looks like this:
struct VDP1Command {
uint16_t ctrl; // command type (sprite, polygon, etc.)
uint16_t link; // next command uint16_t pmod; // draw mode flags uint16_t colr; // color/texture info uint16_t srca; // texture base address uint16_t size; // texture width/height int16_t xa, ya; // vertex A int16_t xb, yb; // vertex B int16_t xc, yc; // vertex C int16_t xd, yd; // vertex D // ...};
You read these commands and identify textured quads (distorted sprites)
Step 2 – Recover the 3D Depth (Z value) This is the hardest part. VDP1 only stores 2D screen coordinates – the Z value is already lost after the game’s own projection. You need to reverse the projection:
// Approximate Z recovery from screen-space position
// using the Saturn’s fixed focal length float recoverZ(int16_t sx, int16_t sy, float focalLength) {
// Games typically use a known projection matrix // Z can be approximated from vertex divergence // across the quad float dx = (xb - xa) + (xc - xd); // horizontal spread float dy = (yd - ya) + (yc - yb); // vertical spread return focalLength / (dx + dy + epsilon);}
This is an approximation – perfect Z recovery is impossible without the original 3D data. But it’s good enough for convincing correction in most cases.
Step 3 – Compute Perspective-Correct UVs Replace the affine UV interpolation with proper perspective-correct interpolation:
// Affine (what Saturn does - WRONG) float u_affine = lerp(u0, u1, t);
// Perspective correct (what we want) // Carry 1/z per vertex, interpolate, then divide float oneOverZ0 = 1.0f / z0; float oneOverZ1 = 1.0f / z1;
float u_over_z0 = u0 * oneOverZ0; float u_over_z1 = u1 * oneOverZ1;
float u_corrected = lerp(u_over_z0, u_over_z1, t) / lerp(oneOverZ0, oneOverZ1, t);
This needs to be applied per scanline across the quad.
Step 4 – Split Quads into Triangles Modern GPUs only handle triangles. Split each Saturn quad into two triangles and pass the corrected UVs through a shader:
// Vertex shader - pass w for perspective division out vec3 texCoordPerspective; // (u/z, v/z, 1/z) // Fragment shader in vec3 texCoordPerspective; void main() { // GPU hardware perspective division vec2 uv = texCoordPerspective.xy / texCoordPerspective.z; fragColor = texture(saturnTexture, uv); }
Step 5 – Edge Cases to Handle
When implementing perspective correction for Saturn emulation, you need to account for several situations where the correction should either be skipped or handled differently.
The first case is flat geometry like HUD elements and UI. Many games render menus, health bars, and interface elements as flat screen-aligned quads with no perspective involved at all. Applying correction here would actually distort them. You can detect these by checking if the four vertices of the quad have near-zero divergence, meaning they form an almost perfect rectangle. If so, skip the correction and render them as-is.
The second case is intentional warping effects. Some Saturn games deliberately exploit the affine warping as a visual style or even as part of gameplay mechanics. Blindly correcting these would make them look wrong. The best approach here is a per-game database of exceptions, similar to how emulators like PCSX2 maintain game-specific fix lists. A community could maintain this over time.
The third case is VDP2 backgrounds. The second video chip handles scrolling tilemaps and background layers and does not produce texture warping in the same way VDP1 does. You can safely ignore VDP2 entirely for this feature and only apply the correction pipeline to VDP1 draw commands.
The fourth case is transparency and draw order. The Saturn’s VDP1 processes commands sequentially and some effects depend on that exact order, particularly translucency and blending. When you reroute rendering through a corrected pipeline, you need to preserve the original command sequence to avoid rendering artifacts like incorrect transparency or polygons appearing on top of each other wrongly.
Summary:
- Parse VDP1 command table
- Identify textured quads
- Approximate Z from screen-space geometry
- Compute perspective-correct UV coordinates
- Render via modern GPU shader with proper division
- Skip correction for UI/flat elements
The Z recovery in Step 2 is the biggest unsolved challenge – everything else is relatively straightforward graphics math. A good heuristic for Z combined with proper UV correction would already produce a dramatic visual improvement in most Saturn games.
If you find a developer who can do this, then you would be able to get the graphics improvements for saturn emulation, everyone is looking for. Ymir has the capability to implement the approach (looking into the file libs/ymir-core/src/ymir/hw/vdp in github, the author could make another vdp1_enhancement.cpp file).
Eu testei o core funciona corretamente, ele tem a mesma performance do Kronos.
I tested the core and it works correctly; it has the same performance as the Kronos.
