Advertisement Jump to content
achiga

3D Understand the implementation of sobel filter

Recommended Posts

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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!