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

189 lines
7.0 KiB
HLSL

#ifndef UNITY_RAYTRACING_INTERSECTION_INCLUDED
#define UNITY_RAYTRACING_INTERSECTION_INCLUDED
// Engine includes
#include "UnityRayTracingMeshUtils.cginc"
// Raycone structure that defines the stateof the ray
struct RayCone
{
float width;
float spreadAngle;
};
// Structure that defines the current state of the intersection
struct RayIntersection
{
// Origin of the current ray -- FIXME: can be obtained by WorldRayPosition(), should we remove it?
float3 origin;
// Direction of the current ray -- FIXME: can be obtained by WorldRayDirection(), should we remove it?
float3 incidentDirection;
// Distance of the intersection
float t;
// Value that holds the color of the ray
float3 color;
// Cone representation of the ray
RayCone cone;
// The remaining available depth for the current Ray
uint remainingDepth;
// Current sample index
uint sampleIndex;
// Ray counter (used for multibounce)
uint rayCount;
// Pixel coordinate from which the initial ray was launched
uint2 pixelCoord;
// Velocity for the intersection point
float velocity;
};
struct AttributeData
{
// Barycentric value of the intersection
float2 barycentrics;
};
// Macro that interpolate any attribute using barycentric coordinates
#define INTERPOLATE_RAYTRACING_ATTRIBUTE(A0, A1, A2, BARYCENTRIC_COORDINATES) (A0 * BARYCENTRIC_COORDINATES.x + A1 * BARYCENTRIC_COORDINATES.y + A2 * BARYCENTRIC_COORDINATES.z)
// Structure to fill for intersections
struct IntersectionVertex
{
// Object space normal of the vertex
float3 normalOS;
// Object space tangent of the vertex
float4 tangentOS;
// UV coordinates
float4 texCoord0;
float4 texCoord1;
float4 texCoord2;
float4 texCoord3;
float4 color;
#ifdef USE_RAY_CONE_LOD
// Value used for LOD sampling
float triangleArea;
float texCoord0Area;
float texCoord1Area;
float texCoord2Area;
float texCoord3Area;
#endif
};
// Fetch the intersetion vertex data for the target vertex
void FetchIntersectionVertex(uint vertexIndex, out IntersectionVertex outVertex)
{
outVertex.normalOS = UnityRayTracingFetchVertexAttribute3(vertexIndex, kVertexAttributeNormal);
#ifdef ATTRIBUTES_NEED_TANGENT
outVertex.tangentOS = UnityRayTracingFetchVertexAttribute4(vertexIndex, kVertexAttributeTangent);
#else
outVertex.tangentOS = 0.0;
#endif
#ifdef ATTRIBUTES_NEED_TEXCOORD0
outVertex.texCoord0 = UnityRayTracingFetchVertexAttribute4(vertexIndex, kVertexAttributeTexCoord0);
#else
outVertex.texCoord0 = 0.0;
#endif
#ifdef ATTRIBUTES_NEED_TEXCOORD1
outVertex.texCoord1 = UnityRayTracingFetchVertexAttribute4(vertexIndex, kVertexAttributeTexCoord1);
#else
outVertex.texCoord1 = 0.0;
#endif
#ifdef ATTRIBUTES_NEED_TEXCOORD2
outVertex.texCoord2 = UnityRayTracingFetchVertexAttribute4(vertexIndex, kVertexAttributeTexCoord2);
#else
outVertex.texCoord2 = 0.0;
#endif
#ifdef ATTRIBUTES_NEED_TEXCOORD3
outVertex.texCoord3 = UnityRayTracingFetchVertexAttribute4(vertexIndex, kVertexAttributeTexCoord3);
#else
outVertex.texCoord3 = 0.0;
#endif
#ifdef ATTRIBUTES_NEED_COLOR
outVertex.color = UnityRayTracingFetchVertexAttribute4(vertexIndex, kVertexAttributeColor);
#else
outVertex.color = 0.0;
#endif
}
void GetCurrentIntersectionVertex(AttributeData attributeData, out IntersectionVertex outVertex)
{
// Fetch the indices of the currentr triangle
uint3 triangleIndices = UnityRayTracingFetchTriangleIndices(PrimitiveIndex());
// Fetch the 3 vertices
IntersectionVertex v0, v1, v2;
FetchIntersectionVertex(triangleIndices.x, v0);
FetchIntersectionVertex(triangleIndices.y, v1);
FetchIntersectionVertex(triangleIndices.z, v2);
// Compute the full barycentric coordinates
float3 barycentricCoordinates = float3(1.0 - attributeData.barycentrics.x - attributeData.barycentrics.y, attributeData.barycentrics.x, attributeData.barycentrics.y);
// Interpolate all the data
outVertex.normalOS = INTERPOLATE_RAYTRACING_ATTRIBUTE(v0.normalOS, v1.normalOS, v2.normalOS, barycentricCoordinates);
#ifdef ATTRIBUTES_NEED_TANGENT
outVertex.tangentOS = INTERPOLATE_RAYTRACING_ATTRIBUTE(v0.tangentOS, v1.tangentOS, v2.tangentOS, barycentricCoordinates);
#else
outVertex.tangentOS = 0.0;
#endif
#ifdef ATTRIBUTES_NEED_TEXCOORD0
outVertex.texCoord0 = INTERPOLATE_RAYTRACING_ATTRIBUTE(v0.texCoord0, v1.texCoord0, v2.texCoord0, barycentricCoordinates);
#else
outVertex.texCoord0 = 0.0;
#endif
#ifdef ATTRIBUTES_NEED_TEXCOORD1
outVertex.texCoord1 = INTERPOLATE_RAYTRACING_ATTRIBUTE(v0.texCoord1, v1.texCoord1, v2.texCoord1, barycentricCoordinates);
#else
outVertex.texCoord1 = 0.0;
#endif
#ifdef ATTRIBUTES_NEED_TEXCOORD2
outVertex.texCoord2 = INTERPOLATE_RAYTRACING_ATTRIBUTE(v0.texCoord2, v1.texCoord2, v2.texCoord2, barycentricCoordinates);
#else
outVertex.texCoord2 = 0.0;
#endif
#ifdef ATTRIBUTES_NEED_TEXCOORD3
outVertex.texCoord3 = INTERPOLATE_RAYTRACING_ATTRIBUTE(v0.texCoord3, v1.texCoord3, v2.texCoord3, barycentricCoordinates);
#else
outVertex.texCoord3 = 0.0;
#endif
#ifdef ATTRIBUTES_NEED_COLOR
outVertex.color = INTERPOLATE_RAYTRACING_ATTRIBUTE(v0.color, v1.color, v2.color, barycentricCoordinates);
#else
outVertex.color = 0.0;
#endif
#ifdef USE_RAY_CONE_LOD
// Compute the lambda value (area computed in object space)
outVertex.triangleArea = length(cross(v1.positionOS - v0.positionOS, v2.positionOS - v0.positionOS));
outVertex.texCoord0Area = abs((v1.texCoord0.x - v0.texCoord0.x) * (v2.texCoord0.y - v0.texCoord0.y) - (v2.texCoord0.x - v0.texCoord0.x) * (v1.texCoord0.y - v0.texCoord0.y));
outVertex.texCoord1Area = abs((v1.texCoord1.x - v0.texCoord1.x) * (v2.texCoord1.y - v0.texCoord1.y) - (v2.texCoord1.x - v0.texCoord1.x) * (v1.texCoord1.y - v0.texCoord1.y));
outVertex.texCoord2Area = abs((v1.texCoord2.x - v0.texCoord2.x) * (v2.texCoord2.y - v0.texCoord2.y) - (v2.texCoord2.x - v0.texCoord2.x) * (v1.texCoord2.y - v0.texCoord2.y));
outVertex.texCoord3Area = abs((v1.texCoord3.x - v0.texCoord3.x) * (v2.texCoord3.y - v0.texCoord3.y) - (v2.texCoord3.x - v0.texCoord3.x) * (v1.texCoord3.y - v0.texCoord3.y));
#endif
}
// Compute the proper world space geometric normal from the intersected triangle
void GetCurrentIntersectionGeometricNormal(AttributeData attributeData, out float3 geomNormalWS)
{
uint3 triangleIndices = UnityRayTracingFetchTriangleIndices(PrimitiveIndex());
float3 p0 = UnityRayTracingFetchVertexAttribute3(triangleIndices.x, kVertexAttributePosition);
float3 p1 = UnityRayTracingFetchVertexAttribute3(triangleIndices.y, kVertexAttributePosition);
float3 p2 = UnityRayTracingFetchVertexAttribute3(triangleIndices.z, kVertexAttributePosition);
geomNormalWS = normalize(mul(cross(p1 - p0, p2 - p0), (float3x3)WorldToObject3x4()));
}
#endif // UNITY_RAYTRACING_INTERSECTION_INCLUDED