Skip to content

Instantly share code, notes, and snippets.

@mattatz
Last active January 19, 2024 10:41
Show Gist options
  • Star 21 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save mattatz/d14898c16008e3ad1abe to your computer and use it in GitHub Desktop.
Save mattatz/d14898c16008e3ad1abe to your computer and use it in GitHub Desktop.
Sobel filter shader for Unity.
Shader "Mattatz/SobelFilter" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_DeltaX ("Delta X", Float) = 0.01
_DeltaY ("Delta Y", Float) = 0.01
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
CGINCLUDE
#include "UnityCG.cginc"
sampler2D _MainTex;
float _DeltaX;
float _DeltaY;
float sobel (sampler2D tex, float2 uv) {
float2 delta = float2(_DeltaX, _DeltaY);
float4 hr = float4(0, 0, 0, 0);
float4 vt = float4(0, 0, 0, 0);
hr += tex2D(tex, (uv + float2(-1.0, -1.0) * delta)) * 1.0;
hr += tex2D(tex, (uv + float2( 0.0, -1.0) * delta)) * 0.0;
hr += tex2D(tex, (uv + float2( 1.0, -1.0) * delta)) * -1.0;
hr += tex2D(tex, (uv + float2(-1.0, 0.0) * delta)) * 2.0;
hr += tex2D(tex, (uv + float2( 0.0, 0.0) * delta)) * 0.0;
hr += tex2D(tex, (uv + float2( 1.0, 0.0) * delta)) * -2.0;
hr += tex2D(tex, (uv + float2(-1.0, 1.0) * delta)) * 1.0;
hr += tex2D(tex, (uv + float2( 0.0, 1.0) * delta)) * 0.0;
hr += tex2D(tex, (uv + float2( 1.0, 1.0) * delta)) * -1.0;
vt += tex2D(tex, (uv + float2(-1.0, -1.0) * delta)) * 1.0;
vt += tex2D(tex, (uv + float2( 0.0, -1.0) * delta)) * 2.0;
vt += tex2D(tex, (uv + float2( 1.0, -1.0) * delta)) * 1.0;
vt += tex2D(tex, (uv + float2(-1.0, 0.0) * delta)) * 0.0;
vt += tex2D(tex, (uv + float2( 0.0, 0.0) * delta)) * 0.0;
vt += tex2D(tex, (uv + float2( 1.0, 0.0) * delta)) * 0.0;
vt += tex2D(tex, (uv + float2(-1.0, 1.0) * delta)) * -1.0;
vt += tex2D(tex, (uv + float2( 0.0, 1.0) * delta)) * -2.0;
vt += tex2D(tex, (uv + float2( 1.0, 1.0) * delta)) * -1.0;
return sqrt(hr * hr + vt * vt);
}
float4 frag (v2f_img IN) : COLOR {
float s = sobel(_MainTex, IN.uv);
return float4(s, s, s, 1);
}
ENDCG
Pass {
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
ENDCG
}
}
FallBack "Diffuse"
}
@CarlLee
Copy link

CarlLee commented Nov 6, 2017

Neat!

@semperflynex
Copy link

Very nice thank you very much!

@khalv
Copy link

khalv commented Aug 23, 2018

You DO realize that about half of the texture lookups in your sobel function are multiplied by zero, and thus do absolutely nothing? Anyway, this is pretty neat for reference.

@wafi-izz
Copy link

how to implement it

@Bl4ckh34d
Copy link

Bl4ckh34d commented Jan 19, 2024

You DO realize that about half of the texture lookups in your sobel function are multiplied by zero, and thus do absolutely nothing? Anyway, this is pretty neat for reference.

You DO realize that these multiplications are the weights needed for a Sobel Filter? Read up on Convolution Filters, you will understand what I mean.

@khalv
Copy link

khalv commented Jan 19, 2024

You DO realize that these multiplications are the weights needed for a Sobel Filter? Read up on Convolution Filters, you will understand what I mean.

Yes of course, but if a sample is multiplied by a constant value of zero, it will have no influence on the sum, and therefore it would be better to omit this sample to avoid an expensive texture lookup. There is a difference between the mathematical description of a kernel and how it is appropriate to implement it.

Maybe my phrasing was unecessarily rude - I just ran the code through DXC Compiler Explorer, and I can see that it will optimize away those lines anyway, so it's not like it matters.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment