#include "Common.hlsl"
#include "PatchUtil.hlsl"
#include "Packages/com.unity.render-pipelines.core/Runtime/UnifiedRayTracing/FetchGeometry.hlsl"
#include "Packages/com.unity.render-pipelines.core/Runtime/UnifiedRayTracing/TraceRayAndQueryHit.hlsl"
#include "Packages/com.unity.render-pipelines.core/Runtime/UnifiedRayTracing/Common.hlsl"
#include "Packages/com.unity.render-pipelines.core/Runtime/PathTracing/MaterialPool/MaterialPool.hlsl"
struct SurfaceGeometry
{
float3 position;
float3 normal;
float2 uv0;
float2 uv1;
};
SurfaceGeometry FetchSurfaceGeometry(UnifiedRT::InstanceData instanceInfo, UnifiedRT::Hit hit)
{
UnifiedRT::HitGeomAttributes attributes = UnifiedRT::FetchHitGeomAttributes(hit);
SurfaceGeometry res;
res.position = mul(instanceInfo.localToWorld, float4(attributes.position, 1)).xyz;
res.normal = normalize(mul((float3x3)instanceInfo.localToWorldNormals, attributes.faceNormal));
res.uv0 = attributes.uv0.xy;
res.uv1 = attributes.uv1.xy;
return res;
}
struct MaterialPoolParamSet
{
StructuredBuffer<MaterialPool::MaterialEntry> materialEntries;
Texture2DArray<float4> albedoTextures;
Texture2DArray<float4> transmissionTextures;
Texture2DArray<float4> emissionTextures;
SamplerState emissionSampler;
SamplerState albedoSampler;
SamplerState transmissionSampler;
float atlasTexelSize; // The size of 1 texel in the atlases above
float albedoBoost;
};
static const float3 invalidRadianceSample = float3(-1.0f, -1.0f, -1.0f);
float3 SampleOutgoingRadianceAssumingLambertianBrdf(
float3 position,
float3 normal,
UnifiedRT::DispatchInfo dispatchInfo,
UnifiedRT::RayTracingAccelStruct accelStruct,
float3 dirLightDirection,
float3 dirLightIntensity,
bool multiBounce,
IrradianceBufferType patchIrradiances,
StructuredBuffer<uint> cellPatchIndices,
uint gridSize,
StructuredBuffer<int3> cascadeOffsets,
float3 gridTargetPos,
uint cascadeCount,
float voxelMinSize,
float3 albedo,
float3 emission)
{
float3 radianceSample = 0.0f;
if (any(dirLightIntensity != 0.0f))
{
const float worldHitNormalDotSunDir = dot(dirLightDirection, normal);
if (worldHitNormalDotSunDir < 0.0f)
{
UnifiedRT::Ray ray2;
ray2.origin = OffsetRayOrigin(position, normal);
ray2.direction = -dirLightDirection;
ray2.tMin = 0;
ray2.tMax = FLT_MAX;
UnifiedRT::Hit hitResult2 = UnifiedRT::TraceRayClosestHit(dispatchInfo, accelStruct, 0xFFFFFFFF, ray2, UnifiedRT::kRayFlagNone);
if (!hitResult2.IsValid())
{
radianceSample += dirLightIntensity * dot(-dirLightDirection, normal);
}
}
}
if (multiBounce)
{
float3 cacheRead = PatchUtil::ReadPlanarIrradiance(gridTargetPos, patchIrradiances, cellPatchIndices, gridSize, cascadeOffsets, cascadeCount, voxelMinSize, position, normal);
if (all(cacheRead != PatchUtil::invalidIrradiance))
radianceSample += cacheRead;
}
radianceSample *= albedo / PI;
radianceSample += emission;
return radianceSample;
}
float3 SampleIncomingRadianceAssumingLambertianBrdf(
UnifiedRT::DispatchInfo dispatchInfo,
UnifiedRT::RayTracingAccelStruct accelStruct,
UnifiedRT::Ray ray,
MaterialPoolParamSet matPoolParams,
float3 dirLightDirection,
float3 dirLightIntensity,
bool multiBounce,
TextureCube<float3> envTex,
SamplerState envSampler,
IrradianceBufferType patchIrradiances,
StructuredBuffer<uint> cellPatchIndices,
uint gridSize,
StructuredBuffer<int3> cascadeOffsets,
float3 gridTargetPos,
uint cascadeCount,
float voxelMinSize)
{
UnifiedRT::Hit hitResult = UnifiedRT::TraceRayClosestHit(dispatchInfo, accelStruct, 0xFFFFFFFF, ray, UnifiedRT::kRayFlagNone);
float3 radianceSample;
if (hitResult.IsValid())
{
if (!hitResult.isFrontFace)
{
radianceSample = invalidRadianceSample;
}
else
{
const UnifiedRT::InstanceData hitInstance = UnifiedRT::GetInstance(hitResult.instanceID);
const SurfaceGeometry hitGeo = FetchSurfaceGeometry(hitInstance, hitResult);
const MaterialPool::MaterialProperties hitMat = MaterialPool::LoadMaterialProperties(
matPoolParams.materialEntries,
matPoolParams.albedoTextures,
matPoolParams.albedoSampler,
matPoolParams.transmissionTextures,
matPoolParams.transmissionSampler,
matPoolParams.emissionTextures,
matPoolParams.emissionSampler,
matPoolParams.albedoBoost,
matPoolParams.atlasTexelSize,
hitInstance.userMaterialID,
hitGeo.uv0,
hitGeo.uv1);
radianceSample = SampleOutgoingRadianceAssumingLambertianBrdf(
hitGeo.position,
hitGeo.normal,
dispatchInfo,
accelStruct,
dirLightDirection,
dirLightIntensity,
multiBounce,
patchIrradiances,
cellPatchIndices,
gridSize,
cascadeOffsets,
gridTargetPos,
cascadeCount,
voxelMinSize,
hitMat.baseColor,
hitMat.emissive);
}
}
else
{
radianceSample = envTex.SampleLevel(envSampler, ray.direction, 0);
}
return radianceSample;
}