In the recent days, I’m learning to implement a simple screen space reflection effect. But there is a problem in the reflection.
It seems the reflection is not continuous, and is split by some horizontal lines.
I applied a traditional ray marching method to implement my program. And I tried to integrate the binary search to make the hit position more accurate. But this has no effect on the banding artifact.
However, I found if I reduce the step size of ray marching, the banding effect would appear less obvious, the height of each horizontal band becomes smaller. But I don’t thinks this is a ideal method.
Here, I paste my shader code for the ray marching, binary search, and a utility function which converts view space coordinate to the texture coordinate (range [0, 1]).
This is not the original code, I modified the some variable name and added some comments. Hope it would be more readable.
vec2 convertViewSpaceToTextureSpace(vec3 v) {
vec4 positionTextureSpace = projectionMatrix * vec4(v, 1);
positionTextureSpace.xy /= positionTextureSpace.w;
return positionTextureSpace.xy / 2 + 0.5;
}
// `direction` may not be an unit vector
vec3 binarySearch(vec3 origin, vec3 direction, int iterationLimit) {
float deltaDepth = 1;
while (iterationLimit-- != 0 && deltaDepth > 0.001) {
deltaDepth = origin.z - texture(positionInGBuffer, convertViewSpaceToTextureSpace(origin)).z;
origin += (deltaDepth > 0) ? direction : -direction;
direction /= 2;
}
return origin;
}
// `direction` should be an unit vector
bool castRay(vec3 origin, vec3 direction, out vec3 hitPositionViewSpace, out vec2 hitPositionTextureSpace) {
direction *= 0.1; // stepSize = 0.1
for (int i = 0; i < 1000; i++) { // numberOfSteps = 1000
origin += direction;
float depthFromGBuffer = texture(positionInGBuffer, convertViewSpaceToTextureSpace(origin)).z;
if (origin.z > 0 || depthFromGBuffer > 0) { // Point is behind camera.
return false;
}
if (abs(origin.z - depthFromGBuffer) < 0.1 && origin.z < depthFromGBuffer) { // stepSize = 0.1, avoid marching behind object problem
hitPositionViewSpace = binarySearch(origin, direction, 10);
hitPositionTextureSpace = convertViewSpaceToTextureSpace(origin);// Can be optimized with BST
return clamp(hitPositionTextureSpace, 0, 1) == hitPositionTextureSpace; // Hit something out of screen
}
}
return false; // Doesn't hit any thing
}
Thanks for spending some time reading through this question. Any suggestion is appreciated.