Hi,
I've added a standard depth-based DOF post-processing pass to my terrain renderer, and noticed a horrible artifact. The CoC for the reflection in the water is completely wrong. This is because the CoC is based on the pixel depth for the water surface, instead of the reflected surface. The problem is most apparent when the water surface is undistorted and the focal plane is direcly over it.
I googled around, and apparently it's a limitation with all depth based DOF filters. Here's a page I found that explains the problem more clearly, with images: http://www.altyna.co...reflections.htm
The page also describes a solution, but unfortunately it's completely unusable for real-time renderers. (Basically jittering the camera position and rendering many frames).
So, is there anyone who has a proper solution to this problem? I've been thinking about storing a CoC value in the alpha channel of each texel of the reflection, but that seems overly complex, and would probably cause problems with alpha blending other stuff.
Thankful for any insight you might have!
Cheers,
Simon
[SOLVED] Depth-based DOF and reflections
If you do a depth pre-pass (à la Cryengine), couldn't you create a reflection of the depth and save it to your depth buffer? That way when you sample it for your DOF shader, you'll have reflected depth as well.
I suppose you'd have to try it out first, but it seems feasible to me. Of course there's a trade-off with performance for doing that, the main performance issue being the second geometry pass. Depending on the complexity of your engine though, it could be more good than bad, but I think it should be alright seeing as how Crytek does this in CryEngine2/3 without trouble, and it's easily one of the best engines around.
I suppose you'd have to try it out first, but it seems feasible to me. Of course there's a trade-off with performance for doing that, the main performance issue being the second geometry pass. Depending on the complexity of your engine though, it could be more good than bad, but I think it should be alright seeing as how Crytek does this in CryEngine2/3 without trouble, and it's easily one of the best engines around.
simonjacoby, what you want to do and the info on that page you linked is incorrect. Remember, whether it's a mirror reflection or diffuse color, it's all just reflecting light reaching the lens. What matters for dof is the distance the surface is from the focal plane that's reflecting the light, not the distance of the source of light that's reflecting off of the surface, if you get me.
@styves: Thanks for the suggestion. I think that is in line with my thinking with the CoC per pixel. However I realized that it wont be correct either, because it will fix the reflection, but the surface itself will then instead become incorrectly blurred.
The reflection on a water surface is just one example where it fails, a worse case would probably be a reflecting marble floor.
I realized this problem is a variant of the problem of overlapping transparent surfaces (particles for example) having a single depth value for the CoC calculation. I started look around after some digging I think that to properly solve it you have to use either raytracing or stochastic rasterization, both of which are still out of reach performance-wise. Maybe it's possible to do some hack until then. I'll try storing depth or CoC for the reflection like you suggested and see how it turns out.
@Sikkpin1: I don't think so. See the attached screenshot for an example, this is from my landscape renderer. The water surface should stay crisp the way it is, but the reflection should be blurry, just like the real landscape is.
The reflection on a water surface is just one example where it fails, a worse case would probably be a reflecting marble floor.
I realized this problem is a variant of the problem of overlapping transparent surfaces (particles for example) having a single depth value for the CoC calculation. I started look around after some digging I think that to properly solve it you have to use either raytracing or stochastic rasterization, both of which are still out of reach performance-wise. Maybe it's possible to do some hack until then. I'll try storing depth or CoC for the reflection like you suggested and see how it turns out.
@Sikkpin1: I don't think so. See the attached screenshot for an example, this is from my landscape renderer. The water surface should stay crisp the way it is, but the reflection should be blurry, just like the real landscape is.
Here's a photo I found after a quick google, just for reference. Notice how the image in the reflection matches the CoC of the real world.
EDIT: Sorry for spamming like this, but I just realized that I could just run the DOF post processing (or a simplified variant of it) on the reflection texture when I render it. Since the reflection texture is about a quarter of the main backbuffer, maybe performance won't be horrible. I'll try it and post my findings.
EDIT: Sorry for spamming like this, but I just realized that I could just run the DOF post processing (or a simplified variant of it) on the reflection texture when I render it. Since the reflection texture is about a quarter of the main backbuffer, maybe performance won't be horrible. I'll try it and post my findings.
So I tried it, and it works perfectly (and without using raytracing or other bs ) See attached screenshot. The reflection is now blurred and the water surface is still crisp. The DOF for the water reflection is just the reflection texture downsampled twice and then blended in with the original reflection texture with CoC per pixel calculated from depth.
I think the reason I didn't think of this in the first place is that I just thought it would be too expensive. However, if you just assume there will be other things happening, tonemapping, bloom, motionblur, dof, color correction passes and whatever else you might have going on, then adding a simplified DOF filter at half res on top of the reflection rendering isn't that big of a deal.
Anyway, thanks for your replies and happy coding
EDIT: Changed to nicer screenshot
I think the reason I didn't think of this in the first place is that I just thought it would be too expensive. However, if you just assume there will be other things happening, tonemapping, bloom, motionblur, dof, color correction passes and whatever else you might have going on, then adding a simplified DOF filter at half res on top of the reflection rendering isn't that big of a deal.
Anyway, thanks for your replies and happy coding
EDIT: Changed to nicer screenshot
Very nice, well done. Glad you figured it out.
Sikkpin: Oddly enough, that's incorrect. Here's an image I took of a mirror in my bathroom. I was able to focus in and out of the mirror, just as if I were looking at the bathroom normally. The CoC of the reflection and reality were identical, no matter how hard I tried to separate them. If the distance of the object reflecting was indeed the only thing that mattered, this would be impossible.
(For some reason I can't attach the image.)
Sikkpin: Oddly enough, that's incorrect. Here's an image I took of a mirror in my bathroom. I was able to focus in and out of the mirror, just as if I were looking at the bathroom normally. The CoC of the reflection and reality were identical, no matter how hard I tried to separate them. If the distance of the object reflecting was indeed the only thing that mattered, this would be impossible.
(For some reason I can't attach the image.)
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement