|
|
|
|
|
|
// Tweak parameters. |
|
|
|
#define SSS_BILATERAL_FILTER 1 |
|
|
|
#define SSS_USE_LDS_CACHE 1 |
|
|
|
#define SSS_TAA_INTEGRATION 1 // Smoother results at the cost of a tiny amount of flickering in under-sampled areas |
|
|
|
#define SSS_RANDOM_ROTATION 1 // Hides undersampling artifacts with high-frequency noise. TAA blurs the noise. |
|
|
|
#define SSS_ENABLE_NEAR_FIELD 0 // Greatly increases the number of samples. Comes at a high cost. |
|
|
|
#define SSS_USE_TANGENT_PLANE 0 // Improves the accuracy of the approximation(0 -> 1st order). High cost. Does not work with back-facing normals. |
|
|
|
#define SSS_CLAMP_ARTIFACT 0 // Reduces bleeding. Use with SSS_USE_TANGENT_PLANE. |
|
|
|
|
|
|
|
|
|
|
void EvaluateSample(uint i, uint n, uint profileID, uint iR, uint iP, float2 centerCoord, int2 cacheOffset, |
|
|
|
float3 shapeParam, float3 centerPosVS, float mmPerUnit, float2 pixelsPerMm, |
|
|
|
float3 tangentX, float3 tangentY, float4x4 projMatrix, |
|
|
|
float startAngle, float3 tangentX, float3 tangentY, float4x4 projMatrix, |
|
|
|
float r = _FilterKernels[profileID][i][iR]; |
|
|
|
float r = _FilterKernels[profileID][i][iR]; |
|
|
|
#if (SSS_TAA_INTEGRATION != 0) |
|
|
|
// Note that we repeat the pattern twice during the TAA cycle to reduce flickering. |
|
|
|
float sinPsi = _TaaFrameRotation.x; |
|
|
|
float cosPsi = _TaaFrameRotation.y; |
|
|
|
// The angle 'psi' is loop-invariant. All the trigonometry is done at compile time. |
|
|
|
// The angle 'psi' is loop-invariant. |
|
|
|
float sinPsi = sin(startAngle); |
|
|
|
float cosPsi = cos(startAngle); |
|
|
|
|
|
|
|
// cos(a + b) = cos(a) * cos(b) - sin(a) * sin(b) |
|
|
|
// sin(a + b) = sin(a) * cos(b) + cos(a) * sin(b) |
|
|
|
float cosSum = cos(phi) * cosPsi - sin(phi) * sinPsi; |
|
|
|
|
|
|
#else |
|
|
|
float2 vec = r * float2(cos(phi), sin(phi)); |
|
|
|
#endif |
|
|
|
|
|
|
|
// Compute the screen-space position and the squared distance (in mm) in the image plane. |
|
|
|
int2 position; float xy2; |
|
|
|
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
#if SSS_RANDOM_ROTATION |
|
|
|
float startAngle = TWO_PI * GenerateHashedRandomFloat(asuint(centerPosVS)); |
|
|
|
#else |
|
|
|
float startAngle = 0; |
|
|
|
#endif |
|
|
|
|
|
|
|
// Use more samples for SS regions larger than 5x5 pixels (rotated by 45 degrees). |
|
|
|
bool useNearFieldKernel = SSS_ENABLE_NEAR_FIELD && maxDistInPixels > SSS_LOD_THRESHOLD; |
|
|
|
|
|
|
|
|
|
|
// Integrate over the image or tangent plane in the view space. |
|
|
|
EvaluateSample(i, n, profileID, iR, iP, pixelCoord + 0.5, cacheOffset, |
|
|
|
shapeParam, centerPosVS, mmPerUnit, pixelsPerMm, |
|
|
|
tangentX, tangentY, projMatrix, |
|
|
|
startAngle, tangentX, tangentY, projMatrix, |
|
|
|
totalIrradiance, totalWeight); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
// Integrate over the image or tangent plane in the view space. |
|
|
|
EvaluateSample(i, n, profileID, iR, iP, pixelCoord + 0.5, cacheOffset, |
|
|
|
shapeParam, centerPosVS, mmPerUnit, pixelsPerMm, |
|
|
|
tangentX, tangentY, projMatrix, |
|
|
|
startAngle, tangentX, tangentY, projMatrix, |
|
|
|
totalIrradiance, totalWeight); |
|
|
|
} |
|
|
|
|