Strict Standards: call_user_func_array() expects parameter 1 to be a valid callback, non-static method GoogleSitemapGeneratorLoader::Enable() should not be called statically in /home/jmurchison/murcho.alumnaie.net/wp-includes/plugin.php on line 311
 Jimi Makes Games » Real-time Unity post processing shader woes.
Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /home/jmurchison/murcho.alumnaie.net/wp-includes/kses.php on line 947

Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /home/jmurchison/murcho.alumnaie.net/wp-includes/kses.php on line 948

Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /home/jmurchison/murcho.alumnaie.net/wp-includes/kses.php on line 947

Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /home/jmurchison/murcho.alumnaie.net/wp-includes/kses.php on line 948

Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /home/jmurchison/murcho.alumnaie.net/wp-includes/kses.php on line 947

Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /home/jmurchison/murcho.alumnaie.net/wp-includes/kses.php on line 948

Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /home/jmurchison/murcho.alumnaie.net/wp-includes/kses.php on line 947

Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /home/jmurchison/murcho.alumnaie.net/wp-includes/kses.php on line 948

Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /home/jmurchison/murcho.alumnaie.net/wp-includes/kses.php on line 947

Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /home/jmurchison/murcho.alumnaie.net/wp-includes/kses.php on line 948

Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /home/jmurchison/murcho.alumnaie.net/wp-includes/kses.php on line 947

Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /home/jmurchison/murcho.alumnaie.net/wp-includes/kses.php on line 948

Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /home/jmurchison/murcho.alumnaie.net/wp-includes/kses.php on line 947

Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /home/jmurchison/murcho.alumnaie.net/wp-includes/kses.php on line 948

Real-time Unity post processing shader woes.

Posted by jimi on November 22nd, 2009 filed in Game Programming, Shaders


Deprecated: Function split() is deprecated in /home/jmurchison/murcho.alumnaie.net/wp-content/plugins/digg-digg/digg-digg.php on line 510

Deprecated: Function ereg() is deprecated in /home/jmurchison/murcho.alumnaie.net/wp-content/plugins/whydowork_adsense.php on line 332

Deprecated: Function ereg() is deprecated in /home/jmurchison/murcho.alumnaie.net/wp-content/plugins/whydowork_adsense.php on line 340

Deprecated: Function ereg() is deprecated in /home/jmurchison/murcho.alumnaie.net/wp-content/plugins/whydowork_adsense.php on line 306

I haven’t spoken much about the work I’ve been doing in my job at Prophecy Games, largely due to the fact I’ve been very busy with it.  Like all of us though, we do need some help from time to time.

I’ve been doing the shaders for our project, which can be quite complicated.  I’ve done pretty well I think, although I’m at a point where I need some help.  Basically this shader takes the normal and depth information from the scene, and uses that information to determine where a black outline should be drawn.  This creates a very cartoony look for the scene.

All was well with this shader, until I turned on anti-aliasing.  This actually caused the outline to flip upside down, however the rest of the scene is still rendered normally.  I’m posting it here so that I can get some help from the guys at Unity.  I will be updating this post once I have the solution to the problem, just in case anyone else runs into it as well.

Here’s the shader code.

Shader “Hidden/Edge Detect Normals XNA” {
Properties {
_MainTex (”", RECT) = “” {}
_DepthNormalsTexture (”DepthNormalsTexture”, RECT) = “” {}
_NormalThreshold (”NormalThreshold”, float) = 1.0
_DepthThreshold (”DepthThreshold”, float) = 1.0
_NormalSensitivity (”NormalSensitivity”, float) = 1.0
_DepthSensitivity (”DepthSensitivity”, float) = 1.0
_EdgeIntensity (”EdgeIntensity”, float) = 1.0
_EdgeWidth (”EdgeWidth”, float) = 1.0
_ScreenHeight (”", float) = 1.0
_ScreenWidth (”", float) = 1.0
}

SubShader {
Pass {
ZTest Always Cull Off ZWrite Off
Fog { Mode off }

CGPROGRAM
#pragma target 3.0
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include “UnityCG.cginc”

uniform samplerRECT _MainTex;
uniform samplerRECT _DepthNormalsTexture;

uniform float4 _MainTex_TexelSize;
uniform float4 _DepthNormalsTexture_TexelSize;
uniform float _NormalThreshold;
uniform float _DepthThreshold;
uniform float _NormalSensitivity;
uniform float _DepthSensitivity;
uniform float _EdgeWidth;
uniform float _EdgeIntensity;
uniform float _ScreenHeight;
uniform float _ScreenWidth;

struct v2f {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};

v2f vert( appdata_img v )
{
v2f o;
o.pos = mul (glstate.matrix.mvp, v.vertex);
o.uv = MultiplyUV( glstate.matrix.texture[0], v.texcoord );
return o;
}

float4 frag (v2f i) : COLOR
{
float4 original = texRECT(_MainTex, i.uv);
float2 edgeOffset = _EdgeWidth / float2(_ScreenWidth, _ScreenHeight);
float2 offset = float2(1,1) * _DepthNormalsTexture_TexelSize.xy;
float2 invOffset = float2(-1,1) * _DepthNormalsTexture_TexelSize.xy;
// 4 samples from normals+depth buffer
float4 normalD1 = texRECT(_DepthNormalsTexture, i.uv - offset);
float4 normalD2 = texRECT(_DepthNormalsTexture, i.uv + offset);
float4 normalD3 = texRECT(_DepthNormalsTexture, i.uv + invOffset);
float4 normalD4 = texRECT(_DepthNormalsTexture, i.uv - invOffset);

float3 normal1;
float depth1;
float3 normal2;
float depth2;
float3 normal3;
float depth3;
float3 normal4;
float depth4;

// Decode normal/depth data
DecodeDepthNormal(normalD1, depth1, normal1);
DecodeDepthNormal(normalD2, depth2, normal2);
DecodeDepthNormal(normalD3, depth3, normal3);
DecodeDepthNormal(normalD4, depth4, normal4);

//return float4(depth1, depth1, depth1, 1);

// Work out how much the normal and depth values are changing
float4 diagonalDelta = abs(float4(normal1, depth1) - float4(normal2, depth2)) + abs(float4(normal3, depth3) - float4(normal4, depth4));

float4 normalDelta = dot(diagonalDelta.xyz, 1);
float depthDelta = diagonalDelta.w;

// Filter out very small changes, in order to produce nice clean results
normalDelta = saturate((normalDelta - _NormalThreshold) * _NormalSensitivity);
depthDelta = saturate((depthDelta - _DepthThreshold) * _DepthSensitivity);

// Does this pixel lie on an edge?
float edgeAmount = saturate(normalDelta + depthDelta) * _EdgeIntensity;

original *= (1 - edgeAmount);
return original;
}
ENDCG
}
}

Fallback off

}

If you enjoyed this post, make sure you subscribe to my RSS feed!

Leave a Comment