Screen Space Reflection Problem

Hi,

I’m trying to code a SSR based on this work: https://www.youtube.com/watch?v=2Tuo76YQZGg. I got almost everything working, however I still have some artifacts agaist rounded surfaces generating fake reflectionz. Here it is my example with the artifact highlighted in red [ATTACH=CONFIG]744[/ATTACH] . I’m trying to ignore it by using a bias checking the zbuffer diference in each step, however it is still not perfect and it doesnt work for every camera location. Does anyone know how can I fix this and tell which trick should I use!?

Thanks

The code is kinda messy, but I’m still working on it:

#version 330
precision highp float;

uniform vec4 mainColor;
uniform vec3 eyePosition;

uniform sampler2D reflectionPropertiesTexture;
uniform sampler2D depthTexture;
uniform sampler2D renderTexture;
uniform sampler2D positionTexture;
uniform sampler2D normalTexture;
uniform mat4 camera;

uniform vec4 refSteps;

in vec2 fragTexCoord;
out vec4 finalColor[2];

vec3 worldToScreenUV(vec3 position) {
vec4 LightSpacePos = camera * vec4(position, 1.0); //NDC

vec3 ProjCoords = LightSpacePos.xyz / LightSpacePos.w;
vec3 UVCoords;
UVCoords.x = 0.5 * ProjCoords.x + 0.5;
UVCoords.y = 0.5 * ProjCoords.y + 0.5;
UVCoords.z = 0.5 * ProjCoords.z + 0.5;
return UVCoords;

}

vec4 SSR()
{
float Shin = 1.0; //Shiness
float myDepth = texture(depthTexture, fragTexCoord).x; //Current depth
vec4 out_Color = texture(renderTexture, fragTexCoord) ; //Output color
//vec4 out_Color = vec4(0,1,0,1); //Output color

if (Shin<=0.01)  // NO SCREENSPACE REFLECTION
{
	 //Output color
	//nothinf
} else {
	vec3 	Normal 	= 	normalize(texture(normalTexture, fragTexCoord).xyz) ;
	vec3	Position = texture(positionTexture, fragTexCoord).xyz;
	vec3 	View 	= 	Position - eyePosition;

	vec3 R = reflect(normalize(View),Normal); //Reflected vector
	float vdotn = (dot(normalize(View),Normal)); //dot product
		
	vec2 size = vec2(1280, 720);

	// Fresnel
	//Shin = Shin * pow ( 1.0-abs(vdotn), 1.0 );
	Shin *= .6;
	bool outOfBounds = false;


	float STEP_SIZE = refSteps.x;
	float MAX_STEP = refSteps.y;
	float MAX_STEP_BACK = refSteps.z;
	float MIN_OFFSET = refSteps.a;
	
	float steps = 0;

	vec3 currentPos = Position ; //Posicao inicial para a marcha de raios
	float CurrentPosDepth;

	vec3 texPos ;

	//vec3 ScenePos ;
	float SceneDepth;

	float real_step = MAX_STEP;

	// marcha de raios
	while ( steps < MAX_STEP ){	
	
		currentPos += R.xyz*STEP_SIZE;
		
		texPos =  worldToScreenUV(currentPos); 

		//ScenePos = texture( positionTexture, texPos.xy   ).xyz;
		SceneDepth = texture( depthTexture, texPos.xy   ).x;

		if ( (SceneDepth <= texPos.z ) ) { 
			if(texPos.z - SceneDepth < MIN_OFFSET )
			{
				real_step = steps;
				steps = MAX_STEP;

			} else {
				steps++;
				outOfBounds = true;
				break;
			}
							
		}
		else {
			steps ++ ;
		}

		if(!(texPos.x <= 1.0 && texPos.x >= 0.0 && texPos.y <= 1.0 && texPos.y >= 0.0)) {
			outOfBounds = true;
			break;
		}
	}

	// Colidiu com alguma coisa
	if (real_step < MAX_STEP && !outOfBounds){
		steps = 0;		
		while ( steps < MAX_STEP_BACK ){	
		
			currentPos -= R.xyz*(STEP_SIZE/2)/MAX_STEP_BACK;
				
			texPos =  worldToScreenUV(currentPos) ; 
	
			//ScenePos = texture( positionTexture, texPos.xy   ).xyz;
			SceneDepth = texture( depthTexture, texPos.xy   ).x;

			if ( (SceneDepth > currentPos.z ) ) {  
				if(texPos.z - SceneDepth < MIN_OFFSET )
				{
					steps = MAX_STEP_BACK;	
				} else {
					steps++;
					outOfBounds = true;
					break;
				}
			} else {
				steps ++ ;
			}
		}
	}

	Shin =  Shin*(1.0-real_step/MAX_STEP);

	// COMBINING REFLECTION TO THE ORIGINAL PIXEL COLOR
	if (Shin > 0.01 && !outOfBounds){
				
		vec3 colorReflect = texture(renderTexture, texPos.xy ).rgb ;
		
		out_Color.rgb = mix ( out_Color.rgb, colorReflect.rgb , Shin);
		//out_Color.rgb = mix ( out_Color.rgb, colorReflect.rgb , 0);		
	}

	if(outOfBounds) {
		finalColor[1] = vec4(1.0,1.0,1.0,1.0);
	} else {
		finalColor[1] = vec4(0.0,0.0,0.0,1.0);
		//finalColor[1] = vec4(1.0,1.0,1.0,1.0);
	}

	if (Shin <= 0.01){
		finalColor[1] = vec4(1.0,1.0,1.0,1.0);
	}
}

return out_Color;
//return vec4(eyePosition ,1) + texture(normalTexture, fragTexCoord);

}

void main() {
float depth = texture(depthTexture, fragTexCoord).x;
vec3 position = texture(positionTexture, fragTexCoord).xyz;
vec4 ssPos = camera * vec4(position, 1.0);;
vec4 renderedColor = texture(renderTexture, fragTexCoord);
vec4 reflectionProperties = texture(reflectionPropertiesTexture, fragTexCoord);

if (depth<1.0) {
	if(reflectionProperties.x==0) {
		finalColor[0] = (texture(renderTexture, fragTexCoord) * mainColor);
		finalColor[1] = vec4(0.0,0.0,0.0,1.0);
	} else {

		finalColor[0] = SSR();
	}
} else {
	finalColor[0] = vec4(0.0,0.0,0.0,1.0);
	finalColor[1] = vec4(0.0,0.0,0.0,1.0);
}

}

[QUOTE=skul3r;1261696]Hi,

I’m trying to code a SSR based on this work: https://www.youtube.com/watch?v=2Tuo76YQZGg. I got almost everything working, however I still have some artifacts agaist rounded surfaces generating fake reflectionz. Here it is my example with the artifact highlighted in red [ATTACH=CONFIG]1438[/ATTACH] . I’m trying to ignore it by using a bias checking the zbuffer diference in each step, however it is still not perfect and it doesnt work for every camera location. Does anyone know how can I fix this and tell which trick should I use!?

Thanks[/QUOTE]

I got it working when I linearized the depth :slight_smile: