Files
ToriaAssets/Imports/Beautify addon/Runtime/Resources/EdgeFusion/Shaders/EdgeFusionObjectID.shader
T
2026-08-13 16:49:22 +02:00

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
}
}
}