Advertisement

How fragment derivatives are actually evaluated within the 2x2 group

Started by January 22, 2019 05:13 AM
3 comments, last by HolyOdin 6 years ago

I have recently read an article(http://www.aclockworkberry.com/shader-derivative-functions/) ,which was very informative for me。however,there weren't too much details about how the derivatives actually work by explaining them pixels by pixels under the group, only one example was shown there which was too intuitive. but when i came to other pixels in the group, things got really tricky and confusing.for better illustration of my question, Let's just take an example here, say, i have a rendertarget like this:

ddx.jpg.b88d376d895529285bb4489187217556.jpg

According to the article,the horizontal derivative for some value in pixel[0]  is obtained by subtracting the value itself from the correspondence in pixel[1]. Since they are in the same group ,both values can be easily fetched.Great!but how about pixel[1]? if same rule is applied the horizontal derivative should be calculated base on pixel[1] itself as well as the value in pixel[2]. but at this time the two pixels are in diffrent groups! similar situations accured when you perform the vertical derivative for pixel[4]. Well, i was originally thinking maybe there was some fancy driver features that can make it happend. unfortunately the result was not what i expected after i made some experiment.

this simple code below failed my assumption:(you can test it and see the result in shadertoy your self )


void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    int oddRow = int(fragCoord.x) % 2 == 1 ? 1 : 0; //fragCoord是屏幕空间坐标
    float xDerivative = dFdx(float(oddRow));
    fragColor = vec4(xDerivative,xDerivative,xDerivative, 1.0);
}

if my supposition is correct, the screen shoud be alternated with white and black tiles alone the horizontal direction like this:

ss.jpg.11d889ae41c8426a90a170641f79b8dd.jpg

but the result is pure white which is surprisingly not the case.

So,can anyone shed some light about this problem for me. i also goggled a lot of places with no luck, all of them told you the pixels were handled in such a way, but no one really focused on specific situations as i have mentioned above.I think anyone who works with ddx ddy should absolutely have an clear understanding of this.

Much appreciation!

ddx_coarse / ddx_fine (D3D) or dFdxCoarse / dFdxFine (GL), are described pretty well here: https://stackoverflow.com/questions/39579150/difference-between-dfdxfine-and-dfdxcoarse 

If you just use ddx / dFdx, IIRC, you're letting the driver choose between ddx_coarse / ddx_fine for you.

If you have GPU Pro 2, there's an article called "Shader Amortization using Pixel Quad Message Passing" that goes into a good amount of detail.

The GL spec (linked in that stackoverflow answer) should define their inner workings too :D 

Advertisement

GPU's generally use both forward differencing and backwards differencing to compute partial derivatives within a quad. Forward differencing is basically what you're describing: you look at the pixel with address + 1 in the X or Y direction and compute the difference. Backwards differencing is the reverse of that: you look at the pixel with address - 1 and compute the difference from using that. By using both, the GPU can avoid having to access the next quad/group, and can instead only use values from within the quad to compute the derivatives for all 4 pixels. This is certainly what's going on in your shadertoy example: pixel 0 would compute the derivative by calculating p1 - p0, and pixel 1 would also compute the derivative by calculating p1 - p0.

GLSL actually doesn't say much about how dFdx/dFdy work under the hood: they give the implementation a lot of leeway to calculate the result however they see fit. However they explicitly call out the forward/reverse differencing method as an example of a valid approximation that GPU's are allowed to use. Scroll down to section 8.13.1 of the GLSL spec for more details. HLSL/D3D go a bit further, since the coarse/fine versions specify that the values will either be constant across a quad (coarse) or varying per-pixel (fine).

It is greate to know there are coarse and fine version of ddx and ddy.it seems that those version are not available in shadertoy, i will check them out later and do some further test using dx11,thank you!

This topic is closed to new replies.

Advertisement