Shader之旅4:outline edge 描边效果

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liuyizhou95/article/details/86471070

书写本文的初衷是为了自我反省记录。如有表达不当,请批评指正
在shadertoy上看到了物体的描边效果,感觉效果不错,拿来学习一下,先贴出代码,然后分析

float d;

float lookup(vec2 p, float dx, float dy)
{
    vec2 uv = (p.xy + vec2(dx * d, dy * d)) / iResolution.xy;
    vec4 c = texture(iChannel0, uv.xy);
	
	// return as luma
    return 0.2126*c.r + 0.7152*c.g + 0.0722*c.b;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    d = 1.5; // kernel offset
    vec2 p = fragCoord.xy;
    
	// simple sobel edge detection
    float gx = 0.0;
    gx += -1.0 * lookup(p, -1.0, -1.0);
    gx += -2.0 * lookup(p, -1.0,  0.0);
    gx += -1.0 * lookup(p, -1.0,  1.0);
    gx +=  1.0 * lookup(p,  1.0, -1.0);
    gx +=  2.0 * lookup(p,  1.0,  0.0);
    gx +=  1.0 * lookup(p,  1.0,  1.0);
    
    float gy = 0.0;
    gy += -1.0 * lookup(p, -1.0, -1.0);
    gy += -2.0 * lookup(p,  0.0, -1.0);
    gy += -1.0 * lookup(p,  1.0, -1.0);
    gy +=  1.0 * lookup(p, -1.0,  1.0);
    gy +=  2.0 * lookup(p,  0.0,  1.0);
    gy +=  1.0 * lookup(p,  1.0,  1.0);
    
	// hack: use g^2 to conceal noise in the video
    float g = gx*gx + gy*gy;
    float g2 = g ;
    
    vec4 col = texture(iChannel0, p / iResolution.xy);
    col += vec4(0.0, g, g2, 1.0);
    
    fragColor = col;
}

可以看到shader中构造了gx gy两个变量,
这两个变量是用来Sobel(一种边缘检测滤波)算法来计算检测边缘。
构造两个矩阵如下

可以看到,x y互为转置矩阵,在sobel算法中,gx变量的构造过程中,
gx += -1.0 * lookup(p, -1.0, -1.0);
gx += -2.0 * lookup(p, -1.0, 0.0);
gx += -1.0 * lookup(p, -1.0, 1.0);
gx += 1.0 * lookup(p, 1.0, -1.0);
gx += 2.0 * lookup(p, 1.0, 0.0);
gx += 1.0 * lookup(p, 1.0, 1.0);
第一排数字是x矩阵的列阵,而looup方法里的dx参数的(1,-1)的正负是根据第一排数字的正负决定的,dy是固定的(-1,0,1对应列阵的line 1 line2 line 3)
这样就能根据uv.xy创建不同的gx gy
大概原理如下

对于某一点vec2(x,y),对其边缘的8个位置进行检测

// Sobel masks (参考 http://en.wikipedia.org/wiki/Sobel_operator)
    //        1 0 -1      -1 -2 -1
    //    X=2 0 -2   Y= 0  0  0
    //        1 0 -1      1  2  1

猜你喜欢

转载自blog.csdn.net/liuyizhou95/article/details/86471070