Concerning dFd{x, y}() in GLSL

来源:互联网 发布:cydia4g软件源 编辑:程序博客网 时间:2024/05/17 08:55
dFdx(fragAttrib) and dFdy(fragAttrib) compute derivatives of certain given attribute between two adjacent fragments.
If currently being processed fragment is f(x, y), x and y refer to the position of this fragment in SCREEN SPACE, then

    1. dFdx(fragAttrib) calculates the derivative of "fragAttrib" between f(x, y) and f(x+1, y), atually is the "fragAttrib" value of f(x+1, y)
subtracted by the value of "fragAttrib" of f(x, y);

    2. dFdy(fragAttrib) calculates the derivative of "fragAttrib" between f(x, y) and f(x, y+1), atually is the "fragAttrib" value of f(x, y+1)
subtracted by the value of "fragAttrib" of f(x, y);


///////////////////////////////////////////////////////////////////////////////////////////////////////////
CAUTION!
    1. Since dFd{x, y}() are used to compute derivatives, so if a constant is the parameter, the return value is permanently ZERO!

    2. The prototype is genType dFd{x, y}(genType fragAttrib), so return value shares the same data-type with the parameter "fragAttrib".


///////////////////////////////////////////////////////////////////////////////////////////////////////////
TIP(s):
    1. Usually a varying variable is used of being the parameter of dFd{x, y}();, like fragment position, tex coord, etc.

    2. texture(tex, v2VarTC) equals to textureGrad(tex, v2VarTC, dFdx(v2VarTC), dFdy(v2VarTC)).

    3. Yet unknown(yukk!).


///////////////////////////////////////////////////////////////////////////////////////////////////////////
    E.G:
        A shader like the following code for digital image processing. Here I use dFdx() and dFdy() to compute distance between 2 adjacent fragments(so-called pixels in D3D).

        A full screen quad which has 4 vertices with position (-1, -1), (1, -1), (1, 1) and (-1, 1) is simply loaded to vertex shader as a platform for digital image processing.
    
#version 330

layout (location = 0) vec3 in v3Pos;    // vertex position.
layout (location = 1) vec2 in v2TC;     // vertex tex coord.

out vec3 v3VarPos;
out vec2 v2VarTC;        

void main()
{
    gl_Position = vec4(v3VarPos, 1.0);
    v3VarPos = v3Pos;
    v2VarTC = v2TC;
}
    
/*****************************************************************************************/
Here is the fragment shader:

#version 330

uniform sampler2D tex;

in vec3 v3VarPos;    // After passed to fragment shader, this "v3VarPos" has been transformed into screen space(if transform is
//  applied but currently no transform here), and interpolated, v3VarPos.xy refers to the coordinate of currently being processed
// fragment in screen space(normalized to [0, 1]);

in vec2 v3VarTC:

out v4FragColor;


void main()
{
    if(v2VarTC.x >= 0.5)
        v4FragColor = texture(tex, v2VarTC);
    else
    {
        float fDDX = dFdx(v3VarPos.x);  // fDDX = [v3VarPos.x of f(x+1, y)] - [v3VarPos.x of f(x, y)];
        float fDDY = dFdy(v3VarPos.y); // fDDY = [v3VarPos.y of f(x, y+1)] - [v3VarPos.y of f(x, y)];

        // So fDDX is the distance along X axis of screen space between  two adjacent fragments, as well as f(x, y) and f(x+1, y);
        // fDDY is the distance along Y axis of screen space between two adjacent fragments, as well as f(x, y) and f(x, y+1).
    
        float f9K[9] = float[9](1, 2, 1, 0, 0, 0, -1, -2, -1); // A simple 3x3 horizontal Sobel edge detection kernel.
                                                                                  //  1   2   1
                                                                                  //  0   0   0
                                                                                  //  -1 -2  -1    
                                       
        v4OutFragColor = f9K[0]*texture(tex, v2VarTC+vec2(-fDDX, fDDY)) + f9K[1]*texture(tex, v2VarTC+vec2(0, fDDY)) + 
                                      f9K[2]*texture(tex, v2VarTC+vec2( fDDX, fDDY)) + 

                                      f9K[3]*texture(tex, v2VarTC+vec2(-fDDX, 0)) + f9K[4]*texture(tex, v2VarTC) + 
                                      f9K[5]*texture(tex, v2VarTC+vec2( fDDX, 0)) + 
     
                                      f9K[6]*texture(tex, v2VarTC+vec2(-fDDX, -fDDY)) + f9K[7]*texture(tex, v2VarTC+vec2(0, -fDDY)) + 
                                      f9K[8]*texture(tex, v2VarTC+vec2( fDDX, -fDDY));
    }


Result(Left half processed by horizontal Sobel, Right is the original texture)

 
Another by a Laplacian kernel:
// -1 -1 -1
// -1  8 -1
// -1 -1 -1
 
0 0
原创粉丝点击