Sign in to follow this  
gs2912

OpenGL Screen space reflections: Issues

Recommended Posts

gs2912    154

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:

http://youtu.be/4fyVNkr4wkY

 

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;
}

 

 

Share this post


Link to post
Share on other sites
Vilem Otte    2938

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)?

Share this post


Link to post
Share on other sites
gs2912    154

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...

 

 

 

Share this post


Link to post
Share on other sites
gs2912    154

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

Share this post


Link to post
Share on other sites
kalle_h    2464

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?

Share this post


Link to post
Share on other sites
gs2912    154

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.

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Similar Content

    • By povilaslt2
      Hello. I'm Programmer who is in search of 2D game project who preferably uses OpenGL and C++. You can see my projects in GitHub. Project genre doesn't matter (except MMO's :D).
    • By ZeldaFan555
      Hello, My name is Matt. I am a programmer. I mostly use Java, but can use C++ and various other languages. I'm looking for someone to partner up with for random projects, preferably using OpenGL, though I'd be open to just about anything. If you're interested you can contact me on Skype or on here, thank you!
      Skype: Mangodoor408
    • By tyhender
      Hello, my name is Mark. I'm hobby programmer. 
      So recently,I thought that it's good idea to find people to create a full 3D engine. I'm looking for people experienced in scripting 3D shaders and implementing physics into engine(game)(we are going to use the React physics engine). 
      And,ye,no money =D I'm just looking for hobbyists that will be proud of their work. If engine(or game) will have financial succes,well,then maybe =D
      Sorry for late replies.
      I mostly give more information when people PM me,but this post is REALLY short,even for me =D
      So here's few more points:
      Engine will use openGL and SDL for graphics. It will use React3D physics library for physics simulation. Engine(most probably,atleast for the first part) won't have graphical fron-end,it will be a framework . I think final engine should be enough to set up an FPS in a couple of minutes. A bit about my self:
      I've been programming for 7 years total. I learned very slowly it as "secondary interesting thing" for like 3 years, but then began to script more seriously.  My primary language is C++,which we are going to use for the engine. Yes,I did 3D graphics with physics simulation before. No, my portfolio isn't very impressive. I'm working on that No,I wasn't employed officially. If anybody need to know more PM me. 
       
    • By Zaphyk
      I am developing my engine using the OpenGL 3.3 compatibility profile. It runs as expected on my NVIDIA card and on my Intel Card however when I tried it on an AMD setup it ran 3 times worse than on the other setups. Could this be a AMD driver thing or is this probably a problem with my OGL code? Could a different code standard create such bad performance?
    • By Kjell Andersson
      I'm trying to get some legacy OpenGL code to run with a shader pipeline,
      The legacy code uses glVertexPointer(), glColorPointer(), glNormalPointer() and glTexCoordPointer() to supply the vertex information.
      I know that it should be using setVertexAttribPointer() etc to clearly define the layout but that is not an option right now since the legacy code can't be modified to that extent.
      I've got a version 330 vertex shader to somewhat work:
      #version 330 uniform mat4 osg_ModelViewProjectionMatrix; uniform mat4 osg_ModelViewMatrix; layout(location = 0) in vec4 Vertex; layout(location = 2) in vec4 Normal; // Velocity layout(location = 3) in vec3 TexCoord; // TODO: is this the right layout location? out VertexData { vec4 color; vec3 velocity; float size; } VertexOut; void main(void) { vec4 p0 = Vertex; vec4 p1 = Vertex + vec4(Normal.x, Normal.y, Normal.z, 0.0f); vec3 velocity = (osg_ModelViewProjectionMatrix * p1 - osg_ModelViewProjectionMatrix * p0).xyz; VertexOut.velocity = velocity; VertexOut.size = TexCoord.y; gl_Position = osg_ModelViewMatrix * Vertex; } What works is the Vertex and Normal information that the legacy C++ OpenGL code seem to provide in layout location 0 and 2. This is fine.
      What I'm not getting to work is the TexCoord information that is supplied by a glTexCoordPointer() call in C++.
      Question:
      What layout location is the old standard pipeline using for glTexCoordPointer()? Or is this undefined?
       
      Side note: I'm trying to get an OpenSceneGraph 3.4.0 particle system to use custom vertex, geometry and fragment shaders for rendering the particles.
  • Popular Now