# Help with GPU Pro 5 Hi-Z Screen Space Reflections

This topic is 1712 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi Bruzer100,

I was also preparing to start implementing something similar, and was disappointed to find that the code was unavailable, especially since several places in the chapter specifically tell the reader to consult the source.  I'm sure when I do start my implementation in the next few days, I'll probably run into similar issues like the ones you've come across, so if you wouldn't mind sharing what hurdles you've had to work around that weren't called out, or even want to share your implementation, it would be highly appreciated.  I'll bookmark this thread so that when I do start my implementation I can add anything I find to be valuable, especially if it was left out of the book's chapter.

Thanks,

WFP

##### Share on other sites

Hi guys,

Same boat as you. Are you doing the ray marching in screen or view space?

On page 174, it's not clear to me how the function intersectDepthPlane should work:

float3 o = intersectDepthPlane(p.xy, d.xy, -p.z);

Is this a type-o or am I missing something? Should it be 'p.xyz' since it should be re-projecting the point onto the near plane (o.z = 0)? The method can't assume the point returned is always at z=0 since it's also used to calculate the tmpRay position during the ray march (which needs to keep track of the .z component)

I would expect the method to look like this: (?)

float3 intersectDepthPlane(float3 p, float2 d, float z)

{

return p + float3(d, 1) * z;

}

Not sure how intersectCellBoundary works either with the crossStep and crossOffset... (why need these two helper variables? Why saturate the cross direction?)

Cheers!

Jp

##### Share on other sites

Also:

static const float2 hiZSize = cb_screenSize; // not sure if correct - this is mip level 0 size

I was also wondering about this. To me it would make sense that this should be the size of the mip_level we are starting the ray march from. Since it is used to do the first cell boundary test, but the name of the variable seems to imply otherwise :) Not sure either. Feels great to have other people to chat about this :D

Jp

##### Share on other sites
Hey Jp,

Great to see you're making some good headway on this. I'm looking forward to seeing how your translation to HLSL works out.

I realize I forgot to answer a question of yours yesterday, but I think you figured out the answer anyway - I am doing the ray marching in screen space.

Regarding the min-max tracing, what the author means is that when you're creating your hi-z buffer, you save not only the minimum depth value [min(min(value.x, value.y), min(value.z, value.w))], you also store the maximum value as well [max(max(value.x, value.y), max(value.z, value.w))]. What this gives you is a better estimation of the depth of the object at the pixel you're currently processing. You can use this in the ray-tracing pass to walk behind an object - if the current ray depth (from O + D * t) is outside the range of [min, max] at that pixel, you know it's not intersecting and can continue marching along that ray without further processing at the current position. I do not have this in my implementation yet, as I'm just trying to get the basics working first.

That's a good idea you had concerning the hiZSize, and this evening when I get back home (mine is a hobby project at the moment, so I work on it in my free time), I will try setting it to something like hiZSize = cb_screenSize / exp2(HI_Z_START_LEVEL). One of my issues could very well be that I'm not taking a large enough step away from the starting point to begin with.

Glad to have another person to bounce ideas back and forth with!

-WFP

(Edit: formatting and grammar)

##### Share on other sites

I tried using different cell sizes (mip levels) to offset the inital ray starting point.  Even going 2 down wasn't enough.  In the end, I ended up biasing much like shadow maps, to clean up the initial self intersections.  It means the reflections aren't perfectly lined up, but you can't tell once there is a blur applied.

I think you are having issues not rejecting the "wrong" ray hits.  This wasn't talked about in the article, or maybe I missed it, but the hiZ trace can return you a screen space position that is incorrect for the reflection.  Think of a ray going behind an object floating above the ground.  The Z position of the ray will be far in back of Z position of the object, but the hiZ trace will return you the screen space position of where the ray and object first intersect.  In this case, you need to understand it's a nonsensical intersection, and keep tracing.  This is also where the max part of the min/max buffer comes in handy, since you will now be "behind" the object, which the implementation in the book doesn't cover.

The author says he does handle all that in his implementation that he never shows us.  :/  IMO it's kind of an incomplete article, and I'm disappointed the GPU Pro editors decided to include it knowing it was written against source code that couldn't be released.  Seems a bit disingenuous.

Also, I _had_ to apply temporal super sampling and temporal filtering to my results to get the effect to shipping quality.  The temporal stability of the technique is very poor - you'll see shimmering / aliasing on real-world scene with any depth complexity to it.

##### Share on other sites

Hi,

I've spent just a moment this evening so far working some more on this, and it does seem that changing the hiZSize to what was mentioned above helps out some.  It is now defined as

static const float2 hiZSize = cb_screenSize / exp2(HIZ_START_LEVEL);

It still needs some refinement, but I feel confident that either a small linear search or a bias like Bruzer mentioned will help.

The main issues I'm facing now are these stair-step-like artifacts that show up.  I've attached links to two images showing what I'm talking about.

Any idea what causes artifacts like this?  Bruzer mentioned some stair-like artifacts he was seeing due to using a floor() command where he didn't need one, but I only have the one there to make sure the cell is an integer and removing that doesn't remove the artifacts.

I'm almost wondering if I'm not doing something in the "setup" code incorrectly - that is, the code leading up to the hiZTrace() call where I'm getting the position and ray direction.  Maybe someone could give it a once-over to see if I've missed something there?

Thanks,

WFP

https://www.dropbox.com/s/3rby7uwi2vugnw0/screenshot_4.png

https://www.dropbox.com/s/hs6ygesn1ez7sw4/screenshot_4_annotated.png

##### Share on other sites

@WFP, looking good :D This seems much better! Yes, it does seem like a small linear search at the end (I guess 4 taps for the missing first 2 mip levels) will probably help. What is the resolution your rendering at? Power of 2? The hi-z pass I wrote this pm doesn't currently support buffers that aren't power of 2 (incorrectly gathers mins and maxs). If some cells have incorrect min/max info, you might have some ray misses. I didn't get very far with the ray march today though. Will continue tomorrow. If I'd have to bet, I would say your screen space pos and dir are corrrect. I don't think you'd get any good reflections that way.

@Bruzer, I sort of agree about the article. It really doesn't stand on it's feet without the code. For example, the article describes in great detail how to calculate a reflection vector in screenspace. Diagrams, of a reflected ray, description of what is a reflection, and then, when it gets to the actual reflection algo: "to understand the algorithm, look at the diagram on page blah". There's a whole lot of subtleties not captured neither by the pseudo code, the diagram, or the code snippet.

I also looked at the simple linear ray march mini program and wondered how that could handle the case where a ray goes "under" an object (the code as is would conclude a reflection is good as soon as the ray reaches anything in front of it)...

And yes about the temp filtering, I was anticipating the reflection pass to be unstable :( How many history buffers did you keep?

Will post results as soon as I have anything.

Cheers,

Jp

• ### Game Developer Survey

We are looking for qualified game developers to participate in a 10-minute online survey. Qualified participants will be offered a \$15 incentive for your time and insights. Click here to start!

• 12
• 30
• 9
• 16
• 12