How do ddx and ddy work?

Started by
3 comments, last by MJP 12 years, 11 months ago
I don't quite understand the ddx and ddy shader instructions. What I know is that a 2x2 block of pixels gets processed inside of one shader unit on the video card. I've read in multiple places that ddx will use the pixel to the right of it to calculate the rate of change. I'm confused because the pixels on the right side of the 2x2 block do not have a pixel to the right in the same shader unit. Similarly, ddy will look at the pixel below it, but there are no pixels below the bottom row in the block. What happens when I get to the edge of the screen?

Also, how are the derivatives calculated?

Thanks!
Advertisement
It's different depending on your GPU. Regarding the problem of there being no pixel to the right, I'd assume that the right hand pixels in a block would measure the rate-of-change from the left-hand pixels, and the bottom pixels would likewise compare their values with the top pixels.


Googling [font="'Courier New"]ddx ddy site:gamdev.net[/font] brought up this:
http://www.gamedev.n...-dfdx-dfdy-etc/
The fragments are processed in the 2x2 blocks; ddx will compute the difference from either the rightward or leftward fragment, depending on which side of the 2x2 block it is on. You can confirm this by observing that ddx always produces the same values for both pixels.

The fragments are processed in the 2x2 blocks; ddx will compute the difference from either the rightward or leftward fragment, depending on which side of the 2x2 block it is on. You can confirm this by observing that ddx always produces the same values for both pixels.


Ah, that sounds reasonable, thanks!

I'm not quite sure how I can observe that both pixels will have the same result. Do you have any suggestions on a quick shader I can put together and what value I can calculate the derivative of?
Pixel shaders are always executed in a 2x2 block, so that they always have derivatives available (since they're needed for mipmapping). So even on triangle or screen edges there will still be 2x2 blocks at the edges. However depending on what you do in that pixel shader and what you take the derivative of, you may get strange or undefined results.

A simple test case you can work up is to render a full screen quad and use the screen-space position (VPOS for D3D9 or SV_Position for D3D10/D3D11) to determine whether each pixel is an odd or even pixel for that row or column. You should always get a derivative of 1 in the x direction for all pixels, due to the way the derivatives are calculated. Same for the y direction. Something like this:

float4 TestShader(in float4 ScreenPos : SV_Position) : SV_Target
{
float oddRow = int(ScreenPos.x) % 2 == 1 ? 1.0f : 0.0f;
float oddColumn = int(ScreenPos.y) % 2 == 1 ? 1.0f : 0.0f;
float xDerivative = ddx(oddRow);
float yDerivative = ddy(oddColumn);
return float4(xDerivative, yDerivative, 0.0f, 1.0f);
}

This topic is closed to new replies.

Advertisement