- Home /
help with custom sobel edge detection
Hello everyone,
i'm trying to build my own shader as a university project using the Sobel edge detection. I looked into the ones provided with the standard effects and noticed the two variants of the Sobel algorithm implemented there don't check for the normals differences, so I wanted to do that. As I didn't understand the code, I tried to write my own from scratch, but as far as I can tell no edges get drawn. I have no clue what I did wrong, and as time is pressing I'd be really happy if someone could explain where my thinking is wrong.
Here is the shader code:
Shader "Custom/CustomEdgeDetection"
{
Properties
{
}
SubShader
{
// No culling or depth
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _CameraDepthNormalsTexture;
struct appdata
{
float4 vertex : POSITION;
float4 color : COLOR;
};
struct v2f
{
float4 vertex : SV_POSITION;
float4 scrPos : TEXCOORD1;
float4 color : COLOR;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.scrPos = ComputeScreenPos(o.vertex);
o.color = v.color;
return o;
}
fixed4 frag (v2f i) : COLOR
{
//sobel algorithm, see http://homepages.inf.ed.ac.uk/rbf/HIPR2/sobel.htm
float3 normalValues[3][3];
float depthValue[3][3];
float KernelX[3][3];
KernelX[0][0] = -1;
KernelX[1][0] = 0;
KernelX[2][0] = 1;
KernelX[0][1] = -2;
KernelX[1][1] = 0;
KernelX[2][1] = 2;
KernelX[0][2] = -1;
KernelX[1][2] = 0;
KernelX[2][2] = 1;
float KernelY[3][3];
KernelY[0][0] = 1;
KernelY[1][0] = 2;
KernelY[2][0] = 1;
KernelY[0][1] = 0;
KernelY[1][1] = 0;
KernelY[2][1] = 0;
KernelY[0][2] = -1;
KernelY[1][2] = -2;
KernelY[2][2] = -1;
//get all the required normals and depth-values
for (int x = 0; x < 3; x++)
{
for (int y = 0; y < 3; y++)
{
DecodeDepthNormal(tex2D(_CameraDepthNormalsTexture, float2(i.scrPos.x + x, i.scrPos.y + y)), depthValue[x][y], normalValues[x][y]);
}
}
//compute depth magnitude and normalValues magnitudes
float2 depthG = float2(0, 0);
float2 XnormalG = float2(0, 0);
float2 YnormalG = float2(0, 0);
float2 ZnormalG = float2(0, 0);
for (int a = 0; a < 3; a++)
{
for (int b = 0; b < 3; b++)
{
//depth magnitude
depthG.x = depthG.x + (depthValue[a][b] * KernelX[a][b]);
depthG.y = depthG.y + (depthValue[a][b] * KernelY[a][b]);
//normalX magnitude
XnormalG.x = XnormalG.x + (normalValues[a][b].x * KernelX[a][b]);
XnormalG.y = XnormalG.y + (normalValues[a][b].x * KernelY[a][b]);
//normalY magnitude
YnormalG.x = YnormalG.x + (normalValues[a][b].y * KernelX[a][b]);
YnormalG.y = YnormalG.y + (normalValues[a][b].y * KernelY[a][b]);
//normalZ magnitude
ZnormalG.x = ZnormalG.x + (normalValues[a][b].z * KernelX[a][b]);
ZnormalG.y = ZnormalG.y + (normalValues[a][b].z * KernelY[a][b]);
}
}
float SobelDepth = sqrt(depthG.x * depthG.x + depthG.y * depthG.y);
float SobelX = sqrt(XnormalG.x * XnormalG.x + XnormalG.y * XnormalG.y);
float SobelY = sqrt(YnormalG.x * YnormalG.x + YnormalG.y * YnormalG.y);
float SobelZ = sqrt(ZnormalG.x * ZnormalG.x + ZnormalG.y * ZnormalG.y);
float SobelTotal = SobelDepth + SobelX + SobelY + SobelZ;
float4 col = i.color + 20 * float4(SobelTotal, SobelTotal, SobelTotal, 1);
return col;
}
ENDCG
}
}
}
And here is the script for the camera:
using UnityEngine;
using System.Collections;
public class CustomEdgeScript : MonoBehaviour {
public Material mat;
// Use this for initialization
void Start () {
GetComponent<Camera>().depthTextureMode = DepthTextureMode.DepthNormals;
}
// Update is called once per frame
void Update () {
}
void OnRenderImage(RenderTexture source, RenderTexture destination)
{
Graphics.Blit(source, destination, mat);
}
}
Thanks in advance for any answer!
Your answer
Follow this Question
Related Questions
How come edititng "_Glossiness" through script doesn't work? 1 Answer
How to set shader vertex normals to face up 1 Answer
How to smooth out jaggedness of Edge Detection? 0 Answers
EnableKeyword("_EMISSION") not working 2019.3.13f1 0 Answers
Only render stencil mask when behind maskable object 0 Answers