Full Screen Quad for Post Processing Effects

Started by
7 comments, last by AndyTX 16 years, 11 months ago
Hey all, Thanks to all the help I've gotten on this forum; I've almost got my first post-process effect up and running. Well, it actually runs in the world right now, however it appears my camera translations are being applied to the quad as the quad is only viewable from certain angles in the world. I think I'm a bit confused on how I go about making this full screen quad not have the camera translations/rotations applied to it. I've tried creating a LH Ortho matrix and passing that into the shader (the vertex shader on the post process effect does a basic clip space transformation), but that doesn't seem to help. Shader code:

OUT.HPosition = mul(float4(IN.Position, 1.0f), matrixWVP);

Really basic so I assume I'm just passing in the wrong matrix before I do the technique. I tried just View * Projection (since this object doesn't need a world matrix) but that didn't help. Any suggestions?
Advertisement
Just pass the viewport coords right through the vertex shader to the pixel shader. There is no need to multiply in the WVP matrix, as you are working in viewport space -1.f to 1.f for DX, not world space.

OUT.HPosition = IN.Position;
Quote:Original post by lubby
Just pass the viewport coords right through the vertex shader to the pixel shader. There is no need to multiply in the WVP matrix, as you are working in viewport space -1.f to 1.f for DX, not world space.

OUT.HPosition = IN.Position;


Yea, I tried that before.

OUT.HPosition = float4(IN.Position, 1.0f);

But that doesn't produce any results.

Here is the code where I actually create the quad (pretty small):

     typedef struct    {        FLOAT       p[3];        FLOAT       tu, tv;        FLOAT       cs, ct;    } TVVERTEX;    TVVERTEX Vertex[4] =     {        //   x y  z tu tv  cu cv        {  0,  0, 0, 0, 0, 0, 0,},        {640,  0, 0, 1, 0, 1, 0,},        {640,480, 0, 1, 1, 1, 1,},        { 0 ,480, 0, 0, 1, 0, 1,},    };    // Set the Effects Parameters    D3DXMATRIX ortho;    D3DXMatrixOrthoLH(&ortho, 640, 480, 100.0f, 10000.0f);    D3DXMATRIX final = ortho * Projection;    m_pEffect->SetMatrix(m_WVP, &final);    m_movementPos += 0.5f * m_deltaTime;    if(m_movementPos > 1.0f)        m_movementPos -= 1.0f;        m_pEffect->SetFloat(m_ScratchPos, m_movementPos);    m_pEffect->SetFloat(m_CenterS, (1.0f/2.0f));    m_pEffect->SetFloat(m_CenterT, (1.0f/2.0f));        m_pEffect->SetFloat(m_ElapsedTime, m_deltaTime);    m_pEffect->SetTexture(m_SceneTextureHandle, m_SceneTexture);    m_pEffect->SetTexture(m_BlipTextureHandle, m_BlipTexture);    m_pEffect->SetTexture(m_ScratchTextureHandle, m_ScratchTexture);    // End Effects Parameters    m_pDevice->SetFVF(D3DFVF_XYZ | D3DFVF_TEX0 | D3DFVF_TEX1);    // Technique Begin    SetTechnique();    Begin();    m_pDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, Vertex, sizeof(TVVERTEX));    // Technique End    End();
Bah I think I got it now guys. Changed my Quad to only use values -1 to 1 and fixed a few other things with regard to the viewport.

Thanks anyway for the suggestions.
Note that it's actually ever-so-slightly faster to render a single large triangle that covers the whole screen. i.e.
(-1, -1) -> (2, -1) -> (-1, 2)

That avoids rasterizing the diagonal line of the quad twice, and actually avoid a single vertex transform as well (although the latter is pretty insignificant).
Quote:Original post by AndyTX
Note that it's actually ever-so-slightly faster to render a single large triangle that covers the whole screen.

Are you sure about this? Now I know we're talking immeasurably small differences here, but I figured that clipping several thousand pixels would cost more than transforming a second triangle. Or is that not how the rasteriser works? Does anyone have some light to shed?

Edit: I just found that last sentence about the diagonal. I think I believe now. Still, I'd like to know if it would take any longer to rasterise a huge triangle compared to smaller one, provided they both fill the screen.

Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.
Quote:Original post by TheAdmiral
Edit: I just found that last sentence about the diagonal. I think I believe now. Still, I'd like to know if it would take any longer to rasterise a huge triangle compared to smaller one, provided they both fill the screen.

Yeah the transform cost is minimal (if it matters at all). The real difference is that the quads along the diagonal will be rasterized twice which can make a difference for complex shaders (or small render targets).

Also in my experience clipping is effectively "free", in that its cost is not variance depending on the input or output size (it is a fixed, cheap, cost).

If the the full-screen quad is textured with a large texture, you may be better off using smaller triangles in long vertical strips for better texture cache coherence. This is quite significant on some consoles, and even the PC.
Also, if you know the triangle will be within the device's guardband you can turn off clipping completely which may help get an extra microsecond or two :-)
Quote:Original post by Rompa
If the the full-screen quad is textured with a large texture, you may be better off using smaller triangles in long vertical strips for better texture cache coherence.

That's certainly true on the G70 which had a kind of irregular rasterization pattern (i.e. long horizontal strips), but that hasn't seemed to be the case for me with G80. Note that this trick is also helpful for dynamic branching coherence on G70, although again it seems to make no difference on G80.

I'd be interested if someone could confirm the rasterization orderings on various architectures though.

This topic is closed to new replies.

Advertisement