191 lines
5.9 KiB
HLSL
191 lines
5.9 KiB
HLSL
#ifndef EDGE_FUSION_COMMON_INCLUDED
|
|
#define EDGE_FUSION_COMMON_INCLUDED
|
|
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
|
|
|
|
TEXTURE2D_X(_ObjectIDTexture);
|
|
TEXTURE2D_X(_SrcColorTexture);
|
|
TEXTURE3D(_NoiseTex3D);
|
|
TEXTURE2D_X(_CustomGroupTexture);
|
|
|
|
// Packed float parameters
|
|
float4 _BlendData1; // x: GlobalIntensity, y: MaxBlendDistance, z: NormalThreshold, w: NoiseContrast
|
|
float4 _BlendData2; // x: MaxScreenRadius, y: ShadowProtection, z: NoiseIntensity, w: NoiseScale
|
|
|
|
// Macros for accessing packed parameters
|
|
#define GLOBAL_INTENSITY _BlendData1.x
|
|
#define MAX_BLEND_DISTANCE _BlendData1.y
|
|
#define NORMAL_THRESHOLD _BlendData1.z
|
|
#define NOISE_CONTRAST _BlendData1.w
|
|
#define MAX_SCREEN_RADIUS _BlendData2.x
|
|
#define SHADOW_PROTECTION _BlendData2.y
|
|
#define NOISE_INTENSITY _BlendData2.z
|
|
#define NOISE_SCALE _BlendData2.w
|
|
|
|
float _DefaultRadiusWorld;
|
|
float _RadiusScale;
|
|
float _DistanceCompensation;
|
|
int _SampleCount;
|
|
int _BinarySearchSteps;
|
|
int _EarlyExitHits;
|
|
int _DebugMode;
|
|
float _DepthDebugMultiplier;
|
|
float4 _SrcColorTexture_TexelSize;
|
|
float4 _CameraDepthTexture_TexelSize;
|
|
float _MSAAFixPower;
|
|
|
|
#define MSAA_FIX_POWER _MSAAFixPower
|
|
|
|
inline float4 SampleColor(float2 uv) {
|
|
return SAMPLE_TEXTURE2D_X_LOD(_SrcColorTexture, sampler_LinearClamp, uv, 0);
|
|
}
|
|
|
|
inline float4 SampleObjectData(float2 uv) {
|
|
return SAMPLE_TEXTURE2D_X_LOD(_ObjectIDTexture, sampler_PointClamp, uv, 0);
|
|
}
|
|
|
|
inline bool SameObjectIds(float4 objA, float4 objB) {
|
|
return abs(objA.r - objB.r) < 0.8;
|
|
}
|
|
|
|
// Packing helpers: pack object ID and normalized radius into the red channel
|
|
#define EF_PACK_QUANT 0.01
|
|
|
|
inline float PackObjectIdRadius(float objectId, float radius) {
|
|
#if defined(SHADER_API_MOBILE) || defined(SHADER_API_GLES3) || defined(SHADER_API_GLES) || defined(SHADER_API_WEBGPU)
|
|
uint id = asuint(objectId);
|
|
id = ((id >> 16) ^ id) * 0x45d9f3b;
|
|
id = ((id >> 16) ^ id) * 0x45d9f3b;
|
|
id = (id >> 16) ^ id;
|
|
float baseId = float(id % 32u);
|
|
#else
|
|
float baseId = floor(objectId / EF_PACK_QUANT);
|
|
baseId = fmod(baseId, 4096.0);
|
|
#endif
|
|
return baseId + radius;
|
|
}
|
|
|
|
inline float UnpackIdFromPacked(float packed) {
|
|
#if defined(SHADER_API_MOBILE) || defined(SHADER_API_GLES3) || defined(SHADER_API_GLES) || defined(SHADER_API_WEBGPU)
|
|
return float(uint(floor(packed) + 0.5));
|
|
#else
|
|
return floor(packed) * EF_PACK_QUANT;
|
|
#endif
|
|
}
|
|
|
|
inline float UnpackRadiusFromPacked(float packed) {
|
|
return frac(packed);
|
|
}
|
|
|
|
float ConvertWorldRadiusToUV(float radius, float linearDepth) {
|
|
radius *= (1.0 + _DistanceCompensation * linearDepth);
|
|
float denom = lerp(max(linearDepth, 1.0), 1.0, unity_OrthoParams.w);
|
|
return 0.5 * radius * unity_CameraProjection._m11 / denom;
|
|
}
|
|
|
|
float GetRadiusUV(float4 objectData, float linearDepth) {
|
|
float radius = UnpackRadiusFromPacked(objectData.r) * _RadiusScale;
|
|
return ConvertWorldRadiusToUV(radius, linearDepth);
|
|
}
|
|
|
|
float3 GetWorldPos(float2 uv, float depth) {
|
|
#if !UNITY_REVERSED_Z
|
|
depth = lerp(UNITY_NEAR_CLIP_VALUE, 1, depth);
|
|
#endif
|
|
|
|
float3 viewPos = ComputeViewSpacePosition(uv, depth, UNITY_MATRIX_I_P);
|
|
return mul(UNITY_MATRIX_I_V, float4(viewPos, 1.0)).xyz;
|
|
}
|
|
|
|
float3 ReconstructNormal(float2 uv, float depthC) {
|
|
// Use 3-tap reconstruction
|
|
float2 texelSize = _CameraDepthTexture_TexelSize.xy;
|
|
|
|
// Sample depths at neighbor pixels
|
|
float depthR = SAMPLE_TEXTURE2D_X_LOD(_CameraDepthTexture, sampler_PointClamp, uv + float2(texelSize.x, 0), 0).r;
|
|
float depthU = SAMPLE_TEXTURE2D_X_LOD(_CameraDepthTexture, sampler_PointClamp, uv + float2(0, texelSize.y), 0).r;
|
|
|
|
// Convert to world positions
|
|
float3 pC = GetWorldPos(uv, depthC);
|
|
float3 pR = GetWorldPos(uv + float2(texelSize.x, 0), depthR);
|
|
float3 pU = GetWorldPos(uv + float2(0, texelSize.y), depthU);
|
|
|
|
// Compute derivatives
|
|
float3 dpdx = normalize(pR - pC);
|
|
float3 dpdy = normalize(pU - pC);
|
|
|
|
// Cross product for normal
|
|
float3 n = cross(dpdy, dpdx);
|
|
return n;
|
|
}
|
|
|
|
float3 ReconstructNormalWS(float3 worldPos) {
|
|
float3 dpdx = ddx(worldPos);
|
|
float3 dpdy = ddy(worldPos);
|
|
float3 normalWS = cross(dpdy, dpdx);
|
|
return dot(normalWS, normalWS) != 0 ? normalize(normalWS) : float3(0, 0, 1);
|
|
}
|
|
|
|
inline float3 GetNormal(float4 objectData) {
|
|
float2 nxy = objectData.zw;
|
|
float nz = sqrt(saturate(1.0 - dot(nxy, nxy)));
|
|
return float3(nxy, nz);
|
|
}
|
|
|
|
float2 WorldToScreenPos(float3 wpos) {
|
|
float4 clip = TransformWorldToHClip(wpos);
|
|
float4 sp = ComputeScreenPos(clip);
|
|
float2 uv = saturate(sp.xy / sp.w);
|
|
return UnityStereoTransformScreenSpaceTex(uv);
|
|
}
|
|
|
|
struct EFVaryings
|
|
{
|
|
float4 positionCS : SV_POSITION;
|
|
float2 texcoord : TEXCOORD0;
|
|
UNITY_VERTEX_OUTPUT_STEREO
|
|
};
|
|
|
|
struct EFFullscreenAttributes
|
|
{
|
|
uint vertexID : SV_VertexID;
|
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
|
};
|
|
|
|
EFVaryings EFVertFullscreen(EFFullscreenAttributes input)
|
|
{
|
|
EFVaryings o;
|
|
UNITY_SETUP_INSTANCE_ID(input);
|
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
|
o.positionCS = GetFullScreenTriangleVertexPosition(input.vertexID);
|
|
o.texcoord = GetFullScreenTriangleTexCoord(input.vertexID);
|
|
return o;
|
|
}
|
|
|
|
#if EDGE_FUSION_ID_EXCLUSION
|
|
float _ExclusionMask[32];
|
|
|
|
inline uint GetExclusionSlot(float4 objData) {
|
|
float id = UnpackIdFromPacked(objData.r);
|
|
uint slot = uint(id + 0.5);
|
|
return (slot >= 1u && slot <= 32u) ? slot : 0u;
|
|
}
|
|
|
|
inline bool IsExcludedIdPair(float4 objA, float4 objB) {
|
|
uint slotA = GetExclusionSlot(objA);
|
|
uint slotB = GetExclusionSlot(objB);
|
|
|
|
if (slotA == 0u || slotB == 0u) return false;
|
|
|
|
uint idxA = slotA - 1u;
|
|
uint idxB = slotB - 1u;
|
|
|
|
return (((uint)_ExclusionMask[idxA] & (1u << idxB)) |
|
|
((uint)_ExclusionMask[idxB] & (1u << idxA))) != 0u;
|
|
}
|
|
#endif
|
|
|
|
#endif // EDGE_FUSION_COMMON_INCLUDED
|