# OpenGL Problem With Screen Space Reflections in OpenGL

## Recommended Posts

Hi, I've recently been trying to implement screen space reflections into my engine, however, it is extremely buggy. I'm using this tutorial http://imanolfotia.com/blog/update/2017/03/11/ScreenSpaceReflections.html

The reflections look decent when I am close to the ground (first image), however when I get further away from the ground (the surface that is reflecting stuff), the reflections become blocky and strange (second image).

I have a feeling that it has something to do with the fact that the further the rays travel in view space, the more scattered they get -> therefore the reflected image is less detailed hence the blockiness. However I really am not sure about this and if this is the case, I don't know how to fix it.

It would be great if anyone had any suggestions around how to debug or sort this thing out. Thanks.

Here is the code for the ray casting

vec4 ray_cast(inout vec3 direction, inout vec3 hit_coord, out float depth_difference, out bool success)
{
vec3 original_coord = hit_coord;

direction *= 0.2;

vec4 projected_coord;
float sampled_depth;

for (int i = 0; i < 20; ++i)
{
hit_coord += direction;

projected_coord = projection_matrix * vec4(hit_coord, 1.0);

projected_coord.xy /= projected_coord.w;
projected_coord.xy = projected_coord.xy * 0.5 + 0.5;

// view_positions store the view space coordinates of the objects
sampled_depth = textureLod(view_positions, projected_coord.xy, 2).z;

if (sampled_depth > 1000.0) continue;

depth_difference = hit_coord.z - sampled_depth;

if ((direction.z - depth_difference) < 1.2)
{
if (depth_difference <= 0)
{
vec4 result;

// binary search for more detailed sample
result = vec4(binary_search(direction, hit_coord, depth_difference), 1.0);

success = true;

return result;
}
}
}

return vec4(projected_coord.xy, sampled_depth, 0.0);
}

Here is the code just before this gets called

float ddepth;

vec3 jitt = mix(vec3(0.0), vec3(hash33(view_position)), 0.5);

vec3 ray_dir = reflect(normalize(view_position), normalize(view_normal));

ray_dir = ray_dir * max(0.2, -view_position.z);

/* ray cast */
vec4 coords = ray_cast(ray_dir, view_position, ddepth);

##### Share on other sites

I found a fix to the problem. The problem was being caused because of this :

if ((direction.z - depth_difference) < 1.2)

(Visualize the scene with the first image)

The reason I needed this "1.2" magic number was to check whether or not the point B was not too far away from the point A (The point A's z coordinate basically projects to infinity because the reflection gets calculated with the info from a 2D texture). However this caused the weird bar artifacts because of the ray march distances.

With the box (second image), the ray marches are of a certain distance (it varies depending on how far the point trying to reflect is from the camera). The point P1 is positioned in such a way that when the ray thinks it hits the box with B1 (because it is behind A1), the ray is within the 1.2 proximity required for the reflection to happen. However, the point P2 is just in the zone where all the rays' B position (in this case B2) arrive just too far for the 1.2 requirement.

So how do you fix it?

Remove the 1.2 requirement!

However this causes other artifacts on the visible points on the surface that are behind the object being reflected. The rays emitted from these points will think that they reflect simply because their B point is behind the A point as there is no threshold. So if you remove the threshold there are artifacts and when you keep the threshold, there are still artifacts.

The solution I found was to get the two vectors : P to B and A to P. B is the point that the ray thinks it is at when it is behind A and A is the actual point that is going to be reflected. Depending on the angle between these two, I can tell whether or not to reflect.

On the third image, you can see that the angle between these two vectors for incorrect reflections is much bigger than that between the two vectors for the correct reflection. So the solution is to set the threshold to be

if (angle_between_vectors > some_value) reflect_point();

Hope this helped for anyone.

##### Share on other sites

Out of curiosity, any screenshots of the correct output?

Edited by orange451

##### Share on other sites
8 hours ago, orange451 said:

Out of curiosity, any screenshots of the correct output?

This is how it was before

Now it's like this

## Create an account

Register a new account

• ### 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!

• 15
• 21
• 21
• 11
• 9