_Dickie

Unity Shader - Normal Injection Decal

Nov 22nd, 2017
3,445
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  
  3. This is a quick proof of concept I knocked out.
  4. just writes into the normal buffer and nothing else
  5. allowing you to do simple normal decals/edges
  6.  
  7. Most of it's copied from a standard surface shader
  8. output for getting the normals into world space.
  9.  
  10. Unity's shaders are covered by MIT license,
  11. my bit (or lack there of) is unlicensed/public domain
  12.  
  13. @_Dickie
  14.  
  15. */
  16.  
  17. Shader "Decal/Normal Injection Decal"
  18. {
  19.     Properties
  20.     {
  21.         _OpacityClip("Clip", 2D) = "white" {}
  22.         _NormalTex ("Normal", 2D) = "bump" {}
  23.     }
  24.     SubShader
  25.     {
  26.         Name "DEFERRED"
  27.         Tags {
  28.             "LightMode" = "Deferred"
  29.             "Queue" = "Geometry+10"
  30.             }
  31.         LOD 100
  32.  
  33.         Pass
  34.         {
  35.         Offset -1, -1
  36.         zwrite off
  37.             CGPROGRAM
  38.             #pragma vertex vert
  39.             #pragma fragment frag
  40.  
  41.            
  42.             #include "UnityCG.cginc"
  43.  
  44.             struct appdata
  45.             {
  46.                 float4 vertex : POSITION;
  47.                 float2 uv : TEXCOORD0;
  48.                 float3 normal : NORMAL;
  49.                 float4 tangent : TANGENT;
  50.             };
  51.  
  52.             struct v2f
  53.             {
  54.                 float2 uv : TEXCOORD0;
  55.  
  56.                   float4 tSpace0 : TEXCOORD1;
  57.                   float4 tSpace1 : TEXCOORD2;
  58.                   float4 tSpace2 : TEXCOORD3;
  59.  
  60.                 float4 vertex : SV_POSITION;
  61.             };
  62.  
  63.             sampler2D _NormalTex;
  64.             float4 _NormalTex_ST;
  65.             sampler2D _OpacityClip;
  66.            
  67.             v2f vert (appdata v)
  68.             {
  69.                 v2f o;
  70.                 o.vertex = UnityObjectToClipPos(v.vertex);
  71.                 o.uv = TRANSFORM_TEX(v.uv, _NormalTex);
  72.  
  73.                 // copied all below out of a compiled standard surface shader
  74.                 // had tried just transforming to world space on my own
  75.                 // but I figured the unity devs probably know better
  76.                 float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
  77.                 fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
  78.                 fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
  79.                 fixed tangentSign = v.tangent.w * unity_WorldTransformParams.w;
  80.                 fixed3 worldBinormal = cross(worldNormal, worldTangent) * tangentSign;
  81.                 o.tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
  82.                 o.tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
  83.                 o.tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
  84.  
  85.                 return o;
  86.             }
  87.  
  88.             // the outGBuffer2 is the render target being 'injected' into
  89.             // could easily change it to 0 if you wanted to change the base color or w/e
  90.             void frag (v2f i, out half4 outGBuffer2 : SV_Target2)
  91.             {
  92.  
  93.                 half3 norm = UnpackNormal(tex2D(_NormalTex, i.uv));
  94.  
  95.                 clip(tex2D(_OpacityClip,i.uv).a - 0.5);
  96.  
  97.                 // again from surface shader output
  98.                 // but converts from tanget space to world
  99.                 fixed3 worldN;
  100.                 worldN.x = dot(i.tSpace0.xyz, norm);
  101.                 worldN.y = dot(i.tSpace1.xyz, norm);
  102.                 worldN.z = dot(i.tSpace2.xyz, norm);
  103.                 worldN = worldN * 0.5f + 0.5f;
  104.                
  105.                 outGBuffer2 = float4( worldN, 0);
  106.             }
  107.             ENDCG
  108.         }
  109.     }
  110. }
Add Comment
Please, Sign In to add comment