SSAO and Deferred Shadow Mapping in Xen?

Sep 21, 2012 at 1:03 PM

I read that before StatusUnknown stopped working on Xen, he was working on a fully integrated Deferred rendering system from Xen, but that it was lost.

I was wondering if anyone has got deferred rendering into xen correctly? I'm more a gameplay programmer than a graphics one, so I'm having some trouble in doing so. I'd really like to get 3 things into my game. Any recommendations on libraries to use that would work well with xen?

1. SSAO
2. Sunlight softshadows
3. Colored point lights (no shadows) 

Developer
Sep 21, 2012 at 7:17 PM

We have our own custom implementation of all of those items, but I cannot really extract any of them and post them here, though I can suggest some sources for you to check out and "port over" from vanilla XNA to Xen.

For deferred rendering, check out this post which deals with deferred rendering (which would cover your 3rd item):

http://www.catalinzima.com/2010/12/xna-4-0-version-of-the-deferred-rendering-code/

 

For SSAO, you pretty much need deferred rendering because the SSAO post-fx relies on the gbuffer channels to generate the SSAO buffer. I'd suggest you check this solution out which you could port over to be an XNA/Xen shader:

http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/a-simple-and-practical-approach-to-ssao-r2753

I realize porting them might not be straight forward, but I think, if you are hoping to get these relatively advanced graphics features in your title, then you'd have to take the time to understand what they are doing in the first place.

For sunlight shadows, I'd suggest you check this XNA project out (download the DeferredCascadedShadowMaps zip):

https://skydrive.live.com/?cid=538e432ea49f5bde&id=538E432EA49F5BDE%21125

Hope it helps.

Sep 22, 2012 at 3:07 AM

Thanks for the links, I'll have to go more in depth again. I actually was working on a deferred renderer before I decided to use Xen and almost had parts of it working. While I understand most of the theory behind it, I haven't really wrapped my mind around how to get the whole thing plugged in to all the rendering, instancing and particles (rather, keep the particles working). And now especially with the Xen shaders and it's way of drawing, looking at other examples makes me a bit dizzy.

I'll have to give this some serious time and start fresh to get it into Xen. I'll post back again with progress I guess :)

One question. I read that when using deferred rendering, you need to render everything in one shader by design. Is this how you do it? How would I build a shader that renders terrain, skyboxes but also characters, models and instances all in one? Especially since my instances use custom data and my terrain shader takes multiple samplers and models are loaded from fbx files.

Developer
Sep 22, 2012 at 3:32 AM

About rendering everything using the same shader, that's only one part of the story.

The idea is that you use whatever shader you want to render into the gbuffer where you figure out the albedo, normals, specular highlight strength, depth etc. 

Then you use a single shader that uses the gbuffer render targets as the source data for each deferred light you render onto the screen. For the sunlight, since it covers the who screen, unless you have enclosed areas, you could do that as a full screen quad (much like a post-fx).

Sep 30, 2012 at 2:56 PM

Yeah I wish I had a much better understanding of rendering overall, as I'm much more a gameplay & tool programmer than other things, but I'm learning as I go.

I've been looking a lot at a Light-Pre-Pass renderer I found here: http://jcoluna.wordpress.com/ and trying to integrate similar techniques myself. It has quite readable code and seams to work well, and has it's advantages over a deferred renderer.

I'm getting stuck on how Xen requires a FrameState to draw a drawtarget, when some ssao and postfx methods require nesting of the rendertarget drawing.

For example, this is his pre-calculations for the SSAO, how would I rework such a method in Xen design?

        public void ComputeSSAO(Renderer renderer, GraphicsDevice device)
        {
            RenderTarget2D depthBuffer = renderer.GetDownsampledDepth();
            RenderTarget2D normalBuffer = renderer.NormalBuffer;
            RenderTarget2D half0 = renderer.HalfBuffer0;
            RenderTarget2D half1 = renderer.HalfBuffer1;

            //render to a half-res buffer
            device.SetRenderTarget(half0);
            device.Clear(Color.Black);

            _effect.CurrentTechnique = _effect.Techniques[0];
            _parameterDepthBuffer.SetValue(depthBuffer);
            _parameterNormalBuffer.SetValue(normalBuffer);
            _parameterRandomMap.SetValue(_randomTex);
            _parameterRandomTile.SetValue(_randomTile);
            _parameterRadius.SetValue(new Vector2(_radius, _maxRadius));
            _parameterBias.SetValue(_bias);

            _parameterHalfBufferHalfPixel.SetValue(new Vector2(0.5f / depthBuffer.Width, 0.5f / depthBuffer.Height));
            _parameteGBufferHalfPixel.SetValue(new Vector2(0.5f / normalBuffer.Width, 0.5f / normalBuffer.Height));

            _parameterFarClip.SetValue(renderer.CurrentCamera.FarClip);
       
            _effect.CurrentTechnique.Passes[0].Apply();

            device.RasterizerState = RasterizerState.CullNone;
            device.BlendState = BlendState.Opaque;
            device.DepthStencilState = DepthStencilState.None;
            

            _quadRenderer.RenderQuad(device, -Vector2.One, Vector2.One);

            if (_blurCount > 0)
            {
                Vector2 tempBufferRes = new Vector2(half1.Width, half1.Height);
                _parameterTempBufferRes.SetValue(tempBufferRes);
                _effect.CurrentTechnique = _effect.Techniques[1];
                device.BlendState = BlendState.Opaque;
                device.DepthStencilState = DepthStencilState.None;
                for (int i = 0; i < _blurCount; i++)
                {
                    device.SetRenderTarget(half1);
                    device.Clear(Color.Black);
                    _parameterSSAOBuffer.SetValue(half0);
                    _parameterBlurDirection.SetValue(Vector2.UnitX / half1.Width);
                    _effect.Techniques[1].Passes[0].Apply();
                    _quadRenderer.RenderQuad(device, -Vector2.One, Vector2.One);


                    device.SetRenderTarget(half0);
                    device.Clear(Color.Black);
                    _parameterSSAOBuffer.SetValue(half1);
                    _parameterBlurDirection.SetValue(Vector2.UnitY / half1.Height);
                    _effect.Techniques[1].Passes[0].Apply();
                    _quadRenderer.RenderQuad(device, -Vector2.One, Vector2.One);
                }
            }

            device.DepthStencilState = DepthStencilState.None;
          
            device.BlendState = BlendState.Opaque;

        }

Also, I'm uncertain on a few renderstate things.

Does "device.DepthStencilState = DepthStencilState.None" translate to "state.RenderState.CurrentStencilState.Enabled = false;"?

and does "device.BlendState = BlendState.Opaque;" translate to "state.RenderState.CurrentBlendState.SetToNoBlending();" or "state.RenderState.CurrentBlendState.Enabled = false;"?

Also I'd like to give a huge thanks for all the help so far Abuzer! Haven't properly thanked you for your extensive replies in the custom instancing & dynamic mesh threads yet since I'm still trying to get them all to work properly. I have limited time, and when I get stuck I move a bit between which parts I'm working on and thus don't really have anything concrete to ask/show yet. I'll post when I get it working though. And good luck with your kickstarter! :)