Drawing FullScreen Quads with XNA 4.0


Quads are very important for numerous effects like all Image processing techniques (Bloom, Blur,Fog ….), Deferred Shading, Some particles system technics and others …..

In this short tutorial we will show how to draw a simple quad (and the theory behind it =P) using xna 4.0

If you dont want to know about the theory behind the quads, no problems =P, go to the code section directly.

Instead of showing how to create a Quad, i will talk about a specific case called FullScreenQuad, cause it is simpler and more easy to follow than the general case. (The concepts are the same in both case).

In simple words FullScreenQuad is just two triangles that fills the entire screen (imagine a rectangle in 2D that cover all the screen =P).

The importance of drawing FullScreen Quads is that we can run the pixel shader exactly once for each pixel of the render target (can be the back buffer or a texture). One example of this usefull property is the PostProcessing phase (or Image Process phase) where we recieve one quad and one texture as inputs, in GPU we change each texel of this texture and save the changes to the render target.

The magic is that the constructed quad will be perfect aligned to the screen borders (a rectangle covering all of it), when it is rasterized, the pixel shader will be called exactely once for each pixel of the screen, then you can access each corresponding texel of the associated texture, change it (process) and output  it in the render target in the same position it has in the original texture. (Remember that Render targets can be used as textures in another shader pass)

There are LOTS of ways of drawing fullscreen quads. We will use one that is simple and flexible enough =P (and can be used to draw arbitrary size quads, not only fullscreen).

Our choice is to create the vertices in CPU already in Projection Space and send them to a by-pass Vertex Shader.
In Projection space (after applying the world, view and projection matrix) , the borders of the screen (using the DirectX/XNA Projection matrix convention) are:  X: [-1,1], Y:[-1,1] and Z[0,1] (primitives which vertices is out of this range are clipped).  For example, a point with (-1,-1,0) will be in the down, left of you screen (The Z being 0 mean that it is VERY close to the camera). A point in (0,0,0) will appear in the midle of the screen. The following image shows the projection coordinates domain: (imagine the screen being the front square). Remember that we are in the normalized space, the rasterizator unit will convert it to the real screen coordinates (resolution dependent one)

DirectX Projection Coordinates space

So we will just create two triangles (to fill the quad) already in projection space, pass them to vertex shader, dont apply transformation (cause they are already in projection space) and send the vertices to the rasterization unit.

The vertice will contain the positions in Projection Space  and the Texture Coordinates. The up, left point of the quad will have the (0,0) texture coordinate and the lower, right will be (1,1).

The following code shows an easy way to do this in XNA 4.0:

internal sealed class QuadRender
    {
        private VertexPositionTexture[] verts;
        private GraphicsDevice myDevice;
        private short[] ib = null;

        ///
        /// Loads the quad.
        ///
        ///
The engine.
        public QuadRender(GraphicsDevice device)
        {

            myDevice = device;         

            verts = new VertexPositionTexture[]
                        {
                            new VertexPositionTexture(
                                new Vector3(0,0,0),
                                new Vector2(1,1)),
                            new VertexPositionTexture(
                                new Vector3(0,0,0),
                                new Vector2(0,1)),
                            new VertexPositionTexture(
                                new Vector3(0,0,0),
                                new Vector2(0,0)),
                            new VertexPositionTexture(
                                new Vector3(0,0,0),
                                new Vector2(1,0))
                        };

             ib = new short[] { 0, 1, 2, 2, 3, 0 };

        }             

        ///
        /// Draws the fullscreen quad.
        ///
        ///
The effect.
        public void RenderFullScreenQuad(Effect effect)
        {
            effect.CurrentTechnique.Passes[0].Apply();
            RenderQuad(Vector2.One * -1, Vector2.One);
        }

        public void RenderQuad(Vector2 v1, Vector2 v2)
        {          

            verts[0].Position.X = v2.X;
            verts[0].Position.Y = v1.Y;

            verts[1].Position.X = v1.X;
            verts[1].Position.Y = v1.Y;

            verts[2].Position.X = v1.X;
            verts[2].Position.Y = v2.Y;

            verts[3].Position.X = v2.X;
            verts[3].Position.Y = v2.Y;

            myDevice.DrawUserIndexedPrimitives
                (PrimitiveType.TriangleList, verts, 0, 4, ib, 0, 2);
        }
    }

If you dont want to draw a full screen quad, you can change the border values passed as function parameter

The Vertex Shader to process the FullScreen quad is:

texture colorMap;
sampler colorSampler = sampler_state
{
    Texture = (colorMap);
    AddressU = CLAMP;
    AddressV = CLAMP;
    MagFilter = LINEAR;
    MinFilter = LINEAR;
    Mipfilter = LINEAR;
};

struct VertexShaderInput
{
    float3 Position : POSITION0;
    float2 TexCoord : TEXCOORD0;
};

struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float2 TexCoord : TEXCOORD0_centroid;
};

float2 halfPixel;
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;
    input.Position.x =  input.Position.x - 2*halfPixel.x;
    input.Position.y =  input.Position.y + 2*halfPixel.y;
    output.Position = float4(input.Position,1);
    output.TexCoord = input.TexCoord ;
    return output;
}

 

XNA 4.0 works under DirectX9.0. In this environment, we have to make a “somehow strange correction” to the position of our vertices in the Vertex Shader (subtract the halfPixel size) when processing quads. The reason for this is the algorithm used in the rasterization unit (More info about this is Here).

The Pixel Shader is where you process the image. For this sample i just multiply each texel by 0.7f. (make them darker):

float4 PixelShaderFunctionNormal(VertexShaderOutput input) : COLOR0
{
	float4 process = tex2D(colorSampler,input.TexCoord);
        return process * 0.7f;
}

Its done =P quite simple. The PostProcess samples (the simple ones) are just “diferent” pixel shaders that process the recovered color in diferent ways.

 

, , ,

  1. #1 by japanese katana swords on 27 de setembro de 2016 - 12:46 pm

    A + + + + Merci

  2. #2 by real samurai swords on 27 de setembro de 2016 - 12:56 pm

    great item, fast shipping

  3. #3 by Fashion on 27 de setembro de 2016 - 1:24 pm

    There is definately a great deal to know about this topic. I really like all of the points you made.

  4. #4 by Mark on 27 de setembro de 2016 - 2:01 pm

    I do believe all of the ideas you’ve offered for your post. They are really convincing and will definitely work. Still, the posts are very quick for newbies. May just you please extend them a little from next time? Thank you for the post.

  5. #5 by Mark on 27 de setembro de 2016 - 2:24 pm

    Specifically where web can a certified psyciatrist submit content or sites for them to become fashionable?

  6. #6 by real katana on 27 de setembro de 2016 - 2:37 pm

    very fast shipping , and accurate description. Great seller.

  7. #7 by katanas for sale on 27 de setembro de 2016 - 2:37 pm

    Fast Shipping

  8. #8 by true katana on 27 de setembro de 2016 - 2:45 pm

    Very Fast Delivery!

  9. #9 by samurai katana for sale on 27 de setembro de 2016 - 2:59 pm

    Beautiful person and fast shipping

  10. #10 by palladium weissgold eheringe on 27 de setembro de 2016 - 3:17 pm

    Some really quality blog posts on this website , saved to my bookmarks.

  11. #11 by tactical wakizhasi on 27 de setembro de 2016 - 4:18 pm

    Great transaction and seller – fast delivery! Handshoe is beautiful! Thank you!

  12. #12 by Buy Tsukas on 27 de setembro de 2016 - 4:18 pm

    Thanks!

  13. #13 by authentic katana swords for sale on 27 de setembro de 2016 - 4:27 pm

    Great seller;item exactly as described;great communication; Thank you!

  14. #14 by real swords on 27 de setembro de 2016 - 4:47 pm

    This seller shipped my item faster than any other. Phenominal seller!

  15. #15 by jananese katana sword on 27 de setembro de 2016 - 4:47 pm

    Great transaction!!! Thanks.

  16. #16 by paid to drive on 27 de setembro de 2016 - 5:10 pm

    only two thousand from the initial yr involving the starting

  17. #17 by every week on 27 de setembro de 2016 - 5:21 pm

    Precisely what I was looking for, thankyou for posting.

  18. #18 by tanto blade on 27 de setembro de 2016 - 5:59 pm

    Very nice item.Fast shipping.Thanks

  19. #19 by apply permanent resident on 27 de setembro de 2016 - 6:19 pm

    Great post!

  20. #20 by kdf podatki rozliczenie podatku uk kalkulator on 27 de setembro de 2016 - 6:26 pm

    F*ckin’ remarkable things here. I’m very satisfied to look your post. Thank you so much and i am taking a look ahead to touch you. Will you kindly drop me a mail?

  21. #21 by Best real estate agent in South Pasadena on 27 de setembro de 2016 - 7:01 pm

    This particular blog is really entertaining and also amusing. I have chosen many interesting stuff out of it. I ad love to visit it every once in a while. Cheers!

  22. #22 by Best real estate agent in South Pasadena on 27 de setembro de 2016 - 7:13 pm

    Useful information. Fortunate me I found your site by accident, and I am shocked why this coincidence did not happened earlier! I bookmarked it.

  23. #23 by pr application on 27 de setembro de 2016 - 7:13 pm

    Great post!

  24. #24 by auf der Titelseite on 27 de setembro de 2016 - 9:36 pm

    Lebensjahr erreicht haben.

  25. #26 by Podnośnik Teleskopowy Wynajem Warszawa on 27 de setembro de 2016 - 11:43 pm

    Simply wanna state that this is very helpful , Thanks for taking your time to write this.

  26. #27 by yeezy boost 350 v2 on 28 de setembro de 2016 - 12:51 am

  27. #28 by 3d pictures in glass on 28 de setembro de 2016 - 4:52 am

    Very neat blog.Really thank you! Cool.

  28. #29 by anime on 28 de setembro de 2016 - 6:28 am

    Major thanks for the post. Great.

  29. #30 by naruto shippuden online hd on 28 de setembro de 2016 - 6:39 am

    Thanks again for the blog article. Cool.

  30. #31 by boo of ra on 28 de setembro de 2016 - 7:03 am

    we came across a cool internet site that you may possibly love. Take a appear should you want

  31. #32 by lowest price on 28 de setembro de 2016 - 7:14 am

    best marriage counselor in chicago

  32. #33 by best protein powder on 28 de setembro de 2016 - 8:05 am

    Major thankies for the blog.Much thanks again. Much obliged.

  33. #34 by Shandi Jasmann on 28 de setembro de 2016 - 8:21 am

    I am often to blogging and i genuinely appreciate your articles. The write-up has truly peaks my interest. My goal is to bookmark your website and sustain checking choosing details.

  34. #36 by Louis Vuitton Uhren on 28 de setembro de 2016 - 9:26 am

  35. #37 by extra resources on 28 de setembro de 2016 - 10:32 am

    marriage counselor lansing michigan

1 505 506 507
(não será publicado)