In the previous entry I ended with an abrupt half-joke where I said I got raytracing working. The idea was that I spent days struggling to get simple old technology working properly, but then casually mastered cutting-edge tech in a single sentence. Sadly, it’s not totally true. I got access to raytracing, but I think it’s a stretch to say it’s “working”.
When I left off, I presented you with an image that looked more or less like this:
That’s what the program looks like when you leave it alone, but if you move the camera even slightly then it looks something like this:
To a certain extent, this is expected. This is what you get with raytracing / path tracing. Even on the cutting-edge magic hardware we have these days, you still don’t get more than a few thousand rays per frame. We get around this with two techniques:
- We take the little bit of data available and spread it out. I’m not sure of the exact algorithm used, but it’s probably something like “if you’re rendering a spot that hasn’t been hit with ANY rays, then use the nearest available one”. So those existing pixels of light would get smeared out to fill the gaps. This means that the lighting starts out “blurry”. The walls and textures remain crisp, but the patterns of light and dark are initially vague. This gives the images a kind of “dreamy” quality.
- We accumulate rays over multiple frames. Each frame adds a few more rays to the scene, gradually filling things in and sharpening up the lighting. This means the room is initially dark if the whole thing enters the frame abruptly. The room starts out dim, and then gradually lightens as more light rays are added. You’d think this would look wrong, but it ends up feeling like your eyes adjusting when you enter a dark room. This works even if the previous room and this new one are supposed to be the same level of brightness. You can run back and forth between the two rooms, and it will always feel like you’re moving from a brighter room to a dimmer one. It seems to be one of those tricks that your brain just ignores.
As far as I can tell, these features are collectively called “denoising”. In the Quake 2 RTX demo, there’s a console command to turn denoising off and allow you to see the raw images with low ray counts, like my image above. The problem I’m having in Unity is that I can’t find either of these features. There are a few possibilities:
- Denoising hasn’t been implemented. I’m using a preview version of Unity for this projectUnity is REALLY graceful about letting you have several different versions installed simultaneously, and it keeps track of which projects belong with which versions. It’s pretty great. and it’s possible that denoising is still on someone’s to-do list.
- The denoising in the Quake 2 demo is an implementation of a very NVIDIA-specific feature. Maybe the Unity team wants to avoid manufacturer-specific gimmicks like that and aim for generalized solutions. Therefore, this is as good as it’s going to get until NVIDIA and AMD embrace some sort of standard. That will probably take months or years.
- The denoising feature exists, but it’s not documented and so I have no way of knowing where to find it or how to use it.
Normally I’m hard on the Unity team for the state of their documentationParticularly this ludicrous habit of documenting important things inside of hour-long video presentations. Arg. My rage is boundless., but in this case I’m obliged to cut them some slack. It’s called a “preview” version for a reason, and documentation is usually the last step. It’s annoying to have to fumble around in the dark like this, but that comes with the territory if you’re messing around with beta software.
Soon, or Never?
While I understand the lack of documentation, I really wish I could figure out if this is a problem that Unity plans to solve in the future. Without denoising, this system is largely useless for realtime projects. Indeed, on the forums it seems like everyone else is doing slow renders of photorealistic scenes.
But Shamus! I use Unity, and I’ve seen a “denoise” feature in the past. Are you blind?!
Yes, there’s actually a feature CALLED “denoising” in the render options, but it doesn’t seem to do anything and I’m not even sure it’s related to raytracing. One of the things I’m struggling with is that the options aren’t very organized right now. Like, there are two competing systems in use right now: Raytracing, and path tracing. But in Unity you have to enable raytracing, and then under the raytracing dialog you get a checkbox for path tracing. That’s like making Coke a subset of Pepsi. The menus are full of options for old-school rendering, current-gen rendering, raytracing, and path tracing. Some options only impact one of these systems, and there’s no way to tell if the feature you’re looking at is relevant in the render path you’re currently using.
At one point I clipped outside the level and I saw the sky was a gradient color with a horizon. It was really confusing to have all that background detail while I was trying to examine the level from the outside, and I wanted a simple flat color. I found four different dialogs that had settings for the gradient sky. I turned them all off, and the feature is still active.
The point I’m getting at is that the interface needs a re-work to support all this new stuff, and until that happens we have random features scattered everywhere and doing anything requires a ton of trial and error.
Anyway, back to the problem at hand.
It’s a shame I can’t make this work a little better. It’s really annoying trying to view the world through this odd shimmering snow, and if I want to see what I’m doing I have to hold perfectly still for 4-7 seconds to allow the rays to build up.
One way to make this slightly less painful is to make it so that there’s a lot more light. To this end, I slapped a grid of lights on the ceiling texture. It looks terrible, but it also makes it so the image stabilizes in 2-3 seconds instead of 4-7. I also added a reflective floor, because what else are you gonna do when you have raytracing? I predict that mirrored floors will be all the rage once raytracing catches on. In the 90s, game designers went nuts with the new colored lighting and turned their levels into rainbow neon puke festsThe original Unreal was the most over the top about this. And to be fair, it really did look amazing at the time.. I expect we’ll get the same thing with overly-polished surfaces in the next couple of years.
If Only This Worked…
I’ve been waiting for this moment for a long time. Once we get proper raytracing working, everything gets WAY easier for those of us making procgen content. In traditional rendering, making interesting lighting ends up being a massive pain in the ass. Lights are expensive. If you have too many in the same room, then you’ll kill the framerate. Too few, and you end up with either pitch black areas, or large sections where the lighting is very flat. You have to make sure your real light sourcesThe point in space that creates light. are reasonably close to your apparent light sources Example: A 3D model of a lamp and you need to position them so that you don’t get strange shadowsYou don’t want some little corner of the lamp to cast huge dramatic shadows all over the room. or visual artifactsIf you stick the light INSIDE the lamp, then it will be inside a hull of outward-facing polygons. Little bits of geometry will end up blocking the light in odd ways..
But in a raytracing context, none of this is a problem. You don’t need to worry about having an extra light here or there, because lights are literally free. Actually, a bunch of people nitpicked the video I linked above, explaining to me that lights aren’t actually free. Lights still cost CPU + GPU cycles to use! You fool!
To which I say: It actually depends on how you set them up. Yes, if you add traditional light sources then there’s some additional overhead. But why bother with that? In my project, I don’t have any light sources. I just have some textures set to glow. The renderer doesn’t even need to know that I’m using this thing as a light source. Rays bounce off of it and hit a wall, and you get light. That’s not any more expensive than bouncing a ray off a dark wall.
Also, making light sources out of objects solves other problems. In the real world, lights generally have a penumbra. You get a spot on the table that’s in half-light because it’s exposed to the left half of the lightbulb, but the right half of the light bulb is blocked by an object on the table. In traditional rendering, room lights come from an infinitely small point in space. This means they cast unnaturally harsh shadows with perfectly crisp edges. For years we’ve been trying to fix this by taking our crisp shadows and deliberately blurring them a bit. That softens the shadow, but it’s expensive and can lead to nonsensical results. Like the blurring goes both ways, which means it looks like the very edge of a wall is slightly transparent because some light appears to pass through it.
When the light is coming from an object, this stops being a problem because it works just like the real world. Larger lights will cast softer shadows because they’ll have a larger penumbra. The light comes out of whatever shape you make, so a tube light will behave differently compared to a light bulb, which will give different results than a bonfire. You don’t need any special code to do this. You just make your object the right shape and texture and you’ll get light.
With tracing, rooms won’t be overpowered if you use too many lights. Just like in real life, turning on three lamps doesn’t turn the room into a blinding white-out. It just makes it a little brighter. Likewise, having too few won’t make the image flat because you’ll still have lights reflected in from other places. And in either case, you can have all the lights you want without worrying about performance. You don’t have to turn off shadows for all the lights in the level and just have shadows enabled for the closest few, and then have a system for fading the shadows in and out as you change position. That’s a huge pain in the ass with lots of weird edge cases and fussy details to worry aboutLike, this light is one of the five closest, so we want to enable expensive shadows for it, right? No! It’s close spatially, but it’s in another hotel room and there’s no way for any of the emitted light to reach me. So this lamp is wasting processing cycles for no reason and should be turned off.. With tracing, you just let the lighting happen. You get shadows everywhere, all the time, and you don’t even need to care about where it’s coming from. A room made entirely of glowing bricks isn’t any more expensive to render than a room made of regular bricks.
All of this makes everything so much simpler for procgen content.
As for this project: I don’t know that there’s anything left to do at this point. I got a BSP reader working to my satisfaction, and I’ve fiddled with Unity’s current ray / path tracing solution. Maybe I’ll come back to this in a few weeks / months when there’s some new information or a new version to try, but for now I think I’m done.
But! There’s more programming content coming Real Soon Now.
WARNING: This post was thrown together at the last minute and didn’t get my usual editing pass. There may be (and probably are) many grammatical and typographical errors. Proceed at your own risk. Additionally, I may have put this warning in the wrong place.
 Unity is REALLY graceful about letting you have several different versions installed simultaneously, and it keeps track of which projects belong with which versions. It’s pretty great.
 Particularly this ludicrous habit of documenting important things inside of hour-long video presentations. Arg. My rage is boundless.
 The original Unreal was the most over the top about this. And to be fair, it really did look amazing at the time.
 The point in space that creates light.
 Example: A 3D model of a lamp
 You don’t want some little corner of the lamp to cast huge dramatic shadows all over the room.
 If you stick the light INSIDE the lamp, then it will be inside a hull of outward-facing polygons. Little bits of geometry will end up blocking the light in odd ways.
 Like, this light is one of the five closest, so we want to enable expensive shadows for it, right? No! It’s close spatially, but it’s in another hotel room and there’s no way for any of the emitted light to reach me. So this lamp is wasting processing cycles for no reason and should be turned off.
Batman: Arkham City
A look back at one of my favorite games. The gameplay was stellar, but the underlying story was clumsy and oddly constructed.
Why I Hated Resident Evil 4
Ever wonder how seemingly sane people can hate popular games? It can happen!
Even allegedly smart people can make life-changing blunders that seem very, very obvious in retrospect.
Batman: Arkham Origins
A breakdown of how this game faltered when the franchise was given to a different studio.
Silent Hill Origins
Here is a long look at a game that tries to live up to a big legacy and fails hilariously.