Deferred Rendering... with some issues

Hey all…

In my spare time, I’ve been working on a deferred rendering implementation and I’m hitting a snag, that (from what I can tell) everyone else has hit as well (whether or not they realized it).

I’m having trouble correctly reconstructing the position from depth.

Let me start with an example of how position from depth should be constructed (in all examples I have found):

[java]
// Depth in this case, is non-linear
vec4 position = ProjMatInv*vec4(texCoord, depth, 1.0);
position.xyz /= position.w;
[/java]

One thing that is not clear from the examples is the use of the inverse projection matrix… every topic/paper I have read on the subject says using the inverse of the current projection matrix. Which one?

I’m not so sure this is what I am looking for as it is completely unusable for everything from Parallax mapping to SSAO. Though seems to do fine for lighting.

Sooo… the question is:

  1. Does the above reconstruct the position in View Space? Or World Space?

I can not track down a definitive answer, though I would have to assume that since it is starting in screen space, using the inverse projection matrix would result in view space. However, no matter which is the case, the results are unusable unless you comment out the second line. Which makes little sense, as every example I can find uses the above.

The results are clearly wrong, if you output them to the screen.

I guess, one of the biggest problems I am having is:

  1. There is NO comprehensive list of global variables that JME will pass to shaders (though the documentation has said this will be added for over 3.5 years now).
  2. Why, oh why did someone decide to replace the word Model with World? /cry This has been the bane of my existence for… well… since I started writing custom shaders for JME. Though may have been easier to deal with if that illusive comprehensive list of globals had been added to the docs.

Soooo… aside from the single question above (which I would REALLY appreciate some insight into), is there any chance we could finally get that comprehensive list of globals? please please please please please?

There is actually more to this… but this would be a stellar start!

@t0neg0d said:

Soooo… aside from the single question above (which I would REALLY appreciate some insight into), is there any chance we could finally get that comprehensive list of globals? please please please please please?

UniformBinding and UniformBindingManager.updateUniformBindings is the place you are looking for I think.

1 Like
  1. Well according to the naming scheme , ProjMatInv must be the Projection matrix inverse then it reconstruct in view space.
model  ----> World ----> View ----> Projection
   worldmat        viewmat     projmat
    ------Worldviewmat------
                     --------ViewProjMat--------
    --------------WorldViewProjmat----------

EDIT : I can’t emphasis on this enough, because this is the most important thing to have in mind when you’re dealing with shaders.

Not sure that’s clear, but that explains how you transform position from a space to another. Of course to go backward you have to use inverse matrices.

Note that very often the lighting in a deferred rendering process is computed in view space.
There is also an alternative to that matrix multiplication. It’s named the frustum corners method, and allow to reconstruct the position from depth with just a couple of uniform and a formula.It’s faster and uses slightly less uniforms.
That’s what is used in the SSAO Filter, I recommend using it.

1.bis There is, depending of what you mean by comprehensive, but I always find it enough http://hub.jmonkeyengine.org/javadoc/com/jme3/shader/UniformBinding.html
2. No one did, you are confused about the spaces. The only strange thing is that the starting space is not mentioned in the Matrix name. and that’s pretty much a conventional naming around opengl.

IMPORTANT :You’re probably using a FilterPostProcessor for your deferred rendering. Note that if you are using 3.0 release, the Camera related globals are no the ones you expect to be. In 3.0 we were using another camera in parallel projection to render the full screen quad, so the globals are the ones from this cam…That’s maybe the issue here. In that case you have to use classic material paramters, and pass the matrices yourself.

Or use the last SVN because I refactored the FPP a bit so we could use the same cam for the quad rendering, so now the globals are from the scene camera.

1 Like

Ah hell… might as well brain dump as a starter to the list…

All of these seem to be available: Grrrr the use of the word World >.<
[java]
uniform mat4 g_ProjectionMatrix;
uniform mat4 g_ProjectionMatrixInverse;
uniform mat3 g_NormalMatrix;
uniform mat3 g_NormalMatrixInverse;

uniform mat4 g_ViewMatrixt;
uniform mat4 g_ViewMatrixInverse;
uniform mat4 g_ViewProjectionMatrix;
uniform mat4 g_ViewProjectionMatrixInverse;

uniform mat4 g_WorldMatrix;
uniform mat4 g_WorldMatrixInverse;
uniform mat4 g_WorldProjectionMatrix;
uniform mat4 g_WorldProjectionMatrixInverse;

uniform mat4 g_WorldViewMatrix;
uniform mat4 g_WorldViewMatrixInverse;
uniform mat4 g_WorldViewProjectionMatrix;
uniform mat4 g_WorldViewProjectionMatrixInverse;

uniform vec2 g_Resolution;

uniform vec3 c_CameraPosition;
uniform vec3 c_CameraDirection;

float g_Time;
[/java]

All I can think of off the top of my head. Though I am sure there are plenty more.

What else do we have? And a general description for them would be great as well.

i.e. g_CameraDirection : A small description stating the obvious… including the fact that it is normalized. I’ve noticed people blindly re-normalize vectors often as a “just to be on the safe side” measure… not the best practice.

Oh… which reminds me… @nehon … this is from Parallax.glsl and should probably be removed, as it is an extra texture lookup that shouldn’t be there:

[java]
vec2 classicParallaxOffset(sampler2D parallaxMap, vec3 vViewDir,vec2 texCoord,float parallaxScale){
float h;
h = texture2D(parallaxMap, texCoord).a; // <<<<<<< THIS LINE HERE!!! REMOVE ME!
#ifdef NORMALMAP_PARALLAX
//parallax map is stored in the alpha channel of the normal map
h = texture2D(parallaxMap, texCoord).a;
#else
//parallax map is a texture
h = texture2D(parallaxMap, texCoord).r;
#endif
float heightScale = parallaxScale;
float heightBias = heightScale* -0.6;
vec3 normView = normalize(vViewDir);
h = (h * heightScale + heightBias) * normView.z;
return texCoord + (h * normView.xy);
}
[/java]

@nehon said: IMPORTANT :You're probably using a FilterPostProcessor for your deferred rendering. Note that if you are using 3.0 release, the Camera related globals are no the ones you expect to be. In 3.0 we were using another camera in parallel projection to render the full screen quad, so the globals are the ones from this cam...That's maybe the issue here. In that case you have to use classic material paramters, and pass the matrices yourself.

First… I want to kiss you! This is the issue… done and done. I’ll resolve this pronto.

Sorry for the name in the example… that was a #define in my shader to shorten the matrix names. Yes, it is g_ProjectionMatrixInverse

I just wanted to ensure that the examples I was looking was truly resolving to View Space and that they weren’t referring to a mixed projection matrix for resolving to world or model, etc, etc.

And thanks both of you for the pointer to the uniform binding info. I’ll start putting together a list for the docs as I go.

@t0neg0d said: Oh... which reminds me... @nehon ... this is from Parallax.glsl and should probably be removed, as it is an extra texture lookup that shouldn't be there:

[java]
vec2 classicParallaxOffset(sampler2D parallaxMap, vec3 vViewDir,vec2 texCoord,float parallaxScale){
float h;
h = texture2D(parallaxMap, texCoord).a; // <<<<<<< THIS LINE HERE!!! REMOVE ME!
#ifdef NORMALMAP_PARALLAX
//parallax map is stored in the alpha channel of the normal map
h = texture2D(parallaxMap, texCoord).a;
#else
//parallax map is a texture
h = texture2D(parallaxMap, texCoord).r;
#endif
float heightScale = parallaxScale;
float heightBias = heightScale* -0.6;
vec3 normView = normalize(vViewDir);
h = (h * heightScale + heightBias) * normView.z;
return texCoord + (h * normView.xy);
}
[/java]


Doh… You’re right. I’ll fix it.

@nehon
I appreciate the diagram using JME naming conventions. I understand the relationships between the different matrices… how to use them to convert between different spaces. However… I literally have to stop and think about it each time I use anything starting with g_World … It’s my issue… I need flash-cards or something >.<

Oh oh oh… right! I just caught it. Good god I am slow some(most)times. Nothing is prefixed with the starting point. Omg… lol… it makes complete sense now. Ya know how things just don’t click sometimes… this would be one of those… a very extended time period of one of those.

1 Like

@t0neg0d I’m breaking the no-resurrecting-old-posts rule, but did you get anywhere with this? I’m taking my third and hopefully final crack at deferred rendering and I was wondering if you had any tips or pointers for things along the way.