Path Tracing Quake in Blender
matthewearl.github.io
matthewearl.github.io
Pre-calculated lighting had very little to do with physical correctness, it was purely an artistic placement of light sources in a specific map processed with a specific tool (official or third party) with specific defaults. Two adjacent rooms could be lit in a very different manner because map maker decided it looked good; two maps coming from different sources could not be expected to share any common lighting principles. Quirks like overbright values were not even consistent among officially supported renderers, and were inherited by later Quake and Source engines (which would add their own quirks and light processing options). To put it shortly, there was no reference for the final result except the final result itself, and it often was unstable (changing textures, geometry, or processing constants would shift the look too much, and require fixes).
To make the game look as intended, you have to somehow rely on original lightmaps that are tightly coupled with original low resolution geometry and textures. Given that people still argue which of the original renderers gives the “true” picture, I have my doubts about making a new one that pretends some average light model is good enough for everything. Even for episode 1, hand-placed lights had to be reintroduced into the system, and ad-hoc fixes had to be done, but manual fixes are not an option for all the existing maps.
Kind of, but on the other hand:
> people still argue which of the original renderers
Now you have N+1 renderers - I'm not sure why the new one would be any more questionable than the last N-1. Obviously you shouldn't pretend this is somehow "the way it was meant to be rendered", but they don't seem to claim that; rather, this is one additional option of how to render it, with novel upsides not shared by the previous ones (but also with it's own set of downsides).
I'm saying that all of that doesn't converge. For lighting, we have original map data with original lightmaps, and that's it. How to interpret these? We can often reason about the port author used to check how the map looks, and sometimes guess whether author was lazy (guys, any map that is not pitch black is playable) or made very specific choices that have to be presented more or less intact. This makes any decision, even purely technical, an artistic choice. Should we render it this way? Sure, why not. Should we add motion blur? Sure, why not. Should we add lens flares? Sure, why not. And so on, and so on.
This might look like rambling, but there is an example of nonsense that is so ubiquitous most people don't even understand there is a problem: rendering resolution. To run software Quake in “mere” 640×480 with 25+ fps in 1996, you had to use the top home PC configuration available. And, contrary to modern expectations, first generation of hardware accelerators did not perform much better, there were no 60 fps 1280×960 crazy rides. They allowed to maybe play at the same ~25 fps (often in puke HiColor) if you did not have a monster 200 MHz Pentium, and be happy about it. Professional OpenGL accelerators are often mentioned, but their fillrate was actually less than that of a Voodoo, and they targeted the same typical resolutions (the difference was that they implemented crazy realtime pixel shading like reflection mapping in hardware, and offered the same fillrate in scenes using it, hence the crazy price tags). So 640×480 was Ultra Super High Definition in which people would realistically play Quake, and most would definitely use a lower one. Consequently, the complexity of 3D objects and textures match that specific range of screen resolutions.
What does anyone playing an old 3D game, streaming, or recording videos do today instantly on the first run? Setting game resolution to native, FullHD and higher. And then the game starts to look like empty amateurish junk from mid-2000 because neither geometry nor textures are matching the rasterizer resolution. Those giant flat polygons with sharpest edges never were the intended look of the game. People feel that something is wrong, add lots of common and uncommon texture filtering, make high resolution substitutes, but it all looks like a makeup on a corpse. The fix is not using the improper resolution in the first place. But this is so common that a lot of young viewers believe that this is how “retro games” looked like. They even make their own works based on that assumption.
But yeah, you never saw the blockheads of https://blog.habets.se/static/2015-03-27-e1m1-2c2b74e-0102.p...
Triangle count in models were just never a thing I remember seeing.
At the same time, though, we had nothing to compare to. It was perfectly normal that the legs move the same way when you ran forward as when you ran sideways.
So it's not just "what did we see then with eyes from 2021?", but "what did we see then with eyes from 1996?".
Will note that one minor detail about the Quake map format you may find interesting... Quake does not encode the texture coordinates for vertexes in the map. Instead, Quake encodes the coordinate system for textures of each face. This is transformed to screen-space during rendering.
This is different from modern renderers, which record the texture coordinates of vertexes.
Quake's system is less flexible, can't be used for character models, and can be inconvenient during asset creation, but it is a bit faster and more convenient at run-time. When you're rendering, you want to know the gradient of texture coordinates in the X and Y direction on screen, which is easy to calculate using Quake's system.
(Obviously the author knows this, but it wasn't spelled out in the article.)
Also AFAIK the texture coordinates are converted to regular U/V pairs when rendering.
The texture coordinates are not converted to U/V pairs. You may be thinking of one of other Quake-derived engines like GLQuake.
You are supposed to stick to the grid, the crate texture is sized so that it fits perfectly on the grid. If you go off the grid things become a bit harder, but this is why pretty much everything on Quake is axis aligned :-P.
It is ridiculously simple to make stuff actually.
About rotation, most editors that people used even in the 90s had support for texture locking for both translation and rotation. id's original editor was very primitive though, but later editors like Worldcraft and Radiant had those features.
WRT. texture coordinates, they are converted to U/V (or actually S/T) pairs, but it happens quite late during the edge span rasterization. You can see the inner rasterizer loop here[1] where it draws an edge span and performs a linear interpolation of the S/T values calculated at [2] above and [3] (during the surface draw setup).
Having said that i think what you described is closer to what Ken Silverman was working on at the time as a successor to the Build engine (at least based on my understanding from what he wrote years ago).
[0] https://i.imgur.com/5xWOw3K.jpg
[1] https://github.com/id-Software/Quake/blob/master/WinQuake/d_...
[2] https://github.com/id-Software/Quake/blob/master/WinQuake/d_...
[3] https://github.com/id-Software/Quake/blob/master/WinQuake/d_...
The whole distinction I was making was between calculating UV coordinates for the vertexes versus directly calculating the gradients.
Unless I’m reading this wrong, the UV coordinates for vertexes are not calculated. Instead, the gradients are converted to screen space and used to calculate pixel UV coordinates, exactly as I had said:
> …Quake does not encode the texture coordinates for vertexes in the map…
I have used Radiant and the “texture lock” was a bit of a joke for a long time. If a game is released in 1996 but it takes many years before something otherwise simple is easy to achivee in editors… the only natural conclusion is that the map format is optimized for renderer simplicity rather than map-making convenience.
This problem can be solved but the fact that the problem exists is just a curiosity in an otherwise obsolete engine. There is no reason why you would encode the texture coordinates that way in modern engines.
But yeah, they are not stored in the BSP file and are derived from the surface.
As for why it is done like that, it isn't for rendering simplicity but for storage. It takes less memory and disk space to store only the surface plane and texture axes and calculate the texture coordinates when you need them than store them on memory/disk for every vertex. Not only you store a few less bytes even for a triangle (with additional memory for each vertex) but also allows sharing of vertex and edge data which are common between surfaces even if their texture coordinates would differ.
After all the game had to run in systems with just 8MB of RAM.
> I have used Radiant and the “texture lock” was a bit of a joke for a long time.
Well, i just tried it in QERadiant and seems to work fine.
In any case, yes there are limitations, but when you are sticking to the grid - which is what most of Quake maps do, going off the grid isn't that common - the automatic texture alignment is also very convenient. This was also a big improvement over Doom where every linedef had to be manually adjusted and misaligned textures were commonplace.
[0] Traditionally S,T as convention are supposed to refer to coordinates in surface space and U,V in texture space but in practice everyone uses them interchangeably, especially with 3D APIs that use both to mean the same thing. Some older 3D graphics books do make a distinction though.
The author's write-up is better, and his target (Blender) enables some things mine (POV-Ray) doesn't.
I also really like the idea to use emissive textures. I just used point light sources.
I'm still rendering, and you can join if you want: https://qpov.retrofitta.se/
https://docs.blender.org/manual/en/latest/render/cycles/rend...
In my estimation of things: motion blur is only beneficial to try to work around sample and hold displays. If there were fully continuous (1000 Hz is close enough) or sub 1 ms strobed displays then motion blur would add nothing.
And if you can renderer 1000 images per seconds, then generating motion blur that work on a 100 fps monitor is as simple as displaying an average of 10 frames.
The various motion blur techniques allow simulating higher frame rate without paying the full cost of rendering all the extra frames.
Blurbusters has a fair amount of literature on this topic.
https://blurbusters.com/blur-busters-law-amazing-journey-to-...
Edit: The article you linked to is very confused about some basic terminology. It equates response time artifacts of an LCD monitor that display sharp, digital images with motion blur. That's so wildly wrong I'm not even sure where to start. Maybe here: When displaying video, motion blur is a property of the source, response time one of the output device.
(+) Edit 2: To expand on this, the human vision system integrates arriving photons over time, and this way implicitly behaves a lot like a low-pass filter. A low-pass filter is different from a fixed-rate shutter, which is what people mean when they say the eye doesn't have a fixed framerate. However, there is a limited temporal resolution.
A more everyday example of this effect would be a dimmed LED. You can pulse an LED at 1 MHz, it will look dimmed, not blinking. But when filming/rendering this LED at 1 million still images per second, it will either be all on or all off, both of which are wrong (i.e., an artifact of your chosen shutter speed).
>look blurred to the human eye
Ah but it has everything to do with biology. You are proposing a far too simple model for the signal processing actually at play. Unfortunately there is no clock going to the rods and cones, they simply fire signals off asynchronously and the timebase is reconstructed in your noggin. How would you go about filtering a few million samples all on their own timebases that are themselves not uniformly (or even periodically) sampled? It would be a truly awful approximation.
However, the complexity of the biology behind this doesn’t actually matter for my argument. My point is that we need proper signal processing in order to not irreparably damage the signal before it reaches the eye, when we’re still in the realm of precise technology. I’m not sure if I explain this poorly or if you’re a tiny bit motivated to misunderstand me, but of course, it is a complex subject.
As a last honest attempt, can we agree in the simplest possible case — that an LED blinking at 1 MHz filmed at 1 million still frames per second can’t ever reproduce a signal that can be interpreted as being dimmed? If so, we already agree that we have an artifact. Then the question is only how to remove it, and signal processing theory gives an answer.
If not, I’d recommend that you work through it with pencil and paper: what is the LED doing, what are the still images showing, what is the monitor showing to the eye? You can’t miss the conclusion if you do this carefully.
I had a lot of fun making Thief levels though.
There might be add-ons that help, but vanilla Cycles will take orders of magnitude more samples to create a good image when there's caustics involved than when there's not. For that reason, it's still common to fake caustics in Blender using a texture or projection effect.