Understand the implementation of sobel filter

Started by
3 comments, last by pcmaster 5 years, 3 months ago

I am new to shader programming. I was learning how to detect edges using shaders these days. And I found the UnityChan toon shader project. But I found it difficulty to understand when I read its implementation of sobel filter.

Especially for these s few lines:(From Line166)

        depthsDiag.x = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv[1]+uvDist)); // TR
        depthsDiag.y = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv[1]+uvDist*float2(-1,1))); // TL
        depthsDiag.z = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv[1]-uvDist*float2(-1,1))); // BR
        depthsDiag.w = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv[1]-uvDist)); // BL

        depthsAxis.x = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv[1]+uvDist*float2(0,1))); // T
        depthsAxis.y = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv[1]-uvDist*float2(1,0))); // L
        depthsAxis.z = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv[1]+uvDist*float2(1,0))); // R
        depthsAxis.w = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv[1]-uvDist*float2(0,1))); // B

        depthsDiag -= centerDepth;
        depthsAxis /= centerDepth;

It seems to try to get the diagonal and axial depth values. But I don't know why we need to substract centerDepth from depthsDiag and divide depthsAxis by centerDepth?

 

Another confusion comes from these a few lines when it tries to return the final color from fragment shader:(From line 191)

     

        float SobelX = dot(SobelH, float4(1,1,1,1));

  float SobelY = dot(SobelV, float4(1,1,1,1));   float Sobel = sqrt(SobelX * SobelX + SobelY * SobelY);       Sobel = 1.0-pow(saturate(Sobel), _Exponent);   //NK   float4 Col = tex2D(_MainTex, i.uv[0].xy);   Col = _EdgesColor * Col * (1.0 - Sobel) + Sobel;   return Col * lerp(tex2D(_MainTex, i.uv[0].xy), _TestColor, _BgFade);

 

What does Sobel = 1.0-pow(saturate(Sobel), _Exponent) do? And what dose Col = _EdgesColor * Col * (1.0 - Sobel) + Sobel mean?

Sorry for my bad English and hope anyone could help me understand this.

Links to the git

Advertisement

Have you looked at https://en.wikipedia.org/wiki/Sobel_operator for an explanation of the Sobel filter?

The final value "Sobel" is how much 'edge' there is (1: edge, 0: no edge -- or vice versa, not sure by heart). The rest is just a way to present it to the user/screen. Just try to solve the equation on paper for Sobel == 1 and Sobel == 0 and you'll see what it does with the colours.

6 hours ago, pcmaster said:

Have you looked at https://en.wikipedia.org/wiki/Sobel_operator for an explanation of the Sobel filter?

The final value "Sobel" is how much 'edge' there is (1: edge, 0: no edge -- or vice versa, not sure by heart). The rest is just a way to present it to the user/screen. Just try to solve the equation on paper for Sobel == 1 and Sobel == 0 and you'll see what it does with the colours.

Thank you for replying. I have read the wiki for several times. Its exlanation is simple and straitforward. After written down the expressions on paper, I understood what Sobel means. But I still cannot understand using the diagonal and axial depths values and treating them differently. 

       depthsDiag.x = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv[1]+uvDist)); // TR

  depthsDiag.y = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv[1]+uvDist*float2(-1,1))); // TL   depthsDiag.z = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv[1]-uvDist*float2(-1,1))); // BR   depthsDiag.w = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv[1]-uvDist)); // BL       depthsAxis.x = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv[1]+uvDist*float2(0,1))); // T   depthsAxis.y = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv[1]-uvDist*float2(1,0))); // L   depthsAxis.z = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv[1]+uvDist*float2(1,0))); // R   depthsAxis.w = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv[1]-uvDist*float2(0,1))); // B       depthsDiag -= centerDepth;  

depthsAxis /= centerDepth;

 

After doing these, it seems to try to convolute the depths values with sobel operator. But the kernel is somehow different from the common one?

      const float4 HorizDiagCoeff = float4(1,1,-1,-1);     const float4 VertDiagCoeff = float4(-1,1,-1,1);   const float4 HorizAxisCoeff = float4(1,0,0,-1);   const float4 VertAxisCoeff = float4(0,1,-1,0);       float4 SobelH = depthsDiag * HorizDiagCoeff + depthsAxis * HorizAxisCoeff;   float4 SobelV = depthsDiag * VertDiagCoeff + depthsAxis * VertAxisCoeff;  

 

Could you give me any hint on that?

 

Thank you

I'm afraid, I can't. I unfortunately don't have time to try what it does.

In a version I have, both DepthsDiag and DepthsAxis are divided by CenterDepth, which is about the only significant difference.

I expect it'll just cause a bit different edge in the horizontal/vertical directions.

This topic is closed to new replies.

Advertisement