84 lines
2.6 KiB
HLSL
84 lines
2.6 KiB
HLSL
|
#ifndef GEO_UTILITIES_H
|
||
|
#define GEO_UTILITIES_H
|
||
|
|
||
|
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
|
||
|
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Packing.hlsl"
|
||
|
|
||
|
struct CylinderBound
|
||
|
{
|
||
|
float3 center;
|
||
|
float3 axis;
|
||
|
float halfHeight;
|
||
|
float capRadius;
|
||
|
};
|
||
|
|
||
|
struct SphereBound
|
||
|
{
|
||
|
float3 center;
|
||
|
float radius;
|
||
|
};
|
||
|
|
||
|
float CompleteSinCos(float sinOrCos)
|
||
|
{
|
||
|
return sqrt(max(1.0f - sinOrCos*sinOrCos, 0.0f));
|
||
|
}
|
||
|
|
||
|
float2 ProjectedHalfLengths(CylinderBound cylinder, float3 planeNormal)
|
||
|
{
|
||
|
float absCosTheta = abs(dot(planeNormal, cylinder.axis));
|
||
|
float sinTheta = CompleteSinCos(absCosTheta);
|
||
|
|
||
|
float h = cylinder.halfHeight;
|
||
|
float r = cylinder.capRadius;
|
||
|
|
||
|
float halfLengthAlongNormal = absCosTheta * h + sinTheta * r;
|
||
|
float halfLengthInPlane = max(sinTheta * h + absCosTheta * r, r); // ellipse, so use max of two axis lengths
|
||
|
|
||
|
return float2(halfLengthInPlane, halfLengthAlongNormal);
|
||
|
}
|
||
|
|
||
|
struct BoundingObjectData
|
||
|
{
|
||
|
float3 frontCenterPosRWS;
|
||
|
float2 centerPosNDC;
|
||
|
float2 radialPosNDC;
|
||
|
};
|
||
|
|
||
|
BoundingObjectData CalculateBoundingObjectData(SphereBound boundingSphere,
|
||
|
float4x4 viewProjMatrix,
|
||
|
float4 viewOriginWorldSpace,
|
||
|
float4 radialDirWorldSpace,
|
||
|
float4 facingDirWorldSpace)
|
||
|
{
|
||
|
const float3 centerPosRWS = boundingSphere.center - viewOriginWorldSpace.xyz;
|
||
|
|
||
|
const float3 radialVec = abs(boundingSphere.radius) * radialDirWorldSpace.xyz;
|
||
|
const float3 facingVec = abs(boundingSphere.radius) * facingDirWorldSpace.xyz;
|
||
|
|
||
|
BoundingObjectData data;
|
||
|
data.centerPosNDC = ComputeNormalizedDeviceCoordinates(centerPosRWS, viewProjMatrix);
|
||
|
data.radialPosNDC = ComputeNormalizedDeviceCoordinates(centerPosRWS + radialVec, viewProjMatrix);
|
||
|
data.frontCenterPosRWS = centerPosRWS + facingVec;
|
||
|
return data;
|
||
|
}
|
||
|
|
||
|
BoundingObjectData CalculateBoundingObjectData(CylinderBound cylinderBound,
|
||
|
float4x4 viewProjMatrix,
|
||
|
float4 viewOriginWorldSpace,
|
||
|
float4 radialDirWorldSpace,
|
||
|
float4 facingDirWorldSpace)
|
||
|
{
|
||
|
const float3 centerPosRWS = cylinderBound.center - viewOriginWorldSpace.xyz;
|
||
|
|
||
|
const float2 halfLengths = ProjectedHalfLengths(cylinderBound, facingDirWorldSpace.xyz);
|
||
|
const float3 radialVec = halfLengths.x * radialDirWorldSpace.xyz;
|
||
|
|
||
|
BoundingObjectData data;
|
||
|
data.centerPosNDC = ComputeNormalizedDeviceCoordinates(centerPosRWS, viewProjMatrix);
|
||
|
data.radialPosNDC = ComputeNormalizedDeviceCoordinates(centerPosRWS + radialVec, viewProjMatrix);
|
||
|
data.frontCenterPosRWS = centerPosRWS + halfLengths.y * facingDirWorldSpace.xyz;
|
||
|
return data;
|
||
|
}
|
||
|
|
||
|
#endif
|