Hi!
I'm new with shaders, so maybe this is a noob question, but I didn't found any solution on the web so:
I wrote this edge detection shader for use it in a post process effect. It is working "fine" if I use it with a monobehaviour on the camera (pasted lower), but not if I try to use it in a custom post process effect. (code at the buttom) In that case it is creates only a triangle. I would be happy with the monobehaviour solution but in that case it is overwrites the other effects.
WithMono:
![alt text][1]
With Post:
![alt text][2]
The shader:
Shader "Hidden/EdgeDetection"
{
Properties
{
_EdgeColor("EdgeColor", COLOR) = (0,0,0,1)
_SampleDistance("SampleDistance", float) = 1
_DepthSensitivity("DepthSensitivity", float) = 0.1
_NormalSensitivity("NormalSensitivity",float) = 0.1
_FadeToDistance("FadeToDistance", float) = 1
}
SubShader
{
// No culling or depth
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex VertexToFragment
#pragma fragment frag
#include "UnityCG.cginc"
//vars
sampler2D _Depth;
sampler2D _CameraDepthNormalsTexture;
float2 _CameraDepthNormalsTexture_TexelSize;
float4 _EdgeColor : COLOR;
float _DepthSensitivity;
float _NormalSensitivity;
float _SampleDistance;
sampler2D _MainTex;
float _FadeToDistance;
struct VertInput
{
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
struct VertexOutput
{
float4 clipPos : SV_POSITION;
float2 uv : texcoord;
};
VertexOutput VertexToFragment (VertInput input)
{
VertexOutput output;
output.clipPos = UnityObjectToClipPos(input.pos);
output.uv = input.uv;
return output;
}
fixed4 frag (VertexOutput i) : SV_Target
{
fixed4 col = tex2D(_CameraDepthNormalsTexture, i.uv);
fixed4 texColor = tex2D(_MainTex, i.uv);
float depth;
float3 normal;
DecodeDepthNormal(col, depth, normal);
float2 uvs[4];
float depthDistance = _SampleDistance * (1-depth*0.7);
uvs[0] = i.uv + float2(_CameraDepthNormalsTexture_TexelSize.x, _CameraDepthNormalsTexture_TexelSize.y)*depthDistance;
uvs[1] = i.uv + float2(_CameraDepthNormalsTexture_TexelSize.x, -_CameraDepthNormalsTexture_TexelSize.y)*depthDistance;
uvs[2] = i.uv + float2(-_CameraDepthNormalsTexture_TexelSize.x, -_CameraDepthNormalsTexture_TexelSize.y)*depthDistance;
uvs[3] = i.uv + float2(-_CameraDepthNormalsTexture_TexelSize.x, _CameraDepthNormalsTexture_TexelSize.y)*depthDistance;
//Neighbours - get datas
fixed4 nCols[4];
float nDepths[4];
float3 nNormals[4];
nCols[0] = tex2D(_CameraDepthNormalsTexture, uvs[0]);
nCols[1] = tex2D(_CameraDepthNormalsTexture, uvs[1]);
nCols[2] = tex2D(_CameraDepthNormalsTexture, uvs[2]);
nCols[3] = tex2D(_CameraDepthNormalsTexture, uvs[3]);
DecodeDepthNormal(nCols[0], nDepths[0], nNormals[0]);
DecodeDepthNormal(nCols[1], nDepths[1], nNormals[1]);
DecodeDepthNormal(nCols[2], nDepths[2], nNormals[2]);
DecodeDepthNormal(nCols[3], nDepths[3], nNormals[3]);
float avgDepth = (nDepths[0] + nDepths[1] + nDepths[2] + nDepths[3])*0.25;
bool isEdge = abs(avgDepth - depth) > _DepthSensitivity*(1-depth);
bool isFade = _FadeToDistance >= 0.5;
//is edge by depth
if (isEdge) {
if (isFade) {
texColor.rgb = lerp(_EdgeColor.rgb, texColor.rgb, depth);
}
else {
texColor.rgb = _EdgeColor.rgb;
}
}
else {
//is edge by normals
float3 avgNormal = nNormals[0] + nNormals[1] + nNormals[2] + nNormals[3];
avgNormal = normalize(avgNormal);
float normalDif = 1-((dot(normal, avgNormal)+1)*0.5);
isEdge = normalDif > _NormalSensitivity*(1+depth*10);
if (isEdge) {
if (isFade) {
texColor.rgb = lerp(_EdgeColor.rgb, texColor.rgb, depth);
}
else {
texColor.rgb = _EdgeColor.rgb;
}
}
}
return texColor;
}
ENDCG
}
}
}
The Mono:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[ExecuteInEditMode]
public class EdgeDetectEffect : MonoBehaviour
{
public Material postProcessingMat;
private void Start()
{
GetComponent().depthTextureMode = DepthTextureMode.DepthNormals;
}
private void OnRenderImage(RenderTexture source, RenderTexture destination)
{
Graphics.Blit(source, destination, postProcessingMat);
}
}
The Post Process:
using System;
using UnityEngine;
using UnityEngine.Rendering.PostProcessing;
[Serializable]
[PostProcess(typeof(EdgeDetectRenderer), PostProcessEvent.BeforeStack, "Hidden/EdgeDetection")]
public sealed class EdgeDetect : PostProcessEffectSettings
{
}
public sealed class EdgeDetectRenderer : PostProcessEffectRenderer
{
public override DepthTextureMode GetCameraFlags()
{
return DepthTextureMode.DepthNormals;
}
public override void Render(PostProcessRenderContext context)
{
var sheet = context.propertySheets.Get(Shader.Find("Hidden/EdgeDetection"));
context.command.BlitFullscreenTriangle(context.source, context.destination, sheet, 0);
}
}
[1]: /storage/temp/131639-edgeon.png
[2]: /storage/temp/131640-edgeoff.png
↧