2021-09-09 20:42:29 -04:00

93 lines
3.3 KiB
HLSL

#ifndef UNITY_SCREEN_SPACE_TRACING_INCLUDED
#define UNITY_SCREEN_SPACE_TRACING_INCLUDED
// How this file works:
// This file is separated in two sections: 1. Library, 2. Constant Buffer Specific Signatures
//
// 1. Library
// This section contains all function and structures for the Screen Space Tracing.
//
// 2. Constant Buffer Specific Signatures
// This section defines signatures that will use specifics constant buffers.
// Thus you can use the Screen Space Tracing library with different settings.
// It can be usefull to use it for both reflection and refraction but with different settings' sets.
//
//
// To use this file:
// 1. Define the macro SSRTID
// 2. Include the file
// 3. Undef the macro SSRTID
//
//
// Example for reflection:
// #define SSRTID Reflection
// #include "ScreenSpaceTracing.hlsl"
// #undef SSRTID
//
// Use library here, like ScreenSpaceProxyRaycastReflection(...)
// -------------------------------------------------
// Output
// -------------------------------------------------
struct ScreenSpaceRayHit
{
uint2 positionSS; // Position of the hit point (SS)
float2 positionNDC; // Position of the hit point (NDC)
float linearDepth; // Linear depth of the hit point
};
struct ScreenSpaceProxyRaycastInput
{
float3 rayOriginWS; // Ray origin (WS)
float3 rayDirWS; // Ray direction (WS)
EnvLightData proxyData; // Proxy to use for raycasting
};
// -------------------------------------------------
// Algorithm: Scene Proxy Raycasting
// -------------------------------------------------
// We perform a raycast against a proxy volume that approximate the current scene.
// Is is a simple shape (Sphere, Box).
// -------------------------------------------------
bool ScreenSpaceProxyRaycastRefraction(ScreenSpaceProxyRaycastInput input, out ScreenSpaceRayHit hit)
{
// Initialize loop
ZERO_INITIALIZE(ScreenSpaceRayHit, hit);
float3x3 worldToPS = WorldToProxySpace(input.proxyData);
float3 rayOriginPS = WorldToProxyPosition(input.proxyData, worldToPS, input.rayOriginWS);
float3 rayDirPS = mul(input.rayDirWS, worldToPS);
float projectionDistance = 0.0;
switch(input.proxyData.influenceShapeType)
{
case ENVSHAPETYPE_SPHERE:
case ENVSHAPETYPE_SKY:
{
projectionDistance = IntersectSphereProxy(input.proxyData, rayDirPS, rayOriginPS);
break;
}
case ENVSHAPETYPE_BOX:
projectionDistance = IntersectBoxProxy(input.proxyData, rayDirPS, rayOriginPS);
break;
}
float3 hitPositionWS = input.rayOriginWS + input.rayDirWS * projectionDistance;
float4 hitPositionCS = ComputeClipSpacePosition(hitPositionWS, GetWorldToHClipMatrix());
float4 rayOriginCS = ComputeClipSpacePosition(input.rayOriginWS, GetWorldToHClipMatrix());
float2 hitPositionNDC = ComputeNormalizedDeviceCoordinates(hitPositionWS, GetWorldToHClipMatrix());
uint2 hitPositionSS = uint2(hitPositionNDC *_ScreenSize.xy);
float hitLinearDepth = hitPositionCS.w;
hit.positionNDC = hitPositionNDC;
hit.positionSS = hitPositionSS;
hit.linearDepth = hitLinearDepth;
bool hitSuccessful = hitLinearDepth > 0; // Negative means that the hit is behind the camera
return hitSuccessful;
}
#endif