Sign in to follow this  
discman1028

Screen-aligned quad - Why?

Recommended Posts

Hi all, I am reading "Shaders for Game Programmers and Artists" (I'm the former), and I'm coming across the chapter of filtering (blur effects, etc). It says that one should render to a temporary texture, map the texture to a screen-aligned quad, and then one could use the pixel shader on it to do various effects. What I don't understand is, couldn't you just render to the normal render target, and still use the pixel shader subsequently to produce the same effect? Thanks for any explanation.

Share this post


Link to post
Share on other sites
rendering to a screen aligned quad gives you a 1-1 mapping from screen pixels to texture texels. This prevents sadness that you would get from doing it your proposed way.

Share this post


Link to post
Share on other sites
You can't generally use the backbuffer as a texture in a subsequent rendering pass. Thus, you have to have the render data in a texture to be able to use it in post-process. However, some games (Half-Life 2 comes to mind) render to the backbuffer, then copy the results to a texture that's the same size. That way, you still get any FSAA that may be turned on (since you cannot, at this time, create a render target texture with anti-aliasing).

Once you have this data as a texture, you can use it in a pixel shader. The full-screen quad is used as a method of getting the texels of the render texture to the correct spot on-screen. A pixel shader has to be run on geometry (you can't just arbitrarily run it on the screen), which is why you need the quad. And pixel shaders use textures as input, which is why you need a texture.

Hope that helps,

Josh

Share this post


Link to post
Share on other sites
Since your blur/bloom texture or whatever can be smaller in size, i find that using the stretch rect method (d3d) works well in this case. Just stretch your backbuffer to a smaller target, then do your blur methods using the smaller texture.. faster than blurring a big fullsize tex.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Use a screen filling triangle rather than a real quadrilateral (which would be split into two triangles). Modern hardware executes the pixel shader on pixel quads containing four pixels, So if you have two triangles filling the screen,the pixel shader is executed twice on the pixel-quads along the edge shared by the two triangles.

Share this post


Link to post
Share on other sites
A single triangle large enough to cover a (rectangular) screen will obviously be larger than the screen. Thus, it will be clipped. When clipped, it will be reduced to multiple triangles (probably two). Since clipping occurs prior to rasterization (and thus, prior to the execution of the pixel shader) this is basically pointless.

I don't really know what you're getting at with the pixel-quad thing. The shader runs per-fragment. Are you trying to suggest that a fragment is a four-pixel block and every four-pixel block gets the shader run once (and thus, gets a single color)? I find that hard to believe as it would effectively half the resolution of the render target since its basically pixel-doubling.

Share this post


Link to post
Share on other sites
The AP is correct, mostly. Rendering a big triangle that covers the screen will be slightly faster, but only because you're transforming one less vertex. Nvidia hardware, and recent ATI hardware, render quads natively so you don't get the 2x2 fragment overlap along the diagonal. On older hardware it can definitely happen, though.

One other thing to note is that Nvidia hardware does not clip triangles, but only scissors them. Thus, no extra vertices are created if you use a screen-filling triangle. I'm not sure what ATI hardware does with this nowadays.

Share this post


Link to post
Share on other sites
In any case this seems academic, because the bottleneck here is fragments, not vertices, you can render a giant quad made of 400 polys and you wont see any real difference. (unless of course you are rendering a large amount of quads).

That's why i suggested using Strechrect to shink down your backbuffer texture before applying you shaders, because thats the way to speed up your methods.

Plus, using a giant triangle to render a screen aligned texture is annoying becasue you have to calculate special texture coords.

Share this post


Link to post
Share on other sites
Quote:
Original post by Drilian
A pixel shader has to be run on geometry (you can't just arbitrarily run it on the screen), which is why you need the quad.


Thanks, that was what I was missing. :) I thought it ran on all pixels... which doesn't make sense.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by Eric Lengyel
Nvidia hardware, and recent ATI hardware, render quads natively so you don't get the 2x2 fragment overlap along the diagonal. On older hardware it can definitely happen, though.


Interesting! By quads do you mean the screen aligned quad or any quadrilateral primitive(which need not be planar) in general? Do you have any more details on how the rasterizer deals with a generic quadrilateral?

Thanks!

@jpetrie:
The fragment shader unit is typically an array of SIMD processors each of which operates on 2x2 fragment quad. The same program is run but the data is different for each fragment in the 2x2 block. Even if you render a single 1 pixel point on the screen, since its SIMD, the processing would be done on 4 fragments. But only the 1 fragment correspoding to the point will be used to update the framebuffer and the rest are discarded.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by discman1028
Actually... couldn't you potentially just combine all meshes into one (your "scene" mesh) and then use the pixel shader on that?


Typically a scene will have many kinds of objects with different materials. And each material would have its own pixel shader so you wouldn't want to combine all objects into a single mesh. The key thing here though is that the way blurs are typically done, they require the rendered image of the scene in which case the blur becomes a pure image processing filter requiring little knowledge of the geometry of the scene.

Share this post


Link to post
Share on other sites
Just felt like expanding. (helps me clear my thoughts) :P

The examples of filtering you mentioned fall into the category of image processing techniques. By the very nature of the term "image processing", you can't do any processing until you have an image to process.

During the normal render loop you are still part of the way through the final presentation of your scene into its rendered image representation, so although you could run the algorithms on the fragments generated during this stage, it would be inaccurate (due to missing image data still yet to tbe rendered) and wasteful as depending on your ordering of whats left to do pixels/fragments generated may overlap thus duplicating work and/or overwriting previous results.

Not to mention the fact that a lot of these algorithms require information from neighboring fragments or from fragments nowhere near the one currently being processed. Reading back data from a source you are currently rendering to as well, is troublesome to say the least (undefined or not supported in most, if not all cases).

Waiting until the image has been "finalized" ensures you have the image information desired in a form ready to be to be processed. The usage of a screen aligned quad allows you to cover the screen with fragments to be processed without the complexity of the geometric data you may have rendered to get to this point. This also separates your data into input and output sources to allow for proper access to the required information.

This ensuring of a 1:1 pixel mapping as others have put it, makes sure the entire set of data you intended gets processed once and only once for the algorithm you are trying to run and that it covers the area of the screen you intended. This is especially helpful when you have multiple image processing routines you need to run after the scene is done.

hth.

Share this post


Link to post
Share on other sites
Quote:

@jpetrie:
The fragment shader unit is typically an array of SIMD processors each of which operates on 2x2 fragment quad. The same program is run but the data is different for each fragment in the 2x2 block. Even if you render a single 1 pixel point on the screen, since its SIMD, the processing would be done on 4 fragments. But only the 1 fragment correspoding to the point will be used to update the framebuffer and the rest are discarded.


That's what I thought, but the way you phrased it originally (assuming you're the same AP) made it sound to me like the same program ran once, with one set of data, for four pixels, which would be very yucky.

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