Jump to content

  • Log In with Google      Sign In   
  • Create Account

Screen space reflections: Issues


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
5 replies to this topic

#1 gs2912   Members   -  Reputation: 150

Like
0Likes
Like

Posted 05 February 2013 - 02:42 PM

Hey there gamedev people,

 

this is my firt post on the forums, even if I'm reading and searching here for some years now.

I'm studying computer visualistics in Germany and do a lot of OpenGL programming at the moment.

 

I'm currently trying to implement screen space reflections, but got some issues.

I first gather all informations in a G-Buffer (first pass rendering to frame buffer object) and do the lighting in a second pass.

Then I have a third pass for calculating the reflections.

 

Unfortunatelly, my reflections seem to be dependent of a certain viewing direction. They start to appear or disappear depending on the incident angle.

After implementing the approach several times and trying to understand the geometry on paper, this seems to be one of my last issues, until the reflections looks correct. I would be very happy if you'd take a lot at my code and hopefully someone can tell me my mistakes, I'd really appreciate that smile.png

 

Here's a short video to better show the problem:

 

And here's my shader code:

 

/******************************************************************************/
// LATEST (working, with some perspective errors)
/* SSR (screen space reflections)
 ******************************************************************************/
vec4 SSR()
{
   // Variables
   vec4 fragmentColor = vec4(0.0f, 0.0f, 0.0f, 0.0f);
   float initalStep = 0.001f;
   float stepSize = 0.01f;
   float blurSize = 1.0f;

   // Current fragment
   vec2 fragment = gl_FragCoord.xy/vec2(Screen.Width, Screen.Height);
   vec2 ssfragment = 0.5f * fragment + 0.5f;
   vec3 ssPosition = vec3(ssfragment, 0.0f);
   ssPosition.z = linearizeDepth( texture(deferredDepthTex, vert_UV) ); 

   // Normal & position
   vec3 vsNormal = normalize(texture(deferredNormalTex, fragment).xyz);
   vec3 vsPosition = texture(deferredPositionTex, fragment).xyz;
	
   // View vector
   vec3 vsViewVec = normalize( -ssPosition );
   vsViewVec.y -= Camera.Position.y;

   // Reflection vector
   vec3 vsReflectVec = reflect(vsViewVec, vsNormal);
   vsReflectVec = normalize(vsReflectVec);

   // Initialze traced ray
   vec3 initialRay = vsReflectVec * initalStep; 

   vec3 tracedRay = initialRay;
   // Get depth informations
   float fragmentDepth = linearizeDepth(texture(deferredDepthTex, fragment)); 
   vec3 samplingPosition = ssPosition + tracedRay;
   float sampledDepth = linearizeDepth(texture(deferredDepthTex, samplingPosition.xy));
   float rayDepth =  ssPosition.z + tracedRay.z * fragmentDepth;

   // Ray tracing while in screen space
   int count = 0;
   while(
	samplingPosition.x > 0.0f && samplingPosition.x < 1.0f &&
        samplingPosition.y > 0.0f && samplingPosition.y < 1.0f)
	{
		// Update sampling position and depth values
		samplingPosition.x = (2.0f * ssPosition.x - 1.0f) + tracedRay.x;
		samplingPosition.y = (2.0f * ssPosition.y - 1.0f) + tracedRay.y;
		sampledDepth = linearizeDepth( texture(deferredDepthTex, samplingPosition.xy) );
		rayDepth = ssPosition.z + tracedRay.z * fragmentDepth;
		
		// intersection found
		if(rayDepth > sampledDepth)
		{
			if(abs(rayDepth - sampledDepth) < 0.005f)
			{
				fragmentColor = vec4(
                                    texture(deferredDiffuseTex, samplingPosition.xy).rgb, 1.0f );
				break;
			}
			// Ray tracing termination
			break;
		}
		else
		    fragmentColor = vec4(texture(deferredDiffuseTex, fragment).rgb, 1.0f);

		tracedRay += tracedRay * stepSize;
		count++;
	}

	// Return color from sampled fragment
	return fragmentColor;
}

 

 



Sponsor:

#2 Vilem Otte   Crossbones+   -  Reputation: 1569

Like
0Likes
Like

Posted 05 February 2013 - 09:36 PM

You're definitely doing something wrong.

 

Basically your reflection rays are terribly wrong because reflections shouldn't transform when you rotate viewport (but they do). I'd say your screen space ray origins are wrong, shouldn't initial ray be viewVector * depth (although I'm not entirely sure, I'd probably have to test & go through your code at some better time than 4am)?


My current blog on programming, linux and stuff - http://gameprogrammerdiary.blogspot.com


#3 gs2912   Members   -  Reputation: 150

Like
0Likes
Like

Posted 07 February 2013 - 02:45 PM

I recently changed my code. I now calculate the reflected ray in the fragment shader of the g-Buffer using:

 

vec4 ReflectVec = normalize( reflect(vert_EyePosition, Normal) );

 

Where vert_EyePosition is the negative vertex position, which is multiplied with the model-view-matrix before in the vertex shader and

Normal is the interpolated normal from the vertex shader.

My resulting image of the reflected vector looks like this:

 

bsc22-reflectvec.jpg

 

But acctually my tracing doesn't work now, so obviously my reflection vector wasn't correct before. Now I just have to get the tracing right...

 

 

 



#4 gs2912   Members   -  Reputation: 150

Like
3Likes
Like

Posted 07 February 2013 - 08:48 PM

Okay, I got it working smile.png , had' some space conversion problems. And adding the camera's near-plane value to the view vector helped very much:

 

 

bsc24.jpg


Edited by gs2912, 07 February 2013 - 08:49 PM.


#5 kalle_h   Members   -  Reputation: 1570

Like
1Likes
Like

Posted 09 February 2013 - 04:28 AM

Okay, I got it working smile.png , had' some space conversion problems. And adding the camera's near-plane value to the view vector helped very much:
 
 
bsc24.jpg

Could you post the final working code as reference?

#6 gs2912   Members   -  Reputation: 150

Like
2Likes
Like

Posted 18 February 2013 - 05:55 AM

Sorry for the late response, but here your are.

I split the algorithm into two functions and remove some debugging stuff, I had there (e.g. a counter in the raytracing while loop for manually breaking the loop):

vec4 SSR()
{
	vec3 reflectedColor = vec3(0.0f);

	vec3 normal = normalize( texture(deferredNormalTex, vert_UV) ).xyz;

	// Depth at current fragment
	float currDepth = linearizeDepth( texture(deferredDepthTex, vert_UV).z );

	// Eye position, camera is at (0, 0, 0), we look along negative z, add near plane to correct parallax
	vec3 eyePosition = normalize( vec3(0, 0, Camera.NearPlane) );
	vec4 reflectionVector = ProjectionMatrix * reflect( vec4(-eyePosition, 0), vec4(normal, 0) ) ;

        // Call raytrace to get reflected color
	reflectedColor = raytrace(reflectionVector.xyz, currDepth);	


	return vec4(reflectedColor, 1.0f);
}
/*
 * Raytracing to get reflected color
 */
vec3 raytrace(in vec3 reflectionVector, in float startDepth)
{
	vec3 color = vec3(0.0f);
	float stepSize = rayStepSize; 

	float size = length(reflectionVector.xy);
	reflectionVector = normalize(reflectionVector/size);
	reflectionVector = reflectionVector * stepSize;
        
        // Current sampling position is at current fragment
	vec2 sampledPosition = vert_UV;
        // Current depth at current fragment
	float currentDepth = startDepth;
        // The sampled depth at the current sampling position
	float sampledDepth = linearizeDepth( texture(deferredDepthTex, sampledPosition).z );

        // Raytrace as long as in texture space of depth buffer (between 0 and 1)
	while(sampledPosition.x <= 1.0 && sampledPosition.x >= 0.0 &&
	      sampledPosition.y <= 1.0 && sampledPosition.y >= 0.0)
	{
                // Update sampling position by adding reflection vector's xy and y components
		sampledPosition = sampledPosition + reflectionVector.xy;
                // Updating depth values
		currentDepth = currentDepth + reflectionVector.z * startDepth;
		float sampledDepth = linearizeDepth( texture(deferredDepthTex, sampledPosition).z );
                
                // If current depth is greater than sampled depth of depth buffer, intersection is found
		if(currentDepth > sampledDepth)
		{
                        // Delta is for stop the raytracing after the first intersection is found
                        // Not using delta will create "repeating artifacts"
			float delta = (currentDepth - sampledDepth);
			if(delta < 0.003f )
			{
				color = texture(deferredDiffuseTex, sampledPosition).rgb;
				break;
			}
		}
	}

	return color;
}

 

If you have some questions or comments, give it to me :). I'd like to get more into that whole screen space stuff and understand it more.

 






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS