0
\$\begingroup\$

I'm using directx 9 and vertex shaders to rasterize triangles...I have vertex shader input structs like this:

struct VS_INPUT_Quad
{
   float4 Position : POSITION;
   float2 UV : TEXCOORD0;
};

and pixel shader input structs like this:

struct PS_INPUT_Quad
{
   float4 Position : POSITION;
   float4 Pos2 : TEXCOORD0;
   float2 UV : TEXCOORD1;
};

Here is vertex shader:

    PS_INPUT_Quad SkyboxVisibilityPass_Vertex_Shader( VS_INPUT_Quad Input )
    {
        PS_INPUT_Quad Output = ( PS_INPUT_Quad )0;

// projected vertex position
        Output.Position = mul( Input.Position, mWVP );

// normalized device coordinates of the vertex
        Output.Pos2 = Output.Position / Output.Position.w;
        Output.Pos2.xy *= float2( 0.5, -0.5 );
        Output.Pos2.xy += float2( 0.5, 0.5 );

// prop uv coordinates
        Output.UV = Input.UV;

        return( Output );   
    }

Here is pixel shader( simply returns a color from a texture ):

    float4 SkyboxVisibilityPass_Pixel_Shader( PS_INPUT_Quad Input ) : COLOR0
    { 
        return tex2D( g_SamplerMultiplier, Input.Pos2.xy );
    }

I'm finding that the Pos2 value sent to the pixel shader is incorrect. Am I incorrectly converting projected vertex position coordinates to normalized device coordinates? PIX says that values are well above 1 when dubugging the pixel shader, however, the output looks correct when looking at the 'mesh' tab while hiliting the draw call...

Here is debug output for a single pixel whose position lies within the clip space:

   //
// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
//
// Parameters:
//
//   sampler2D g_SamplerMultiplier;
//
//
// Registers:
//
//   Name                Reg   Size
//   ------------------- ----- ----
//   g_SamplerMultiplier s0       1
//

    ps_2_0
    dcl t0.xy  // Input<4,5>
    dcl_2d s0
    texld r0, t0, s0  // ::SkyboxVisibilityPass_Pixel_Shader<0,1,2,3>
    mov oC0, r0  // ::SkyboxVisibilityPass_Pixel_Shader<0,1,2,3>

// approximately 2 instruction slots used (1 texture, 1 arithmetic)

Registers:
    oC0 (0.435, 0.435, 0.435, 1.000)    float4
r0  (0.435, 0.435, 0.435, 1.000)    float4
s0      float4
t0  (11.871, 8.631, 0.000, 0.000)   float4

As you can see above, t0 is the Pos2 coordinates that i use to sample the texture...they are well above 1 ... the vertex they belong to is visible so this pixel should have valid normalized device coordinates. Are the coordinates being altered after leaving the vertex shader and arriving at the pixel shader?

\$\endgroup\$
2
\$\begingroup\$

You should do Output.Pos2 = Output.Position in the vertex shader, then in the pixel shader:

float2 screenPos;
        screenPos.x = Input.pos2D.x/Input.pos2D.w/2.0f + 0.5f;
        screenPos.y = -Input.pos2D.y/Input.pos2D.w/2.0f + 0.5f;

To get correct screen space coordinates you have to do your w divide in the pixel shader. After that your return should function correctly:

return tex2D( g_SamplerMultiplier, screenPos );

I hope I could help you.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ that works ... but why can't I perform this operation in the vertex shader? Is a transformation made during interpolation? \$\endgroup\$ – P. Avery Mar 14 '14 at 0:28
  • \$\begingroup\$ Eww I am ashamed a bit but couldn't yet get my head around the math about that w divide yet, sorry. :) It has got something to do with the barycentric interpolation from the rasterizer. \$\endgroup\$ – János Turánszki Mar 14 '14 at 0:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.