What are derivatives in HLSL/GLSL?

This topic is 3277 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

A recent thread on GDNet sparked my interest once again. I've been taking calculus classes for 3 years now and I completely understand what a derivative calculates, and I know what partial derivatives calculate, but for some reason I fail to understand the point and application of the derivative functions in HLSL and GLSL. Specifically ddx(), ddy(), dFdx(), and dFdy(). Can someone explain what exactly these do? I've looked at the MSDN documentation and that doesn't explain much. I've also searched google which turned up minimal results that I still could not understand. Also could you use these functions any place special for shaders in a 2D quad-based graphics engine?

Share on other sites
I recently had use of a derivative and while i didn't use those specific functions, i think the concept still applies maybe (:

I was simulating waves a pool of lava (could have been an ocean) in a vertex shader by taking sin(position.x + CurrentTime) + sin(position.z + CurrentTime).

That made it so there were waves on both the X and Z axis (X-Z describes the "flat plane" of my world, Y is up).

Anyhow, i needed to get the normal of the points to be able to do lighting.

Well, the slope of sine is cosine, so i was able to use that to get the slope vector (in 2d) per axis, and was able to flip X and Y and negate one to get the normal vector (in 2d) per axis, then combine them together to get the 3d normal.

I'll bet that maybe you'd use those functions for similar reasons?

I could be totally wrong though

Share on other sites
That's a good code example, but no I don't think that's what they are used for exactly. That's more of a conventional analysis of the derivative that I'm familiar with: d/dx[sin x] = cos x.

But here's the definition for ddx().

Share on other sites
It tells you how fast a value is changing at the current pixel. It can be used for mip-maps for example, since if the value is changing more than one texel per pixel, then a lower mip-map level should be used.

Share on other sites
I'm sorry, but I'm just not understanding what you mean by that. Do you have any diagrams that might be able to help? I don't really understand how it measures "how fast a value is changing" at an instant when you only have the data from one frame. And it takes scalars, vectors, and matrices as input? I'm looking for some good and simple example usages of these functions.

Share on other sites
It returns how fast the value is changing compared to that value in the next/previous pixel in screen space. So if you're rendering the pixel at screen coordinates (x, y) then ddx(n) will tell you how fast the value n has been changing between (x-1,y) and (x+1,y). Similarly with ddy.

Share on other sites
Quote:
 Original post by CodekaIt returns how fast the value is changing compared to that value in the next/previous pixel in screen space. So if you're rendering the pixel at screen coordinates (x, y) then ddx(n) will tell you how fast the value n has been changing between (x-1,y) and (x+1,y). Similarly with ddy.

Alright, it's starting to make a little sense. The last thing I need clarification on is where is 'n' coming from. Is that texture coordinates, a color? And could you provide a simple example of ddx with a common input and then give the output.

Share on other sites
Yeah the docs (Cg & MSDN) aren't good at explaining what they do.

Here's an excellent thread even with examples of input & output.

Another excellent one (see mattnewport post)

If I understood it correctly (no one seems to do correctly) those functions have little to do with calculus (but the main reason is to compute deltas though)

What I DO know is that those two functions are very very useful when using doing dynamic conditional branching.
Since the derivatives are used to calculate the mipmap & anisotropic filtering, if one of the adjacent pixels in the 2x2 block (note not all video cards could use a 2x2 grid) follow a different code path from the rest, the deltas can't be correctly calculated; therefore you can't use the tex2D instruction inside a conditional, because tex2D can't calculate the right lod or axis of anisotropy.

Example: The following code won't work in PS 3.0 (where 'x' isn't constant):
if( x < 5 ){   tex2D( mySampler, position ); //Error some of the pixels in the 2x2 block may                                 //have x >= 5; the delta can't be computed}

To solve this, you can calculate the derivative outside the conditional (as the deltas will be the same for all the pixels in the block), and providing the deltas manually later in the conditional branch:

float2 derivX = ddx( position );float2 derivY = ddy( position );if( x < 5 ){   //Whether x < 5 or not, derivX & derivY will stay consistent in all the pixels   //from the grid   tex2Dgrad( mySampler, position, derivX, derivY );}

Though, if you don't care about mips/lod and all that stuff (which often happens with PSSM shadows where you use conditional branching and you have just one lod) you may just use tex2Dlod and manually select the top mip (i.e. tex2Dlod( mySampler, position.xyyy )

Cheers
Dark Sylinc

Share on other sites
Thanks Goldberg that helped a lot! That covers everything I needed.

1. 1
Rutin
28
2. 2
3. 3
4. 4
5. 5

• 11
• 13
• 11
• 10
• 13
• Forum Statistics

• Total Topics
632952
• Total Posts
3009438
• Who's Online (See full list)

There are no registered users currently online

×