#ifndef _PATHTRACING_PATHTRACINGCOMMON_HLSL_
#define _PATHTRACING_PATHTRACINGCOMMON_HLSL_
#pragma warning(error: 3206) // Implicit truncation of vector type
#include "Packages/com.unity.render-pipelines.core/Runtime/Sampling/Common.hlsl"
#include "Packages/com.unity.render-pipelines.core/Runtime/UnifiedRayTracing/Common.hlsl"
#include "Packages/com.unity.render-pipelines.core/Runtime/UnifiedRayTracing/CommonStructs.hlsl"
#include "Packages/com.unity.render-pipelines.core/Runtime/UnifiedRayTracing/FetchGeometry.hlsl"
#define LIGHT_SAMPLING 0
#define BRDF_SAMPLING 1
#define MIS 2
// Force uniform sampling of the skybox for debugging / ground truth generation
//#define UNIFORM_ENVSAMPLING
// Emissive mesh sampling: we combine explicit light and brdf sampling using MIS.
// We can disable MIS and use exclusively one of the two sampling techniques with the EMISSIVE_SAMPLING define.
#ifndef EMISSIVE_SAMPLING
#define EMISSIVE_SAMPLING BRDF_SAMPLING
#endif
#define SPOT_LIGHT 0
#define DIRECTIONAL_LIGHT 1
#define POINT_LIGHT 2
#define RECTANGULAR_LIGHT 3
#define DISC_LIGHT 4
#define BOX_LIGHT 5
#define EMISSIVE_MESH 8 // Must match the variable in UnityEngine.PathTracing.Core.World
#define ENVIRONMENT_LIGHT 9 // Must match the variable in UnityEngine.PathTracing.Core.World
#define LIGHT_PICKING_METHOD_UNIFORM 0
#define LIGHT_PICKING_METHOD_RESERVOIR_GRID 1
#define LIGHT_PICKING_METHOD_LIGHT_GRID 2
#define DIRECT_RAY_VIS_MASK 1u
#define INDIRECT_RAY_VIS_MASK 2u
#define SHADOW_RAY_VIS_MASK 4u
// warning: bits 8u and 16u are used for lightmap LODs
#define MAX_TRANSMISSION_BOUNCES 6
struct HitEntry
{
uint instanceID;
uint primitiveIndex;
float2 barycentrics;
bool IsValid()
{
return instanceID != -1;
}
};
struct PixelState
{
float3 radiance;
float3 avgLightingDir;
float2 coord;
float2 motionVector;
float3 normal;
uint2 launchIndex;
uint2 launchDim;
float depth;
int bounces;
};
struct PTLight
{
float3 position;
int type;
float3 intensity;
int castsShadows;
float3 forward;
int contributesToDirectLighting;
float4 attenuation;
float3 up;
float width;
float3 right;
float height;
uint layerMask;
float indirectScale;
float2 spotAngle;
float range;
int shadowMaskChannel;
int falloffIndex;
float shadowRadius;
int cookieIndex;
};
int GetMeshLightInstanceID(PTLight light)
{
return light.height;
}
float4 GetColumn(float4x4 mat, int colIndex)
{
return float4(mat[0][3], mat[1][3], mat[2][3], mat[3][3]);
}
// Photometric RGB -> (Perceived) Luminance / digital ITU BT.709 (https://www.itu.int/rec/R-REC-BT.709)
float Luminance(float3 color)
{
const float3 weights = float3(0.2126f, 0.7152f, 0.0722f);
return dot(color, weights);
}
float3 EvalDiffuseBrdf(float3 albedo)
{
return albedo / PI;
}
float ClampedCosine(float3 normal, float3 direction)
{
return saturate(dot(normal, direction));
}
struct PTHitGeom
{
float3 worldPosition;
float3 lastWorldPosition;
float3 worldNormal;
float3 worldFaceNormal;
float2 uv0;
float2 uv1;
float triangleArea;
uint renderingLayerMask;
void FixNormals(float3 rayDirection)
{
worldFaceNormal = dot(rayDirection, worldFaceNormal) >= 0 ? -worldFaceNormal : worldFaceNormal;
worldNormal = dot(worldNormal, worldFaceNormal) < 0 ? -worldNormal : worldNormal;
}
float3 NextRayOrigin()
{
return OffsetRayOrigin(worldPosition, worldFaceNormal);
}
float3 NextTransmissionRayOrigin()
{
return OffsetRayOrigin(worldPosition, -worldFaceNormal);
}
};
PTHitGeom GetHitGeomInfo(UnifiedRT::InstanceData instanceInfo, UnifiedRT::Hit hit)
{
UnifiedRT::HitGeomAttributes attributes = UnifiedRT::FetchHitGeomAttributes(hit);
PTHitGeom res;
res.worldPosition = mul(instanceInfo.localToWorld, float4(attributes.position, 1)).xyz;
res.lastWorldPosition = mul(instanceInfo.previousLocalToWorld, float4(attributes.position, 1)).xyz;
res.worldNormal = normalize(mul((float3x3)instanceInfo.localToWorldNormals, attributes.normal));
res.worldFaceNormal = mul((float3x3)instanceInfo.localToWorldNormals, attributes.faceNormal);
res.uv0 = attributes.uv0.xy;
res.uv1 = attributes.uv1.xy;
res.renderingLayerMask = instanceInfo.renderingLayerMask;
// compute the area of the hit point (used for MIS)
float l = length(res.worldFaceNormal);
res.triangleArea = 0.5 * determinant(instanceInfo.localToWorld) * l;
// normalize the face normal
if (l > 0)
res.worldFaceNormal /= l;
return res;
}
void FetchGeomAttributes(UnifiedRT::Hit hit, int geometryIndex, out float3 position, out float3 normal, out float3 faceNormal)
{
position = normal = faceNormal = 0.0f;
// hit.instanceID is set to be the same as the submeshIndex
// geometryIndex always points to the first submesh, the others submeshes follow in order in the geometry array:
// submeshGeomIndex = geometryIndex + randomUVHit.instanceID
if (!hit.IsValid())
return;
UnifiedRT::HitGeomAttributes hitAttribs = UnifiedRT::FetchHitGeomAttributes(geometryIndex + hit.instanceID, hit.primitiveIndex, hit.uvBarycentrics);
position = hitAttribs.position;
normal = hitAttribs.normal;
faceNormal = hitAttribs.faceNormal;
}
void FetchGeomAttributes(UnifiedRT::Hit hit, int geometryIndex, out float3 position, out float3 normal, out float3 faceNormal, out float2 uv1)
{
position = normal = faceNormal = 0.0f;
uv1 = 0.0f;
// hit.instanceID is set to be the same as the submeshIndex
// geometryIndex always points to the first submesh, the others submeshes follow in order in the geometry array:
// submeshGeomIndex = geometryIndex + randomUVHit.instanceID
if (!hit.IsValid())
return;
UnifiedRT::HitGeomAttributes hitAttribs = UnifiedRT::FetchHitGeomAttributes(geometryIndex + hit.instanceID, hit.primitiveIndex, hit.uvBarycentrics);
position = hitAttribs.position;
normal = hitAttribs.normal;
faceNormal = hitAttribs.faceNormal;
uv1 = hitAttribs.uv1;
}
#endif