617 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			617 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								#pragma kernel GPUFrustumCulling
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								struct IndirectInstanceData
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    float4x4 PositionMatrix;
							 | 
						||
| 
								 | 
							
								    float4 ControlData;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								struct IndirectShaderData
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    float4x4 PositionMatrix;
							 | 
						||
| 
								 | 
							
								    float4x4 InversePositionMatrix;
							 | 
						||
| 
								 | 
							
								    float4 ControlData;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint _InstanceCount;
							 | 
						||
| 
								 | 
							
								bool UseLODs;
							 | 
						||
| 
								 | 
							
								bool NoFrustumCulling;
							 | 
						||
| 
								 | 
							
								bool ShadowCulling;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//Used for frustum culling
							 | 
						||
| 
								 | 
							
								float4 _VS_CameraFrustumPlane0;
							 | 
						||
| 
								 | 
							
								float4 _VS_CameraFrustumPlane1;
							 | 
						||
| 
								 | 
							
								float4 _VS_CameraFrustumPlane2;
							 | 
						||
| 
								 | 
							
								float4 _VS_CameraFrustumPlane3;
							 | 
						||
| 
								 | 
							
								float4 _VS_CameraFrustumPlane4;
							 | 
						||
| 
								 | 
							
								float4 _VS_CameraFrustumPlane5;
							 | 
						||
| 
								 | 
							
								float4 _WorldSpaceCameraPos;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								float4 _FloatingOriginOffset;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								float3 _LightDirection;
							 | 
						||
| 
								 | 
							
								float3 _PlaneOrigin;
							 | 
						||
| 
								 | 
							
								float3 _BoundsSize;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//Used for vegetatuion distance culling
							 | 
						||
| 
								 | 
							
								float _CullFarStart;
							 | 
						||
| 
								 | 
							
								float _CullFarDistance;
							 | 
						||
| 
								 | 
							
								float _BoundingSphereRadius;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//Used for LODs
							 | 
						||
| 
								 | 
							
								float _LOD1Distance;
							 | 
						||
| 
								 | 
							
								float _LOD2Distance;
							 | 
						||
| 
								 | 
							
								float _LOD3Distance;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								float _LODFactor;
							 | 
						||
| 
								 | 
							
								float _LODBias;
							 | 
						||
| 
								 | 
							
								float _LODFadeDistance;
							 | 
						||
| 
								 | 
							
								int _LODCount;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								StructuredBuffer<IndirectInstanceData> SourceShaderDataBuffer;
							 | 
						||
| 
								 | 
							
								AppendStructuredBuffer<IndirectShaderData> VisibleBufferLOD0;
							 | 
						||
| 
								 | 
							
								AppendStructuredBuffer<IndirectShaderData> VisibleBufferLOD1;
							 | 
						||
| 
								 | 
							
								AppendStructuredBuffer<IndirectShaderData> VisibleBufferLOD2;
							 | 
						||
| 
								 | 
							
								AppendStructuredBuffer<IndirectShaderData> VisibleBufferLOD3;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								AppendStructuredBuffer<IndirectShaderData> ShadowBufferLOD0;
							 | 
						||
| 
								 | 
							
								AppendStructuredBuffer<IndirectShaderData> ShadowBufferLOD1;
							 | 
						||
| 
								 | 
							
								AppendStructuredBuffer<IndirectShaderData> ShadowBufferLOD2;
							 | 
						||
| 
								 | 
							
								AppendStructuredBuffer<IndirectShaderData> ShadowBufferLOD3;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								SamplerState _LinearClamp;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// float CalculateLODFade(float cameraDistance, float nextLODDistance)
							 | 
						||
| 
								 | 
							
								// {
							 | 
						||
| 
								 | 
							
								//     float distance = nextLODDistance - cameraDistance;
							 | 
						||
| 
								 | 
							
								//     if (distance <= _LODFadeDistance)
							 | 
						||
| 
								 | 
							
								//     {
							 | 
						||
| 
								 | 
							
								//         return clamp(1 - distance / _LODFadeDistance, 0, 1);
							 | 
						||
| 
								 | 
							
								//     }
							 | 
						||
| 
								 | 
							
								//     return 0;
							 | 
						||
| 
								 | 
							
								// }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								float CalculateLODFadeFirst(float cameraDistance, float nextLODDistance)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    float distance = nextLODDistance + _LODFadeDistance - cameraDistance;
							 | 
						||
| 
								 | 
							
								    if (distance <= _LODFadeDistance)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return clamp(distance/ _LODFadeDistance, 0, 1) * 2;
							 | 
						||
| 
								 | 
							
								        return clamp(distance * distance/ _LODFadeDistance, 0, 1);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return 1;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								float CalculateLODFadeMiddle(float thisLODDistance, float cameraDistance, float nextLODDistance)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (cameraDistance - thisLODDistance < _LODFadeDistance)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        float distance = cameraDistance - thisLODDistance;
							 | 
						||
| 
								 | 
							
								       // return clamp(distance * distance/ _LODFadeDistance, 0, 1);
							 | 
						||
| 
								 | 
							
								        return clamp(distance/ _LODFadeDistance, 0, 1) * 2;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (nextLODDistance + _LODFadeDistance - cameraDistance <= _LODFadeDistance)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        float distance = nextLODDistance + _LODFadeDistance - cameraDistance;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        //return clamp(distance * distance / _LODFadeDistance, 0, 1);
							 | 
						||
| 
								 | 
							
								        return clamp(distance/ _LODFadeDistance, 0, 1) * 2;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return 1;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								float CalculateDistanceFade(float cameraDistance, float cullDistance)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    float distance = cullDistance - cameraDistance;
							 | 
						||
| 
								 | 
							
								    if (distance <= _LODFadeDistance)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return clamp(1 - distance / _LODFadeDistance, 0, 1);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return 1;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								float4x4 inverse(float4x4 input)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    #define minor(a,b,c) determinant(float3x3(input.a, input.b, input.c))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    float4x4 cofactors = float4x4(
							 | 
						||
| 
								 | 
							
								        minor(_22_23_24, _32_33_34, _42_43_44),
							 | 
						||
| 
								 | 
							
								        -minor(_21_23_24, _31_33_34, _41_43_44),
							 | 
						||
| 
								 | 
							
								        minor(_21_22_24, _31_32_34, _41_42_44),
							 | 
						||
| 
								 | 
							
								        -minor(_21_22_23, _31_32_33, _41_42_43),
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        -minor(_12_13_14, _32_33_34, _42_43_44),
							 | 
						||
| 
								 | 
							
								        minor(_11_13_14, _31_33_34, _41_43_44),
							 | 
						||
| 
								 | 
							
								        -minor(_11_12_14, _31_32_34, _41_42_44),
							 | 
						||
| 
								 | 
							
								        minor(_11_12_13, _31_32_33, _41_42_43),
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        minor(_12_13_14, _22_23_24, _42_43_44),
							 | 
						||
| 
								 | 
							
								        -minor(_11_13_14, _21_23_24, _41_43_44),
							 | 
						||
| 
								 | 
							
								        minor(_11_12_14, _21_22_24, _41_42_44),
							 | 
						||
| 
								 | 
							
								        -minor(_11_12_13, _21_22_23, _41_42_43),
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        -minor(_12_13_14, _22_23_24, _32_33_34),
							 | 
						||
| 
								 | 
							
								        minor(_11_13_14, _21_23_24, _31_33_34),
							 | 
						||
| 
								 | 
							
								        -minor(_11_12_14, _21_22_24, _31_32_34),
							 | 
						||
| 
								 | 
							
								        minor(_11_12_13, _21_22_23, _31_32_33)
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								    #undef minor
							 | 
						||
| 
								 | 
							
								    return transpose(cofactors) / determinant(input);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								struct Ray
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    float3 origin;
							 | 
						||
| 
								 | 
							
								    float3 direction;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Ray CreateRay(float3 origin, float3 direction)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    Ray newRay;
							 | 
						||
| 
								 | 
							
								    newRay.origin = origin;
							 | 
						||
| 
								 | 
							
								    newRay.direction = direction;
							 | 
						||
| 
								 | 
							
								    return newRay;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								struct Bounds
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    float3 center;
							 | 
						||
| 
								 | 
							
								    float3 extents;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    float3 GetMin()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return center - extents;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    float3 GetMax()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return center + extents;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    void SetMinMax(float3 min, float3 max)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        extents = (max - min) * 0.5f;
							 | 
						||
| 
								 | 
							
								        center = min + extents;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    void Encapsulate(float3 targetPoint)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        SetMinMax(min(GetMin(), targetPoint), max(GetMax(), targetPoint));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool IntersectPlane(Ray ray, float3 planeOrigin, out float3 hitPoint)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    float3 planeNormal = -float3(0, 1, 0);
							 | 
						||
| 
								 | 
							
								    float denominator = dot(ray.direction, planeNormal);
							 | 
						||
| 
								 | 
							
								    if (denominator > 0.00001f)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        float t = dot(planeOrigin - ray.origin, planeNormal) / denominator;
							 | 
						||
| 
								 | 
							
								        hitPoint = ray.origin + ray.direction * t;
							 | 
						||
| 
								 | 
							
								        return true;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    hitPoint = float3(0, 0, 0);
							 | 
						||
| 
								 | 
							
								    return false;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Bounds GetShadowBounds(Bounds objectBounds, float3 lightDirection, float3 planeOrigin, out bool hitPlane)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    float3 objectBoundsMin = objectBounds.GetMin();
							 | 
						||
| 
								 | 
							
								    float3 objectBoundsMax = objectBounds.GetMax();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Ray p0 = CreateRay(float3(objectBoundsMin.x, objectBoundsMax.y, objectBoundsMin.z), lightDirection);
							 | 
						||
| 
								 | 
							
								    Ray p1 = CreateRay(float3(objectBoundsMin.x, objectBoundsMax.y, 0), lightDirection);
							 | 
						||
| 
								 | 
							
								    Ray p2 = CreateRay(float3(objectBoundsMax.x, objectBoundsMax.y, objectBoundsMin.z), lightDirection);
							 | 
						||
| 
								 | 
							
								    Ray p3 = CreateRay(objectBoundsMax, lightDirection);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    float3 hitPoint;
							 | 
						||
| 
								 | 
							
								    hitPlane = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (IntersectPlane(p0, planeOrigin, hitPoint))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        objectBounds.Encapsulate(hitPoint);
							 | 
						||
| 
								 | 
							
								        hitPlane = true;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (IntersectPlane(p1, planeOrigin, hitPoint))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        objectBounds.Encapsulate(hitPoint);
							 | 
						||
| 
								 | 
							
								        hitPlane = true;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (IntersectPlane(p2, planeOrigin, hitPoint))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        objectBounds.Encapsulate(hitPoint);
							 | 
						||
| 
								 | 
							
								        hitPlane = true;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (IntersectPlane(p3, planeOrigin, hitPoint))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        objectBounds.Encapsulate(hitPoint);
							 | 
						||
| 
								 | 
							
								        hitPlane = true;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return objectBounds;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool TestPlaneIntersection(Bounds bounds, float4 plane)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    float3 center = bounds.center;
							 | 
						||
| 
								 | 
							
								    float3 extents = bounds.extents;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    float3 planeNormal = plane.xyz;
							 | 
						||
| 
								 | 
							
								    float planeDistance = plane.w;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    float3 absNormal = float3(abs(planeNormal.x), abs(planeNormal.y), abs(planeNormal.z));
							 | 
						||
| 
								 | 
							
								    float r = extents.x * absNormal.x + extents.y * absNormal.y + extents.z * absNormal.z;
							 | 
						||
| 
								 | 
							
								    float s = planeNormal.x * center.x + planeNormal.y * center.y + planeNormal.z * center.z;
							 | 
						||
| 
								 | 
							
								    if (s + r < -planeDistance)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return false;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool BoundsIntersectsFrustum(Bounds bounds)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (TestPlaneIntersection(bounds, _VS_CameraFrustumPlane0) == false)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return false;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (TestPlaneIntersection(bounds, _VS_CameraFrustumPlane1) == false)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return false;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (TestPlaneIntersection(bounds, _VS_CameraFrustumPlane2) == false)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return false;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (TestPlaneIntersection(bounds, _VS_CameraFrustumPlane3) == false)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return false;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (TestPlaneIntersection(bounds, _VS_CameraFrustumPlane4) == false)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return false;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (TestPlaneIntersection(bounds, _VS_CameraFrustumPlane5) == false)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return false;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool IsShadowVisible(Bounds objectBounds, float3 lightDirection, float3 planeOrigin)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    bool hitPlane;
							 | 
						||
| 
								 | 
							
								    Bounds shadowBounds = GetShadowBounds(objectBounds, lightDirection, planeOrigin, hitPlane);
							 | 
						||
| 
								 | 
							
								    return hitPlane && BoundsIntersectsFrustum(shadowBounds);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[numthreads(32, 1, 1)]
							 | 
						||
| 
								 | 
							
								void GPUFrustumCulling(uint3 id : SV_DispatchThreadID)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    uint instanceId = id.x;
							 | 
						||
| 
								 | 
							
								    if (instanceId < _InstanceCount)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        IndirectShaderData instanceData;
							 | 
						||
| 
								 | 
							
								        instanceData.PositionMatrix = SourceShaderDataBuffer[id.x].PositionMatrix;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        instanceData.PositionMatrix._m03_m13_m23 += _FloatingOriginOffset.xyz;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        float DistanceFalloff = SourceShaderDataBuffer[id.x].ControlData.x;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        float itemCullDistance = _CullFarStart * DistanceFalloff;
							 | 
						||
| 
								 | 
							
								        float lod1Distance = clamp(_LOD1Distance * _LODFactor * _LODBias, 0, _CullFarStart);
							 | 
						||
| 
								 | 
							
								        float lod2Distance = clamp(_LOD2Distance * _LODFactor * _LODBias, 0, _CullFarStart);
							 | 
						||
| 
								 | 
							
								        float lod3Distance = clamp(_LOD3Distance * _LODFactor * _LODBias, 0, _CullFarStart);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        #define transformPosition mul(instanceData.PositionMatrix, float4(0,0,0,1)).xyz
							 | 
						||
| 
								 | 
							
								        float3 position = transformPosition + float3(0.0f, _BoundingSphereRadius * 0.5f, 0.0f);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (NoFrustumCulling)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            bool useLODFade = true;
							 | 
						||
| 
								 | 
							
								            float3 itempos = instanceData.PositionMatrix._m03_m13_m23;
							 | 
						||
| 
								 | 
							
								            float dist = distance(itempos, _WorldSpaceCameraPos.xyz);
							 | 
						||
| 
								 | 
							
								            if (dist < itemCullDistance)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                instanceData.InversePositionMatrix = inverse(instanceData.PositionMatrix);
							 | 
						||
| 
								 | 
							
								                float distanceFade = CalculateDistanceFade(dist, itemCullDistance);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                instanceData.ControlData = float4(0, 0, distanceFade, 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                if (UseLODs)
							 | 
						||
| 
								 | 
							
								                {
							 | 
						||
| 
								 | 
							
								                    if (_LODCount == 1)
							 | 
						||
| 
								 | 
							
								                    {
							 | 
						||
| 
								 | 
							
								                        lod1Distance = max(lod1Distance, itemCullDistance);
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    else if (_LODCount == 2)
							 | 
						||
| 
								 | 
							
								                    {
							 | 
						||
| 
								 | 
							
								                        lod2Distance = max(lod2Distance, itemCullDistance);
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    else if (_LODCount == 3)
							 | 
						||
| 
								 | 
							
								                    {
							 | 
						||
| 
								 | 
							
								                        lod3Distance = max(lod3Distance, itemCullDistance);
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    if (dist <= lod1Distance + _LODFadeDistance)
							 | 
						||
| 
								 | 
							
								                    {
							 | 
						||
| 
								 | 
							
								                        if (useLODFade)
							 | 
						||
| 
								 | 
							
								                        {
							 | 
						||
| 
								 | 
							
								                            float lodFade = CalculateLODFadeFirst(dist, lod1Distance);
							 | 
						||
| 
								 | 
							
								                            float lodFadeQuantified = 1 - clamp(round(lodFade * 16) / 16, 0.0625, 1);
							 | 
						||
| 
								 | 
							
								                            instanceData.ControlData =
							 | 
						||
| 
								 | 
							
								                                float4(lodFade, lodFadeQuantified, instanceData.ControlData.z, 0);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                        VisibleBufferLOD0.Append(instanceData);
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    if (dist <= lod2Distance + _LODFadeDistance && dist > lod1Distance)
							 | 
						||
| 
								 | 
							
								                    {
							 | 
						||
| 
								 | 
							
								                        if (useLODFade)
							 | 
						||
| 
								 | 
							
								                        {
							 | 
						||
| 
								 | 
							
								                            float lodFade = CalculateLODFadeMiddle(lod1Distance, dist, lod2Distance);
							 | 
						||
| 
								 | 
							
								                            float lodFadeQuantified = 1 - clamp(round(lodFade * 16) / 16, 0.0625, 1);
							 | 
						||
| 
								 | 
							
								                            lodFadeQuantified = 0;
							 | 
						||
| 
								 | 
							
								                            instanceData.ControlData =
							 | 
						||
| 
								 | 
							
								                                float4(lodFade, lodFadeQuantified, instanceData.ControlData.z, 1);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                        VisibleBufferLOD1.Append(instanceData);
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    if (dist <= lod3Distance + _LODFadeDistance && dist > lod2Distance)
							 | 
						||
| 
								 | 
							
								                    {
							 | 
						||
| 
								 | 
							
								                        if (useLODFade)
							 | 
						||
| 
								 | 
							
								                        {
							 | 
						||
| 
								 | 
							
								                            float lodFade = CalculateLODFadeMiddle(lod2Distance, dist, lod3Distance);
							 | 
						||
| 
								 | 
							
								                            float lodFadeQuantified = 1 - clamp(round(lodFade * 16) / 16, 0.0625, 1);
							 | 
						||
| 
								 | 
							
								                            lodFadeQuantified = 0.5;
							 | 
						||
| 
								 | 
							
								                            instanceData.ControlData =
							 | 
						||
| 
								 | 
							
								                                float4(lodFade, lodFadeQuantified, instanceData.ControlData.z, 2);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                        VisibleBufferLOD2.Append(instanceData);
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    if (dist > lod3Distance)
							 | 
						||
| 
								 | 
							
								                    {
							 | 
						||
| 
								 | 
							
								                        if (useLODFade)
							 | 
						||
| 
								 | 
							
								                        {
							 | 
						||
| 
								 | 
							
								                            float lodFade = CalculateLODFadeMiddle(lod3Distance, dist, itemCullDistance);
							 | 
						||
| 
								 | 
							
								                            float lodFadeQuantified = 1 - clamp(round(lodFade * 16) / 16, 0.0625, 1);
							 | 
						||
| 
								 | 
							
								                            instanceData.ControlData =
							 | 
						||
| 
								 | 
							
								                                float4(lodFade, lodFadeQuantified, instanceData.ControlData.z, 3);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                        VisibleBufferLOD3.Append(instanceData);
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else
							 | 
						||
| 
								 | 
							
								                {
							 | 
						||
| 
								 | 
							
								                    if (useLODFade)
							 | 
						||
| 
								 | 
							
								                    {
							 | 
						||
| 
								 | 
							
								                        float lodFade = CalculateLODFadeFirst(dist, itemCullDistance);
							 | 
						||
| 
								 | 
							
								                        float lodFadeQuantified = 1 - clamp(round(lodFade * 16) / 16, 0.0625, 1);
							 | 
						||
| 
								 | 
							
								                        instanceData.ControlData = float4(lodFade, lodFadeQuantified, instanceData.ControlData.z, 0);
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    VisibleBufferLOD0.Append(instanceData);
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            return;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        float4 CameraDistances0 = float4(
							 | 
						||
| 
								 | 
							
								            dot(_VS_CameraFrustumPlane0.xyz, position) + _VS_CameraFrustumPlane0.w,
							 | 
						||
| 
								 | 
							
								            dot(_VS_CameraFrustumPlane1.xyz, position) + _VS_CameraFrustumPlane1.w,
							 | 
						||
| 
								 | 
							
								            dot(_VS_CameraFrustumPlane2.xyz, position) + _VS_CameraFrustumPlane2.w,
							 | 
						||
| 
								 | 
							
								            dot(_VS_CameraFrustumPlane3.xyz, position) + _VS_CameraFrustumPlane3.w
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        float4 CameraDistances1 = float4(
							 | 
						||
| 
								 | 
							
								            dot(_VS_CameraFrustumPlane4.xyz, position) + _VS_CameraFrustumPlane4.w,
							 | 
						||
| 
								 | 
							
								            dot(_VS_CameraFrustumPlane5.xyz, position) + _VS_CameraFrustumPlane5.w,
							 | 
						||
| 
								 | 
							
								            0.0f,
							 | 
						||
| 
								 | 
							
								            0.0f
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (!(all(CameraDistances0 >= -_BoundingSphereRadius)
							 | 
						||
| 
								 | 
							
								            && all(CameraDistances1 >= -_BoundingSphereRadius)))
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            if (!ShadowCulling)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                return;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            bool useLODFade = true;
							 | 
						||
| 
								 | 
							
								            float3 itempos = instanceData.PositionMatrix._m03_m13_m23;
							 | 
						||
| 
								 | 
							
								            float dist = distance(itempos, _WorldSpaceCameraPos.xyz);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (dist < itemCullDistance)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                Bounds itemBounds;
							 | 
						||
| 
								 | 
							
								                itemBounds.center = itempos;
							 | 
						||
| 
								 | 
							
								                itemBounds.extents = _BoundsSize;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                if (IsShadowVisible(itemBounds, _LightDirection, _PlaneOrigin))
							 | 
						||
| 
								 | 
							
								                {
							 | 
						||
| 
								 | 
							
								                    instanceData.InversePositionMatrix = inverse(instanceData.PositionMatrix);
							 | 
						||
| 
								 | 
							
								                    float distanceFade = CalculateDistanceFade(dist, itemCullDistance);
							 | 
						||
| 
								 | 
							
								                    instanceData.ControlData = float4(0, 0, distanceFade, 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    if (UseLODs)
							 | 
						||
| 
								 | 
							
								                    {
							 | 
						||
| 
								 | 
							
								                        if (_LODCount == 1)
							 | 
						||
| 
								 | 
							
								                        {
							 | 
						||
| 
								 | 
							
								                            lod1Distance = max(lod1Distance, itemCullDistance);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                        else if (_LODCount == 2)
							 | 
						||
| 
								 | 
							
								                        {
							 | 
						||
| 
								 | 
							
								                            lod2Distance = max(lod2Distance, itemCullDistance);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                        else if (_LODCount == 3)
							 | 
						||
| 
								 | 
							
								                        {
							 | 
						||
| 
								 | 
							
								                            lod3Distance = max(lod3Distance, itemCullDistance);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                        if (dist <= lod1Distance + _LODFadeDistance)
							 | 
						||
| 
								 | 
							
								                        {
							 | 
						||
| 
								 | 
							
								                            if (useLODFade)
							 | 
						||
| 
								 | 
							
								                            {
							 | 
						||
| 
								 | 
							
								                                float lodFade = CalculateLODFadeFirst(dist, lod1Distance);
							 | 
						||
| 
								 | 
							
								                                float lodFadeQuantified = 1 - clamp(round(lodFade * 16) / 16, 0.0625, 1);
							 | 
						||
| 
								 | 
							
								                                instanceData.ControlData = float4(lodFade, lodFadeQuantified,
							 | 
						||
| 
								 | 
							
								                                                                  instanceData.ControlData.z, 0);
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                            ShadowBufferLOD0.Append(instanceData);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                        if (dist <= lod2Distance + _LODFadeDistance && dist > lod1Distance)
							 | 
						||
| 
								 | 
							
								                        {
							 | 
						||
| 
								 | 
							
								                            if (useLODFade)
							 | 
						||
| 
								 | 
							
								                            {
							 | 
						||
| 
								 | 
							
								                                float lodFade = CalculateLODFadeMiddle(lod1Distance, dist, lod2Distance);
							 | 
						||
| 
								 | 
							
								                                float lodFadeQuantified = 1 - clamp(round(lodFade * 16) / 16, 0.0625, 1);
							 | 
						||
| 
								 | 
							
								                                instanceData.ControlData = float4(lodFade, lodFadeQuantified,
							 | 
						||
| 
								 | 
							
								                                                                  instanceData.ControlData.z, 0);
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            ShadowBufferLOD1.Append(instanceData);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                        if (dist <= lod3Distance + _LODFadeDistance && dist > lod2Distance)
							 | 
						||
| 
								 | 
							
								                        {
							 | 
						||
| 
								 | 
							
								                            if (useLODFade)
							 | 
						||
| 
								 | 
							
								                            {
							 | 
						||
| 
								 | 
							
								                                float lodFade = CalculateLODFadeMiddle(lod2Distance, dist, lod3Distance);
							 | 
						||
| 
								 | 
							
								                                float lodFadeQuantified = 1 - clamp(round(lodFade * 16) / 16, 0.0625, 1);
							 | 
						||
| 
								 | 
							
								                                instanceData.ControlData = float4(lodFade, lodFadeQuantified,
							 | 
						||
| 
								 | 
							
								                                                                  instanceData.ControlData.z, 0);
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            ShadowBufferLOD2.Append(instanceData);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                        if (dist > lod3Distance)
							 | 
						||
| 
								 | 
							
								                        {
							 | 
						||
| 
								 | 
							
								                            if (useLODFade)
							 | 
						||
| 
								 | 
							
								                            {
							 | 
						||
| 
								 | 
							
								                                float lodFade = CalculateLODFadeMiddle(lod3Distance, dist, itemCullDistance);
							 | 
						||
| 
								 | 
							
								                                float lodFadeQuantified = 1 - clamp(round(lodFade * 16) / 16, 0.0625, 1);
							 | 
						||
| 
								 | 
							
								                                instanceData.ControlData = float4(lodFade, lodFadeQuantified,
							 | 
						||
| 
								 | 
							
								                                                                  instanceData.ControlData.z, 0);
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            ShadowBufferLOD3.Append(instanceData);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    else
							 | 
						||
| 
								 | 
							
								                    {
							 | 
						||
| 
								 | 
							
								                        if (useLODFade)
							 | 
						||
| 
								 | 
							
								                        {
							 | 
						||
| 
								 | 
							
								                            float lodFade = CalculateLODFadeFirst(dist, itemCullDistance);
							 | 
						||
| 
								 | 
							
								                            float lodFadeQuantified = 1 - clamp(round(lodFade * 16) / 16, 0.0625, 1);
							 | 
						||
| 
								 | 
							
								                            instanceData.ControlData =
							 | 
						||
| 
								 | 
							
								                                float4(lodFade, lodFadeQuantified, instanceData.ControlData.z, 0);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                        ShadowBufferLOD0.Append(instanceData);
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            bool useLODFade = true;
							 | 
						||
| 
								 | 
							
								            float3 itempos = instanceData.PositionMatrix._m03_m13_m23;
							 | 
						||
| 
								 | 
							
								            float dist = distance(itempos, _WorldSpaceCameraPos.xyz);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (dist < itemCullDistance + _LODFadeDistance)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                instanceData.InversePositionMatrix = inverse(instanceData.PositionMatrix);
							 | 
						||
| 
								 | 
							
								                float distanceFade = CalculateDistanceFade(dist, itemCullDistance);
							 | 
						||
| 
								 | 
							
								                instanceData.ControlData = float4(0, 0, distanceFade, 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                if (UseLODs)
							 | 
						||
| 
								 | 
							
								                {
							 | 
						||
| 
								 | 
							
								                    if (_LODCount == 1)
							 | 
						||
| 
								 | 
							
								                    {
							 | 
						||
| 
								 | 
							
								                        lod1Distance = max(lod1Distance, itemCullDistance);
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    else if (_LODCount == 2)
							 | 
						||
| 
								 | 
							
								                    {
							 | 
						||
| 
								 | 
							
								                        lod2Distance = max(lod2Distance, itemCullDistance);
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    else if (_LODCount == 3)
							 | 
						||
| 
								 | 
							
								                    {
							 | 
						||
| 
								 | 
							
								                        lod3Distance = max(lod3Distance, itemCullDistance);
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    if (dist <= lod1Distance + _LODFadeDistance)
							 | 
						||
| 
								 | 
							
								                    {
							 | 
						||
| 
								 | 
							
								                        if (useLODFade)
							 | 
						||
| 
								 | 
							
								                        {
							 | 
						||
| 
								 | 
							
								                            float lodFade = CalculateLODFadeFirst(dist, lod1Distance);
							 | 
						||
| 
								 | 
							
								                            float lodFadeQuantified = 1 - clamp(round(lodFade * 16) / 16, 0.0625, 1);
							 | 
						||
| 
								 | 
							
								                            instanceData.ControlData =
							 | 
						||
| 
								 | 
							
								                                float4(lodFade, lodFadeQuantified, instanceData.ControlData.z, 0);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                        VisibleBufferLOD0.Append(instanceData);
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    if (dist <= lod2Distance + _LODFadeDistance && dist > lod1Distance)
							 | 
						||
| 
								 | 
							
								                    {
							 | 
						||
| 
								 | 
							
								                        if (useLODFade)
							 | 
						||
| 
								 | 
							
								                        {
							 | 
						||
| 
								 | 
							
								                            float lodFade = CalculateLODFadeMiddle(lod1Distance, dist, lod2Distance);
							 | 
						||
| 
								 | 
							
								                            float lodFadeQuantified = 1 - clamp(round(lodFade * 16) / 16, 0.0625, 1);
							 | 
						||
| 
								 | 
							
								                            lodFadeQuantified = 0;
							 | 
						||
| 
								 | 
							
								                            instanceData.ControlData =
							 | 
						||
| 
								 | 
							
								                                float4(lodFade, lodFadeQuantified, instanceData.ControlData.z, 1);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                        VisibleBufferLOD1.Append(instanceData);
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    if (dist <= lod3Distance + _LODFadeDistance && dist > lod2Distance)
							 | 
						||
| 
								 | 
							
								                    {
							 | 
						||
| 
								 | 
							
								                        if (useLODFade)
							 | 
						||
| 
								 | 
							
								                        {
							 | 
						||
| 
								 | 
							
								                            float lodFade = CalculateLODFadeMiddle(lod2Distance, dist, lod3Distance);
							 | 
						||
| 
								 | 
							
								                            float lodFadeQuantified = 1 - clamp(round(lodFade * 16) / 16, 0.0625, 1);
							 | 
						||
| 
								 | 
							
								                            instanceData.ControlData =
							 | 
						||
| 
								 | 
							
								                                float4(lodFade, lodFadeQuantified, instanceData.ControlData.z, 2);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                        VisibleBufferLOD2.Append(instanceData);
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    if (dist > lod3Distance)
							 | 
						||
| 
								 | 
							
								                    {
							 | 
						||
| 
								 | 
							
								                        if (useLODFade)
							 | 
						||
| 
								 | 
							
								                        {
							 | 
						||
| 
								 | 
							
								                            float lodFade = CalculateLODFadeMiddle(lod3Distance, dist, itemCullDistance);
							 | 
						||
| 
								 | 
							
								                            float lodFadeQuantified = 1 - clamp(round(lodFade * 16) / 16, 0.0625, 1);
							 | 
						||
| 
								 | 
							
								                            instanceData.ControlData =
							 | 
						||
| 
								 | 
							
								                                float4(lodFade, lodFadeQuantified, instanceData.ControlData.z, 3);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                        VisibleBufferLOD3.Append(instanceData);
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else
							 | 
						||
| 
								 | 
							
								                {
							 | 
						||
| 
								 | 
							
								                    if (useLODFade)
							 | 
						||
| 
								 | 
							
								                    {
							 | 
						||
| 
								 | 
							
								                        float lodFade = CalculateLODFadeFirst(dist, itemCullDistance);
							 | 
						||
| 
								 | 
							
								                        float lodFadeQuantified = 1 - clamp(round(lodFade * 16) / 16, 0.0625, 1);
							 | 
						||
| 
								 | 
							
								                        instanceData.ControlData = float4(lodFade, lodFadeQuantified, instanceData.ControlData.z, 0);
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    VisibleBufferLOD0.Append(instanceData);
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 |