Deferred Rendering (light + parallax + shadows + ssao + fog + bloom + fxaa)

@haze said: Hi,

Any updates @t0neg0d ? I’m really interested in this. Can you explain how you set up your system please…i plan to work on shadows in my game and i will make my own shadow filter so i want to know if you always use it or if you have done some things internally and that’s a waste of time to do it now ^^.

Thanks.

Nothing new atm… two other projects that I’m desperately trying to finish:

  1. Particle System - this is finally almost complete - and will come with an FXBuilder utility that allows you completely setup multiple Emitters and visually customize everything from the emitter shape (including loading and animating them as assets) to choosing custom material (blend mode, texture, etc) to visually setting and altering the influencers.

  2. tonegodGUI - I have so much to do on this, but it’s difficult to ramp back up on. I’m almost at a point where I’m comfortable implementing what needs to be fixed/changed.

Then I’ll be able to revisit this and getting it squared away.

1 Like

Ok, cool. Nice feature to come :).

And for the setup question?

@haze

  • First depth is rendered from the scenes perspective,
  • Next, ssao map is created.
  • Lights are not JME Lights… they’re just a bit of info like position, direction, etc.
  • For shadow mapping, the depth is rendered from the lights perspective (directional = 1 direction no perpsective, point = 6 directions perspective, spot = 1 direction perspective.
  • These are compiled and blended in one pass
  • The initial render of geometries is broken into multiple output textures - normal, normal + normal map, specular, diffuse, etc
  • The lighting is a single pass that is handed all lights, the final shadow map and each of the above maps from the geometry pass.
  • The final output is compiled for the lighting and the diffuse output is blended back into the shadow map.
  • These are all mixed together on the way out…

And that’s pretty much all that is involved.

EDIT: It’s also note worthy to say that there is a only a single shadow cam, each light stores it’s own depth buffer and the buffer size and camera update can be altered based on priority. So, each pass it cycles through the lights, updates the shadow cam and output buffer, renders that light and moves to the next. The only output from this is an updated depth map from that lights perspective.

@t0neg0d said: @haze
  • First depth is rendered from the scenes perspective,
  • Next, ssao map is created.
  • Lights are not JME Lights… they’re just a bit of info like position, direction, etc.
  • For shadow mapping, the depth is rendered from the lights perspective (directional = 1 direction no perpsective, point = 6 directions perspective, spot = 1 direction perspective.
  • These are compiled and blended in one pass
  • The initial render of geometries is broken into multiple output textures - normal, normal + normal map, specular, diffuse, etc
  • The lighting is a single pass that is handed all lights, the final shadow map and each of the above maps from the geometry pass.
  • The final output is compiled for the lighting and the diffuse output is blended back into the shadow map.
  • These are all mixed together on the way out…

And that’s pretty much all that is involved.

EDIT: It’s also note worthy to say that there is a only a single shadow cam, each light stores it’s own depth buffer and the buffer size and camera update can be altered based on priority. So, each pass it cycles through the lights, updates the shadow cam and output buffer, renders that light and moves to the next. The only output from this is an updated depth map from that lights perspective.

Ok, thanks for the explanations… can’t wait to test it :).
So no jme lights, need to manually setup them (no sdk). The shadows filter is not the one currently provided…i’ll wait for lighting work ;).

@haze said: Ok, thanks for the explanations... can't wait to test it :). So no jme lights, need to manually setup them (no sdk). The shadows filter is not the one currently provided...i'll wait for lighting work ;).

The lights are created and added the same way JME lights are.
You still define shadows modes the same as well.

Ow great <3.

That’s really nice looking, good job.

Would you mind explaining what method you used for the SSAO? I’m currently trying to write my own because the built in jME one is a little OP for my needs. I saw an article on creating it from the depth buffer, but I wanted to know what you would think would be best.

Thanks.

Edit:
Are there any runnable demos or code we can look at yet?

@Slyth said: That's really nice looking, good job.

Would you mind explaining what method you used for the SSAO? I’m currently trying to write my own because the built in jME one is a little OP for my needs. I saw an article on creating it from the depth buffer, but I wanted to know what you would think would be best.

Thanks.

Edit:
Are there any runnable demos or code we can look at yet?

I posted the code here someplace for an alternative SSAO filter for JME… let me try and find it. (EDIT: The SSAO code that is)

Well… crap. I never added this as a plugin, because plugins broke right after posting this thread. You can have a look at the vid and see if this is more to your liking. The moment they get plugins working again (for contributors) I’ll post it out there.

SSAO Filter Vid

Are you using some kind of public VCS? Even if you haven’t cleaned up the code i would really like to give it a look. Especially how the filter chain is setup and of course the lighting calculations you used…

Very impressive at a first look. But i am not sure if you got the shadowing right, at least from your descriptions…

@t0neg0d said: I posted the code here someplace for an alternative SSAO filter for JME... let me try and find it. (EDIT: The SSAO code that is)

Well… crap. I never added this as a plugin, because plugins broke right after posting this thread. You can have a look at the vid and see if this is more to your liking. The moment they get plugins working again (for contributors) I’ll post it out there.

SSAO Filter Vid

Thanks for showing me the vid, it looks like a nice implementation. Good luck on your deferred renderer, and I hope to see that plugin soon!

@Slyth said: Thanks for showing me the vid, it looks like a nice implementation. Good luck on your deferred renderer, and I hope to see that plugin soon!

I’ll try and post this to the forum sometime today…

@t0neg0d said: I'll try and post this to the forum sometime today...

Hey @t0neg0d – any update on your awesome work? I’m researching technology for future projects & what you have here looks very good… can you please share the plugin or this demo code? I’ll take ugly code too :stuck_out_tongue:

1 Like

I second that :stuck_out_tongue:

1 Like

I think we are all waiting for this amazing improvement with lighting ^^ …but Chris is a bit busy with all her projects x)

Once I finished up my new BitmapText replacement, I’ll package this up and make it available for download.

Some notes about what you’ll need to change:

  • Don’t expect that the shadow renderer will just be usable. It was a quick throw together to test the idea and likely will have issues (think of it as a template for how to potentially alter @nehon 's awesome shadow renderers to work with deferred renderering.
  • I’d personally want to replace the SSAO filter with the one I wrote before, but never ported it to work with this. You’ll likely want to use your own.

The only thing I ask is, if you come up with something cool based on this, is you share it for everyone else to benefit from as well!

Soooo… gimma a couple weeks tops… I’ll zip this up… finally zip up that SSAO filter that kicks booty and maybe someone else can get that working with this as well.

4 Likes
@t0neg0d said: Once I finished up my new BitmapText replacement, I'll package this up and make it available for download.

Some notes about what you’ll need to change:

  • Don’t expect that the shadow renderer will just be usable. It was a quick throw together to test the idea and likely will have issues (think of it as a template for how to potentially alter @nehon 's awesome shadow renderers to work with deferred renderering.
  • I’d personally want to replace the SSAO filter with the one I wrote before, but never ported it to work with this. You’ll likely want to use your own.

The only thing I ask is, if you come up with something cool based on this, is you share it for everyone else to benefit from as well!

Soooo… gimma a couple weeks tops… I’ll zip this up… finally zip up that SSAO filter that kicks booty and maybe someone else can get that working with this as well.

Thank you for the update.

Where are @nehon’s awesome shadow renderers? :slight_smile:

I believe I used your SSAO filter for 3089. I made some modifications to it to improve performance that I wanted to share. I commented out a ton of stuff that I wasn’t using to save “if” branches. I believe you had an “if” branch inside a loop, which killed performance. Make sure you are using #ifdef instead of “if” branches. Here is how my SSAO filter looked:

[java]uniform vec2 g_Resolution;
uniform vec2 m_FrustumNearFar;
uniform sampler2D m_Texture;
uniform sampler2D m_Normals;
uniform sampler2D m_Noise;
uniform sampler2D m_DepthTexture;
uniform vec3 m_FrustumCorner;
uniform float m_SampleRadius;
uniform float m_Intensity;
uniform float m_Scale;
uniform float m_Bias;
//uniform bool m_EnableFD;
//uniform float m_SampleRadiusFD;
//uniform float m_IntensityFD;
//uniform float m_ScaleFD;
//uniform float m_BiasFD;
uniform vec3 m_Samples[12];

//uniform bool m_UseDistanceFalloff;
//uniform float m_FalloffStartDistance;
//uniform float m_FalloffRate;

varying vec2 texCoord;

//float depthv;
float shadowFactor;

vec3 getPosition(in vec2 uv){
//depthv = texture2D(m_DepthTexture,uv).r;
float depth= (2.0 * m_FrustumNearFar.x) / (m_FrustumNearFar.y + m_FrustumNearFar.x - texture2D(m_DepthTexture,uv).r * (m_FrustumNearFar.y-m_FrustumNearFar.x));
float x = mix(-m_FrustumCorner.x, m_FrustumCorner.x, uv.x);
float y = mix(-m_FrustumCorner.y, m_FrustumCorner.y, uv.y);
return depth* vec3(x, y, m_FrustumCorner.z);
}

vec3 getNormal(in vec2 uv){
return normalize(texture2D(m_Normals, uv).xyz * 2.0 - 1.0);
}

vec3 getRandom(in vec2 uv){
float rand=(fract(uv.x*(g_Resolution.x/2.0))0.25)+(fract(uv.y(g_Resolution.y/2.0))*0.5);
return normalize(vec3(rand,rand,rand));
}

vec3 getNoise(in vec2 uv){
vec4 noise = texture2D(m_Noise, uv*25.0);
return (noise.xyz);
}

float doAmbientOcclusion(in vec2 tc, in vec3 pos, in vec3 norm){
vec3 diff = getPosition(tc)- pos;
vec3 v = normalize(diff);
float d = length(diff) * m_Scale;
return step(0.00002,d)*max(0.0, dot(norm, v) - m_Bias) * ( 1.0/(1.0 + d) ) * (m_Intensity+shadowFactor) * smoothstep(0.00002,0.0027,d);
}

vec3 reflection(in vec3 v1,in vec3 v2){
vec3 result= 2.0 * dot(v2, v1) * v2;
result=v1-result;
return result;
}

/*float doAmbientOcclusionFD(in vec2 tc, in vec3 pos, in vec3 norm){
vec3 diff = getPosition(tc)- pos;
vec3 v = normalize(diff);
float d = length(diff) * m_ScaleFD;
return step(0.00002,d)max(0.0, dot(norm, v) - m_BiasFD) * ( 1.0/(1.0 + d) ) * (m_IntensityFD+shadowFactor) * smoothstep(0.00002,0.0027,d);
}
/

void main(){
float result;
vec3 position = getPosition(texCoord);
//if(depthv==1.0){
// gl_FragColor=vec4(1.0);
// return;
//}
vec3 normal = getNormal(texCoord);
vec3 rand = getRandom(texCoord);

float ao = 0.0;
shadowFactor = 0.075;//0.0;//(position.z*0.002);
float rad = m_SampleRadius/position.z+shadowFactor;
//float radFD = m_SampleRadiusFD/position.z+shadowFactor;

//int iterations = 12;
/*if (m_UseDistanceFalloff) {
    float LOG2 = 1.442695;
    vec2 m_DistanceFrustum = vec2(1.0,m_FalloffStartDistance);
    float depth= (m_DistanceFrustum.x / 4.0) / (m_DistanceFrustum.y - depthv * (m_DistanceFrustum.y));

    float falloffFactor = exp2( -m_FalloffRate * m_FalloffRate * depth *  depth * LOG2 );
    falloffFactor = clamp(falloffFactor, 0.0, 1.0);

    if (falloffFactor &lt; 1.0) {
        for (int j = 0; j &lt; iterations; ++j) {
            vec3 coord1 = reflection(vec3(m_Samples[j]), rand) * vec3(rad);
            ao += doAmbientOcclusion(texCoord + coord1.xy * 0.125, position, normal) - shadowFactor;
            // Fine Detail
            //if (m_EnableFD) {
            //vec3 coord2 = reflection(vec3(m_Samples[j]), rand) * vec3(radFD*0.5);
            //ao += doAmbientOcclusionFD(texCoord + coord2.xy * 0.05, position, normal) * (0.25-shadowFactor);
            //}
        }
        ao /= float(iterations) * (2.35-shadowFactor);
        result = 1.0-ao;
        result = mix(result,1.0,1.0-falloffFactor);
    } else {
        result = 1.0;
    }
} else {*/
    //vec3 rad3 = vec3(rad);
    vec3 sampler;
    vec2 coord1;
    for (int j = 0; j &lt; 12; ++j) { // 12 iterations
        sampler = m_Samples[j];
        float math = 2.0 * (rand.x*sampler.x + rand.y*sampler.y + rand.z*sampler.z);
        coord1.xy = (sampler.xy - (math * rand.xy)) * rad;
        ao += doAmbientOcclusion(texCoord + coord1.xy * 0.125, position, normal) - shadowFactor;
    }
    ao /= 12.0 * (2.35-shadowFactor); // 12.0 iterations
    result = 1.0-ao;
//}

//gl_FragColor = vec4(vec3(result),1.0);
gl_FragColor = vec4(result, result, result, 1.0);

}
[/java]

2 Likes

Nice, cant wait to put a few hundred lights on the scene :slight_smile:

@zzuegg said: Nice, cant wait to put a few hundred lights on the scene :)

Me neither! IMHO that’s like one of the only things really lacking in the 3.0 SDK.


Also, I know this is totally unrelated but I have to ask: why are some people calling Chris a SHE? O.o Not getting it :stuck_out_tongue:

Hell yeah :slight_smile: I might actually be able to start lighting then

I would actually be really curious about the progress on your project Empire…

Sorry for OT chris