Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save pajama/5b6513c421af2964d78ecfbe8a8f3401 to your computer and use it in GitHub Desktop.
Save pajama/5b6513c421af2964d78ecfbe8a8f3401 to your computer and use it in GitHub Desktop.
updated to support single pass instanced rendering and URP render passes with color buffer
Shader "WorldNormalFromDepthTexture"
{
Properties {
_ScanDistance("Scan Distance", float) = 0
_ScanWidth("Scan Width", float) = 10
_LeadSharp("Leading Edge Sharpness", float) = 10
_LeadColor("Leading Edge Color", Color) = (1, 1, 1, 0)
_MidColor("Mid Color", Color) = (1, 1, 1, 0)
_TrailColor("Trail Color", Color) = (1, 1, 1, 0)
_HBarColor("Horizontal Bar Color", Color) = (0.5, 0.5, 0.5, 0)
}
SubShader
{
Tags { "RenderType"="Transparent" "Queue"="Transparent" }
LOD 100
Pass
{
Cull Off
ZWrite Off
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.5
//#include "UnityCG.cginc"
//#include "UnityShaderVariables.cginc"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareOpaqueTexture.hlsl"
float4 _WorldSpaceScannerPos;
float _ScanDistance;
float _ScanWidth;
float _LeadSharp;
float4 _LeadColor;
float4 _MidColor;
float4 _TrailColor;
float4 _HBarColor;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
UNITY_VERTEX_OUTPUT_STEREO
};
v2f vert (appdata v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
//o.pos = UnityObjectToClipPos(v.vertex);
o.pos = float4(v.vertex.xyz, 1.0);
o.uv = v.uv;
#if UNITY_UV_STARTS_AT_TOP
o.pos.y *= -1;
#endif
return o;
}
//TEXTURE2D_SAMPLER2D(_MainTex, sampler_MainTex);
TEXTURE2D_X(_CameraDepthTexture);
SAMPLER(sampler_CameraDepthTexture);
float4 _CameraDepthTexture_TexelSize;
//TEXTURE2D(_MainTex);
// SAMPLER(sampler_MainTex);
float getRawDepth(float2 uv)
{
return SAMPLE_DEPTH_TEXTURE_LOD(_CameraDepthTexture, sampler_CameraDepthTexture,float4(uv, 0.0, 0.0),0);
}
// inspired by keijiro's depth inverse projection
// https://github.com/keijiro/DepthInverseProjection
// constructs view space ray at the far clip plane from the screen uv
// then multiplies that ray by the linear 01 depth
float3 viewSpacePosAtScreenUV(float2 uv)
{
float3 viewSpaceRay = mul(unity_CameraInvProjection, float4(uv * 2.0 - 1.0, 1.0, 1.0) * _ProjectionParams.z);
float rawDepth = getRawDepth(uv);
return viewSpaceRay * Linear01Depth(rawDepth,_ZBufferParams);
}
float3 viewSpacePosAtPixelPosition(float2 vpos)
{
float2 uv = vpos * _CameraDepthTexture_TexelSize.xy;
return viewSpacePosAtScreenUV(uv);
}
// naive 3 tap normal reconstruction
// accurate mid triangle normals, slightly diagonally offset on edges
// artifacts on depth disparities
// unity's compiled fragment shader stats: 41 math, 3 tex
half3 viewNormalAtPixelPosition(float2 vpos)
{
// get current pixel's view space position
half3 viewSpacePos_c = viewSpacePosAtPixelPosition(vpos + float2( 0.0, 0.0));
// get view space position at 1 pixel offsets in each major direction
half3 viewSpacePos_r = viewSpacePosAtPixelPosition(vpos + float2( 1.0, 0.0));
half3 viewSpacePos_u = viewSpacePosAtPixelPosition(vpos + float2( 0.0, 1.0));
// get the difference between the current and each offset position
half3 hDeriv = viewSpacePos_r - viewSpacePos_c;
half3 vDeriv = viewSpacePos_u - viewSpacePos_c;
// get view space normal from the cross product of the diffs
half3 viewNormal = normalize(cross(hDeriv, vDeriv));
return viewNormal;
}
half4 frag (v2f i) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
float4 color = SAMPLE_TEXTURE2D_X(_CameraOpaqueTexture, sampler_CameraOpaqueTexture, i.uv);
// get view space normal at the current pixel position
half3 viewNormal = viewNormalAtPixelPosition(i.pos.xy);
// transform normal from view space to world space
half3 WorldNormal = mul((float3x3)unity_MatrixInvV, viewNormal);
float2 vpos = i.pos.xy;
float2 uv = vpos * _CameraDepthTexture_TexelSize.xy;
float3 viewSpacePos = viewSpacePosAtScreenUV(uv);
half3 worldPos = mul((float3x3)unity_MatrixInvV, viewSpacePos) + _WorldSpaceCameraPos;
float dist = distance(worldPos, _WorldSpaceScannerPos);
return half4(worldPos,1) * color;
}
ENDHLSL
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment