Passing vertex coordinates to the pixel shader (2.0)

Started by
10 comments, last by Jason Z 19 years, 3 months ago
Hi all, I've been trying to pass the vertex coordinates to my pixel shader by wrapping them in a TEXCOORD1 parameter, but that doesn't seem to work. float4x4 matViewProjection; struct VS_OUTPUT { float4 Pos: POSITION; float2 Stage: TEXCOORD1; }; VS_OUTPUT vs_main( float4 inPos: POSITION ) { VS_OUTPUT Out; Out.Pos = mul(matViewProjection, inPos); Out.Stage.x = 2 / (inPos.x % 8); Out.Stage.y = 2 / (inPos.y % 12); return Out; } float4 ps_main( float4 inDiffuse: COLOR0, float4 Tex1: TEXCOORD1 ) : COLOR0 { // Output constant color: float4 color = 0; int temp = 2 / Tex1.x; color.r = temp * 0.1; return color; } Instead of an output with a lot of gradients I only get an image that is half black half gradiented, but no repeating gradient. Is there anybody who can help me with my problem? Thanks in advance!
Advertisement
Quote:
float4x4 matViewProjection;

struct VS_OUTPUT
{
float4 Pos: POSITION;
float2 Stage: TEXCOORD1;
};

VS_OUTPUT vs_main( float4 inPos: POSITION )
{
VS_OUTPUT Out;

Out.Pos = mul(matViewProjection, inPos);

Out.Stage.x = 2 / (inPos.x % 8);
Out.Stage.y = 2 / (inPos.y % 12);

return Out;
}

float4 ps_main( float4 inDiffuse: COLOR0, float4 Tex1: TEXCOORD1 ) : COLOR0
{
// Output constant color:
float4 color = 0;

int temp = 2 / Tex1.x;

color.r = temp * 0.1;

return color;
}


You have to pass the texcoords into the vertex shader, then pass them on to the pixel shader:

float4x4 matViewProjection;struct VS_OUTPUT {   float4 Pos:     POSITION;   float2 Stage:   TEXCOORD0;};VS_OUTPUT vs_main( float4 inPos: POSITION, float4 inTex: TEXCOORD0 ){   VS_OUTPUT Out;   Out.Pos = mul(matViewProjection, inPos);   Out.Stage.x = 2 / (inPos.x % 8);   Out.Stage.y = 2 / (inPos.y % 12);      return Out;}float4 ps_main( float4 inDiffuse: COLOR0, float4 Tex1: TEXCOORD0 ) : COLOR0{   //  Output constant color:   float4 color = 0;        int temp = 2 / Tex1.x;      color.r = temp * 0.1;      return color;}


Otherwise you don't interpolate the texcoords.
It still doesn't work :s

I only want to know in my pixel shader which 'stage' I'm in: I want to know if I'm in a 0, 1, 2, 3, 5, 6 or 7 (screencoords.x % 8).

Thanks in advance!!!
Quote:Original post by executive
It still doesn't work :s

I only want to know in my pixel shader which 'stage' I'm in: I want to know if I'm in a 0, 1, 2, 3, 5, 6 or 7 (screencoords.x % 8).

Thanks in advance!!!


The output color is clamped to [0,1] range. Your color output is looks like this:

// Vertex shader -> (2 / (screencoords.x % 8))// Pixel shader -> ((2 / (Vertex Shader)) * 0.1)// Together makes:Color = (2 / (2 / (screencoords.x % 8))) * 0.1;  // Which reduces to:Color = (screencoords.x % 8) * 0.1;


My guess would be that you are getting math precision errors early on in the calculations that are limiting the output range of your function. Try just passing (screencoords.x % 8) into the Out.Stage.x and multiply by 0.1 in the pixel shader:

float4x4 matViewProjection;struct VS_OUTPUT {   float4 Pos:     POSITION;   float2 Stage:   TEXCOORD0;};VS_OUTPUT vs_main( float4 inPos: POSITION, float4 inTex: TEXCOORD0 ){   VS_OUTPUT Out;   Out.Pos = mul(matViewProjection, inPos);   Out.Stage.x = inPos.x % 8;   Out.Stage.y = inPos.y % 12;      return Out;}float4 ps_main( float4 inDiffuse: COLOR0, float4 Tex1: TEXCOORD0 ) : COLOR0{   //  Output constant color:   float4 color = 0;     color.r = Tex1.x * 0.1;      return color;}


Good Luck!
Hi Jason Z,

I VERY appreciate your help but it still doesn't seems to work.

Here is an output of the screen:
(http://www.poison.be/pixelshader/Scrambling0.jpg)
Screenshot

For my testing with HLSL I use RenderMonkey, but that cannot be a problem right?

Thank you VERY VERY much in advance!!
Nicolas
Ah yes, finally I figured it out. Try this instead:
float4x4 matViewProjection;struct VS_OUTPUT {   float4 Pos:     POSITION;   float2 Stage:   TEXCOORD0;};VS_OUTPUT vs_main( float4 inPos: POSITION, float4 inTex: TEXCOORD0 ){   VS_OUTPUT Out;   Out.Pos = mul(matViewProjection, inPos);   Out.Stage.x = inPos.x;   Out.Stage.y = inPos.y;      return Out;}float4 ps_main( float4 inDiffuse: COLOR0, float4 Tex1: TEXCOORD0 ) : COLOR0{   //  Output constant color:   float4 color = 0;   color.r = round( 10 * Tex1.x ) * 0.1;      return color;}


The problem was that we performed the modulus operator in the vertex shader, which the return values are then interpolated per-pixel. Thus we have to perform the modulus function in the pixel shader and viola!

I also couldn't find any info on that modulus operator, so I used the round function. It requires ps 2.0, but from your original title it should be ok. I have the actual .fx file if you want it, but it is using pre-transformed vertices instead. Hope this helps.
Hi Jason Z,

Thank you very very much for your help, I'm getting there

But there's one small problem: my output looks like this.
(http://www.poison.be/pixelshader/Scrambling1.gif)
Scrambling0

So the % 8 is't done yet and I can't get it to work :s

Thank you very very very much!!!!!
Nicolas
Right now you are using the input position to determine the texture coord outputs in the vertex shader (the stage). What are the input coordinates that you are using? I used the texture coords of a quad as the input to the banding function, which have a range of (0,1).

You could scale the *TRANSFORMED* positions to be within the range (0,1) instead of (-1,1) and use that as the output like this:

float4x4 matViewProjection;struct VS_OUTPUT {   float4 Pos:     POSITION;   float2 Stage:   TEXCOORD0;};VS_OUTPUT vs_main( float4 inPos: POSITION, float4 inTex: TEXCOORD0 ){   VS_OUTPUT Out;   Out.Pos = mul(matViewProjection, inPos);   Out.Stage.x = (Out.Pos.x + 1) * 0.5;   Out.Stage.y = (Out.Pos.y + 1) * 0.5;      return Out;}float4 ps_main( float4 inDiffuse: COLOR0, float4 Tex1: TEXCOORD0 ) : COLOR0{   //  Output constant color:   float4 color = 0;   color.r = round( 10 * Tex1.x ) * 0.1;      return color;}


That should do it. Let me know if you still have trouble (we'll figure it out sooner or later...)
Hi Jason Z

Man you must have a lot of patience!!! ;)

I've written a small program instead of using RenderMonkey and now I see some results with your code (not the last one but the previous one, that uses texture coordinates from [0, 1]). We're getting closer.

The problem is that I see some different areas in my screen but they are not 1 pixel width.
(http://www.poison.be/pixelshader/Scrambling2.png)
Scrambling2

I want to get a result that all the pixels at X-location 0 are (0, 0, 0), all the pixels at X-location 1 are (0.125, 0, 0), all the pixels at X-location are (0.25, 0, 0), ..., all the pixels at X-location 7 are (1, 0, 0), all the pixels at X-location 8 are (0, 0, 0), all the pixels at X-location 9 are (0.125, 0, 0) and so on.

This should be the output.
(http://www.poison.be/pixelshader/Target.png)
Target

I've managed now to debug my pixelshader code, so I can see the contents of the registers, but if I place a breakpoint on some vertexshader code that doesn't work :s Very strange...

Thank you very very much for your time and help!!!
Nicolas
Ok, now I understand what you are trying to get. Essentially, you want to be able to determine in your pixel shader which pixel you are currently working on. Then you can use a similar method as before to create the bands.

To do this, I think you would need to add the dimensions of the render target as uniform parameters in your shader. I would pass the transformed position in the tex coords like you already are in the vertex shader. Then in the pixel shader, you need to calculate which pixel you are on - in your example it is actually which column you are in.

So you would convert your clip space position to screen space coords:

x = (clip_space_x + 1) * 0.5; -> Range is now (0, 1)
Screen_space_x = x * Image_size_x; -> Range is now (0, Image_size_x);

Once you have the screen space x coord, it is similar to the previous step to get the bands:

color = frac( Screen_space_x / 8.0f );


Altogether you would have:

float4x4 matViewProjection;float    fSizeX = 256;struct VS_OUTPUT {   float4 Pos:     POSITION;   float2 Stage:   TEXCOORD0;};VS_OUTPUT vs_main( float4 inPos: POSITION, float4 inTex: TEXCOORD0 ){   VS_OUTPUT Out;   Out.Pos = mul(matViewProjection, inPos);   Out.Stage.x = (Out.Pos.x + 1) * 0.5;   Out.Stage.y = (Out.Pos.y + 1) * 0.5;      return Out;}float4 ps_main( float4 inDiffuse: COLOR0, float4 Tex1: TEXCOORD0 ) : COLOR0{   //  Output constant color:   float4 color = 0;   color = frac( (Tex1.x * fSizeX) / 8.0f );      return color;}


That should do it!!! [wink][wink][wink][wink][wink]

This topic is closed to new replies.

Advertisement