Can't get uv interpolation to work in a pixel shader

Started by
3 comments, last by unbird 13 years, 1 month ago
I'm trying to render some pre-transformed triangles to a texture, and the texture coordinates aren't interpolating for each pixel.

Here is the code for the vertices:

struct XYZTUV {float X, Y, Z, W, U, V;};
XYZTUV verts[] =
{
// x y z w u v
{0, 0, 0, 1, 0, 0},
{512, 0, 0, 1, 1, 0},
{512, 512, 0, 1, 1, 1},
{0, 512, 0, 1, 0, 1},
};


the vertex declaration:

const D3DVERTEXELEMENT9 xyztuvDecl[] =
{
{0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT, 0},
{0, 16, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
D3DDECL_END()
};


and the pixel shader

struct PS_INPUT
{
float2 uv : TEXCOORD0;
};

struct PS_OUTPUT
{
float4 Color : COLOR0;
};

PS_OUTPUT main( in PS_INPUT In ) : COLOR
{
PS_OUTPUT Out;

Out.Color = float4(In.uv.x, In.uv.y, 0, 1);

return Out;
}


I'm simply mapping the uv to the color's red and green channel. What I expect is a gradient of increasing red from left to right and increasing green from top to bottom, but only the second and fourth vertices' uv gets mapped (the second vertex of each triangle), like so

14t0a5g_th.jpg

All pixels in the top (first) triangle get the uv from the second vertex, and the bottom (second) triangle get the uv from the fourth vertex.

The texture coordinates get interpolated for non-pre-transformed vertices, so I tried to use vertices in [-1,1] and pass them through a vertex shader that simply copied them to the output, but then nothing gets rendered. Aren't vertices in [-1,1] after world/view/projection transformation?
Advertisement
If you are using a non indexed triangle list, 2 vertices has to be mentioned twice.
{0, 1, 2}, {2, 3, 0}

Vertice positions are independent of output resolution since the position interpolation from vertex to pixel shader convert from [-1..1] to pixel coordinates.
This is how my quad is defined using a non indexed triangle list with only positions.
VertexStructure_EffectQuad vertices[] = {
{ D3DXVECTOR3( -1.0f, 1.0f, 0.5f ) },
{ D3DXVECTOR3( 1.0f, 1.0f, 0.5f ) },
{ D3DXVECTOR3( -1.0f, -1.0f, 0.5f ) },
{ D3DXVECTOR3( 1.0f, 1.0f, 0.5f ) },
{ D3DXVECTOR3( 1.0f, -1.0f, 0.5f ) },
{ D3DXVECTOR3( -1.0f, -1.0f, 0.5f ) },
};
UV's are redundant for quads that are covering the whole screen.

If you are using a non indexed triangle list, 2 vertices has to be mentioned twice.
{0, 1, 2}, {2, 3, 0}


I was rendering them as a fan, tried rendering as a list, same result (triangles are rendered but uv's aren't interpolated.


Vertice positions are independent of output resolution since the position interpolation from vertex to pixel shader convert from [-1..1] to pixel coordinates.
This is how my quad is defined using a non indexed triangle list with only positions.
VertexStructure_EffectQuad vertices[] = {
{ D3DXVECTOR3( -1.0f, 1.0f, 0.5f ) },
{ D3DXVECTOR3( 1.0f, 1.0f, 0.5f ) },
{ D3DXVECTOR3( -1.0f, -1.0f, 0.5f ) },
{ D3DXVECTOR3( 1.0f, 1.0f, 0.5f ) },
{ D3DXVECTOR3( 1.0f, -1.0f, 0.5f ) },
{ D3DXVECTOR3( -1.0f, -1.0f, 0.5f ) },
};


Just tried this with untransformed vertices, still not getting anything.


UV's are redundant for quads that are covering the whole screen.


How so? You still need to pass uvs to tex2D in a pixel shader.

Edit: just to clarify, I'm having two separate problems:
1. When using pre-transformed vertices and D3DDECLUSAGE_POSITIONT, triangles are drawn but there is no uv interpolation across pixels.
2. When using non-pre-transformed vertices and D3DDECLUSAGE_POSITION, with vertices in [-1,1] and a vertex shader that simply copies the positions, nothing is drawn.
Well, after messing around with this for hours and missing a dentist's appointment, I finally figured this out. Deep in the dark recesses of the MSDN I found this gem:



Vertex Declarations with D3DDECLUSAGE_POSITIONT
.....
The stream offset must be DWORD aligned.
......
[/quote]

so I changed my declaration from


const D3DVERTEXELEMENT9 vertexInfo[] =
{
{0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT, 0},
{0, 16, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
D3DDECL_END()
};


to


const D3DVERTEXELEMENT9 vertexInfo[] =
{
{0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT, 0},
{0, 16, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
D3DDECL_END()
};


(changed the TEXCOORD from a float2 to float4)
Now it works as expected:

2vdmctx_th.jpg


I have no clue why, since a DWORD is 32 bits and float2 is dword aligned, but when I change it back, it no longer works.
This is really strange. Looks like some flat shading effect. I suspect you did something wrong in your setup. Check (or post) your relevant drawing code (render states, declaration and stream setup, draw call, effect or raw shader usage). Check if the DX debug runtime have something to claim about.

2. When using non-pre-transformed vertices and D3DDECLUSAGE_POSITION, with vertices in [-1,1] and a vertex shader that simply copies the positions, nothing is drawn.[/quote]
If you haven't set any vertex shader of your own, the fixed function transformation will be used, i.e. the device's SetTransform. Set them all to identity, maybe you get something then.

Edit: Ninja-ed. Wow, did not know about this. Thanks.

I have no clue why, since a DWORD is 32 bits and float2 is dword aligned,...[/quote]
Edit2: True, I think there must be something else going on, I just checked with your original vertex and I got a fine result.

This topic is closed to new replies.

Advertisement