Question: When looking at old games like Mario64 or DukeNukem3D, all the mirrors in the game are essentially just holes in the wall with a mirrored copy of the geometry in front of the mirror put behind them. In the case of DukeNukem3D one can even activate no-clip and walk into that mirrored room.

In contrast modern games use a render-to-texture approach for mirrors. This leads to the mirrors getting noticeably pixelated when getting to close to them. One of the first games I noticed this approach was Luigi's Mansion, but it seems to be used in almost all modern games.

What change in the hardware or engines made the second approach become so dominant these days and what are the benefits to it? In terms of pure visuals the first approach seems superior, as it doesn't suffer from pixelation issues.

Answer: 
No, you are wrong - that's not how Duke Nukem 3D's mirrors worked at all.

DN3D used a *portal engine*. A joint between any two sectors was arbitrary to an extent, and when the rendering engine came to a portal, it knew that it has to start rendering another sector in that. The sector behind the mirror was basically a place holder to deal with a quirk in the engine - the only point of the sector was to be bigger than whatever you needed "reflected". It didn't contain any real geometry. In fact, it worked pretty much the same way "portals" work in Portal - except that Portal (itself being based on a portal engine) creates the portals at runtime, and has a limit to how many times the portals can recurse (i.e. A -> B -> A -> B -> A ...), while Build (DN3D) would simply crash as its stack overflowed if you pointed a mirror at another mirror.

It's obvious how simple it is to implement a mirror with that - make a portal that points *back* into the room. This meant that rendering the mirror would cost exactly as much as rendering the room itself, giving great performance and consistency. As long as you didn't point a mirror at another mirror, that is. If you look through the Build engine source code, you'll see there's no code handling mirrors at all - there doesn't have to be one, because that's how portals work *NOTE: actually, there is code to flip the rendered pixels - it just doesn't flip the geometry and all the various sprites and effects*. The editor had to be able to make these "fake" portals, though - looking back on itself. If you want to know more about the quite smart Build engine, there's a great analysis by Fabien Sanglard at [Build engine internals](http://fabiensanglard.net/duke3d/build_engine_internals.php). The whole engine has been open sourced and ported to modern platforms as well, though the old one still works flawlessly on Windows 10 (tested for you :P). Many of the games based on Build have also been open sourced and/or remade.

Why is this no longer used? Well, some engines no longer prefer portals, for one. It's tricky to apply a lot of graphics hacks and optimizations - I can't point you to anything specific, but a lot of post-processing depends on hacks that wouldn't work in a true portal engine (they make a lot of assumptions that no longer hold). This is basically the same kind of issue these games have with stereoscopic imagery - the hacks no longer work.

Most importantly, mirrors got more complicated. They can have complex shapes, textures, they may be on the ground (also known as "water") etc. While all of those problems are solvable in a portal engine, RTT becomes the simpler choice at some point, and GPUs are fast enough to handle it.

However, even with all that, there are plenty of games with hardware 3D acceleration that do things "real". Of the older games, Quake 3 or Alien vs. Predator, for example. As far as I know, Source engine games still use "real" mirrors. If you expect that people are going to get close to the mirror, and you can guarantee that there's not too many reflective surfaces at the same time (e.g. through level design), portal mirrors are still very attractive.
RTT would have been used if it was possible but the hardware rendering pipeline was one way.

Older hardware also had limitations that prevented render to texture. Writing to RAM means it can not be read at the same time. To improve rendering performance the destination buffer was locked to write only, only the display hardware could read from it. You could request reading, but that locked the RAM and the render had to wait for the lock to clear before it could start the next frame. RTT would cause a major bottleneck to the pipeline and thus other solutions were used.

You will find that befor Hardware rendering pipelines were the norm RTT was used as it provided a way to reduce the rendering load. 3D rendered to sprites to provide pseudo 3D content. Texture rendering was way too costly (CPU) to be used back then, apart from specialised machines that were outside the general consumer market.