195 lines
7.8 KiB
GLSL
195 lines
7.8 KiB
GLSL
Shader "Kronnect/EdgeFusion/ObjectID"
|
|
{
|
|
Properties
|
|
{
|
|
[MainTexture] _BaseMap("Albedo", 2D) = "white" {}
|
|
_EdgeFusionRadius("Edge Fusion Radius", Float) = 0
|
|
_CustomObjectId("Custom Object ID", Float) = 0
|
|
_DisallowIntraFusion("Disallow Intra Fusion", Float) = 0
|
|
[HideInInspector] _ZWrite("ZWrite", Int) = 0
|
|
[HideInInspector] _ZTest("ZTest", Int) = 3 // Equal = Make it work with cutout materials
|
|
}
|
|
|
|
SubShader
|
|
{
|
|
Pass
|
|
{
|
|
Name "Edge Fusion Object ID"
|
|
ZWrite [_ZWrite]
|
|
ZTest [_ZTest]
|
|
Cull [_Cull]
|
|
|
|
HLSLPROGRAM
|
|
#if UNITY_PLATFORM_ANDROID || (UNITY_PLATFORM_WEBGL && !SHADER_API_WEBGPU) || UNITY_PLATFORM_UWP
|
|
#pragma target 3.5
|
|
#else
|
|
#pragma target 4.5
|
|
#endif
|
|
#pragma vertex vert
|
|
#pragma fragment frag
|
|
#pragma multi_compile_instancing
|
|
#pragma instancing_options nolightprobe nolightmap
|
|
#pragma multi_compile_local_fragment _ EDGE_FUSION_MSAA_ON
|
|
#pragma multi_compile_local_fragment _ EDGE_FUSION_INTRA_OBJECT EDGE_FUSION_CONCAVE_ONLY
|
|
#pragma multi_compile_local_fragment _ EDGE_FUSION_DEBUG_BLEND_NORMALS
|
|
#pragma multi_compile _ LOD_FADE_CROSSFADE
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
|
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityDOTSInstancing.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/UniversalDOTSInstancing.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
|
|
#include "EdgeFusionCommon.hlsl"
|
|
|
|
#if defined(LOD_FADE_CROSSFADE)
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/LODCrossFade.hlsl"
|
|
#endif
|
|
|
|
struct ObjIDAttributes
|
|
{
|
|
float4 positionOS : POSITION;
|
|
float2 uv : TEXCOORD0;
|
|
float3 normalOS : NORMAL;
|
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
|
};
|
|
|
|
struct ObjIDVaryings
|
|
{
|
|
float4 positionCS : SV_POSITION;
|
|
nointerpolation float objectID : TEXCOORD0;
|
|
float4 screenPos : TEXCOORD1;
|
|
float viewDepth : TEXCOORD2;
|
|
float3 worldPos : TEXCOORD3;
|
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
|
UNITY_VERTEX_OUTPUT_STEREO
|
|
};
|
|
|
|
TEXTURE2D(_BaseMap);
|
|
SAMPLER(sampler_BaseMap);
|
|
float _MaxBlendDistance;
|
|
|
|
CBUFFER_START(UnityPerMaterial)
|
|
float _EdgeFusionRadius;
|
|
float _CustomObjectId;
|
|
float _DisallowIntraFusion;
|
|
CBUFFER_END
|
|
|
|
#ifdef UNITY_DOTS_INSTANCING_ENABLED
|
|
UNITY_DOTS_INSTANCING_START(ObjectIDMetadata)
|
|
UNITY_DOTS_INSTANCED_PROP(float, _EdgeFusionRadius)
|
|
UNITY_DOTS_INSTANCED_PROP(float, _CustomObjectId)
|
|
UNITY_DOTS_INSTANCED_PROP(float, _DisallowIntraFusion)
|
|
UNITY_DOTS_INSTANCING_END(ObjectIDMetadata)
|
|
|
|
#define _EdgeFusionRadius UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float, _EdgeFusionRadius)
|
|
#define _CustomObjectId UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float, _CustomObjectId)
|
|
#define _DisallowIntraFusion UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float, _DisallowIntraFusion)
|
|
#endif
|
|
|
|
float GetIdFromObject() {
|
|
float4x4 m = UNITY_MATRIX_M;
|
|
float3 r0 = m[0].xyz;
|
|
float3 r1 = m[1].xyz;
|
|
float3 r2 = m[2].xyz;
|
|
float3 pos = float3(m[0][3], m[1][3], m[2][3]);
|
|
float objectID = dot(r0, float3(73.0, 157.0, 131.0))
|
|
+ dot(r1, float3(269.0, 97.0, 211.0))
|
|
+ dot(r2, float3(337.0, 41.0, 173.0))
|
|
+ dot(pos, float3(521.0, 313.0, 463.0));
|
|
return objectID;
|
|
}
|
|
|
|
ObjIDVaryings vert(ObjIDAttributes input)
|
|
{
|
|
ObjIDVaryings output;
|
|
UNITY_SETUP_INSTANCE_ID(input);
|
|
UNITY_TRANSFER_INSTANCE_ID(input, output);
|
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
|
|
|
|
float4 positionOS = input.positionOS;
|
|
float3 normalOS = input.normalOS;
|
|
|
|
float3 positionWS = TransformObjectToWorld(positionOS.xyz);
|
|
float3 positionVS = TransformWorldToView(positionWS);
|
|
output.viewDepth = -positionVS.z;
|
|
|
|
output.positionCS = TransformObjectToHClip(positionOS.xyz);
|
|
output.screenPos = ComputeScreenPos(output.positionCS);
|
|
|
|
float objectId = _CustomObjectId;
|
|
if (objectId < 0.5) {
|
|
objectId = GetIdFromObject();
|
|
#if UNITY_ANY_INSTANCING_ENABLED
|
|
objectId += unity_InstanceID;
|
|
#endif
|
|
objectId = fmod(abs(objectId), 4096.0);
|
|
}
|
|
|
|
output.objectID = floor(objectId);
|
|
|
|
output.worldPos = positionWS;
|
|
|
|
return output;
|
|
}
|
|
|
|
float4 frag(ObjIDVaryings input) : SV_Target0
|
|
{
|
|
UNITY_SETUP_INSTANCE_ID(input);
|
|
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
|
|
|
|
if (input.viewDepth > _MaxBlendDistance) return float4(0, 0, 0, 0);
|
|
|
|
#if defined(LOD_FADE_CROSSFADE)
|
|
LODFadeCrossFade(input.positionCS);
|
|
#endif
|
|
|
|
float objectId = input.objectID;
|
|
float radius = _EdgeFusionRadius;
|
|
|
|
if (radius <= 0) {
|
|
radius = _DefaultRadiusWorld;
|
|
} else if (radius > 0.9 * _RadiusScale) {
|
|
return float4(0, -1, 0, 0);
|
|
}
|
|
|
|
float2 uv = input.screenPos.xy / input.screenPos.w;
|
|
float sceneDepth = SampleSceneDepth(uv);
|
|
|
|
float rawDepth;
|
|
#if EDGE_FUSION_MSAA_ON
|
|
rawDepth = input.positionCS.z;
|
|
#if UNITY_REVERSED_Z
|
|
if (rawDepth < sceneDepth) return float4(0, 0, 0, 0);
|
|
#else
|
|
if (rawDepth > sceneDepth) return float4(0, 0, 0, 0);
|
|
#endif
|
|
#else
|
|
rawDepth = sceneDepth;
|
|
#endif
|
|
|
|
float linearDepth = LinearEyeDepth(rawDepth, _ZBufferParams);
|
|
float uvRadius = ConvertWorldRadiusToUV(radius, linearDepth);
|
|
float screenRadiusPx = uvRadius * _ScreenParams.y;
|
|
if (screenRadiusPx < 2.0) {
|
|
return float4(0, -1, 0, 0);
|
|
}
|
|
|
|
float packedR = PackObjectIdRadius(objectId, radius / _RadiusScale);
|
|
|
|
float3 nVS;
|
|
#if EDGE_FUSION_INTRA_OBJECT || EDGE_FUSION_CONCAVE_ONLY || EDGE_FUSION_DEBUG_BLEND_NORMALS
|
|
float3 nWS = ReconstructNormalWS(input.worldPos);
|
|
nVS = mul((float3x3)UNITY_MATRIX_V, nWS);
|
|
nVS = normalize(nVS);
|
|
if (_DisallowIntraFusion > 0.5) {
|
|
nVS.x = 999.0;
|
|
}
|
|
#else
|
|
nVS = float3(0, 0, 1);
|
|
#endif
|
|
return float4(packedR, rawDepth, nVS.xy);
|
|
}
|
|
ENDHLSL
|
|
}
|
|
}
|
|
}
|