官网地址:
TraceRay function - Win32 apps | Microsoft Learn
Template<payload_t>
void TraceRay(RaytracingAccelerationStructure AccelerationStructure,
uint RayFlags,
uint InstanceInclusionMask,
uint RayContributionToHitGroupIndex,
uint MultiplierForGeometryContributionToHitGroupIndex,
uint MissShaderIndex,
RayDesc Ray,
inout payload_t Payload);
RayFlags: RAY_FLAG enumeration - Win32 apps | Microsoft Learn
enum RAY_FLAG : uint
{
RAY_FLAG_NONE = 0x00,
RAY_FLAG_FORCE_OPAQUE = 0x01,
RAY_FLAG_FORCE_NON_OPAQUE = 0x02,
RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH = 0x04,
RAY_FLAG_SKIP_CLOSEST_HIT_SHADER = 0x08,
RAY_FLAG_CULL_BACK_FACING_TRIANGLES = 0x10,
RAY_FLAG_CULL_FRONT_FACING_TRIANGLES = 0x20,
RAY_FLAG_CULL_OPAQUE = 0x40,
RAY_FLAG_CULL_NON_OPAQUE = 0x80,
RAY_FLAG_SKIP_TRIANGLES = 0x100,
RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES = 0x200,
};
InstanceInclusionMask: [shader/shared/RayTracingDefinitions.h]
#define RAY_TRACING_MASK_OPAQUE 0x01 // Opaque and alpha tested meshes and particles (e.g. used by reflection, shadow, AO and GI tracing passes)
#define RAY_TRACING_MASK_TRANSLUCENT 0x02 // Opaque and alpha tested meshes and particles (e.g. used by translucency tracing pass)
#define RAY_TRACING_MASK_THIN_SHADOW 0x04 // Whether the thin geometry (e.g. hair) is visible for shadow rays
#define RAY_TRACING_MASK_SHADOW 0x08 // Whether the geometry is visible for shadow rays
#define RAY_TRACING_MASK_ALL 0xFF
Ray: RayDesc structure - Win32 apps | Microsoft Learn
struct RayDesc
{
float3 Origin;
float TMin;
float3 Direction;
float TMax;
};
RayContributionToHitGroupIndex MultiplierForGeometryContributionToShaderIndex:
[shader/shared/RayTracingDefinitions.h]
#define RAY_TRACING_SHADER_SLOT_MATERIAL 0
#define RAY_TRACING_SHADER_SLOT_SHADOW 1
#define RAY_TRACING_NUM_SHADER_SLOTS 2
MissShaderIndex: [shader/shared/RayTracingDefinitions.h]
#define RAY_TRACING_MISS_SHADER_SLOT_DEFAULT 0 // Main miss shader that simply sets HitT to a "miss" value (see FMinimalPayload::SetMiss())
#define RAY_TRACING_MISS_SHADER_SLOT_LIGHTING 1 // Miss shader that may be used to evaluate light source radiance in ray traced reflections and translucency
#define RAY_TRACING_NUM_MISS_SHADER_SLOTS 2
UE4:
struct FMinimalPayload
{
float HitT; // Distance from ray origin to the intersection point in the ray direction. Negative on miss.
bool IsMiss() { return HitT < 0; }
bool IsHit() { return !IsMiss(); }
void SetMiss() { HitT = -1; }
};
#define RAY_TRACING_BLEND_MODE_OPAQUE 0
#define RAY_TRACING_BLEND_MODE_ALPHA_COMPOSITE 1
#define RAY_TRACING_BLEND_MODE_TRANSLUCENT 2
#define RAY_TRACING_BLEND_MODE_ADDITIVE 3
#define RAY_TRACING_BLEND_MODE_MODULATE 4
#define RAY_TRACING_BLEND_MODE_ALPHA_HOLDOUT 5
// Check how Flags are packed in the FPackedMaterialClosestHitPayload before adding to ensure bits are free
#define RAY_TRACING_PAYLOAD_FLAG_FRONT_FACE (1 << 0) // Indicates that ray has hit front face of a primitive. Set by closest hit shader.
#define RAY_TRACING_PAYLOAD_FLAG_MINIMAL_PAYLOAD (1 << 1) // Indicates that closest hit shader should only fill FMinimalPayload (HitT), skipping full material evaluation. Set by RayGen shader, before TraceRay().
#define RAY_TRACING_PAYLOAD_FLAG_ENABLE_SKY_LIGHT_CONTRIBUTION (1 << 2) // Indicates that hit shaders should add in the Sky Light contribution in their output. Set by RayGen shader, before TraceRay().
#define RAY_TRACING_PAYLOAD_FLAG_IGNORE_TRANSLUCENT (1 << 3) // Indicates that translucent materials should be ignored by IgnoreHit() in anyhit shaders.
struct FMaterialClosestHitPayload : FMinimalPayload
{
// Unpacked Packed
// offset bytes
// float FMinimalPayload::HitT // 0 4 32bits
FRayCone RayCone; // 4 8 64bits
float3 Radiance; // 8 6 48bits
float3 WorldNormal; // 24 6 48bits
float3 BaseColor; // 36 6 48bits
float3 DiffuseColor; // 48 0 (derived)
float3 SpecularColor; // 60 0 (derived)
float Opacity; // 72 2 16bits
float Metallic; // 76 1 8bits
float Specular; // 80 1 8bits
float Roughness; // 84 2 16bits
float Ior; // 88 2 16bits
uint ShadingModelID; // 92 1 4bits
uint BlendingMode; // 96 0 4bits (packed with ShadingModelID)
uint PrimitiveLightingChannelMask; // 100 0 3bits (packed with ShadingModelID)
float4 CustomData; // 104 4 32bits
float GBufferAO; // 120 0 (removed)
float3 IndirectIrradiance; // 124 0 48bits -- gbuffer only has float payload and there are truncation HLSL warnings
// Quite some code assume FRayHitInfo has a WorldPos
// So keep it here and force to re-construct it in Unpack call using ray information.
// It is not packed in FRayHitInfoPacked
float3 WorldPos; // 136 0 (derived)
uint Flags; // 148 0 5bits (packed with ShadingModelID)
float3 WorldTangent; // 152 6 48bits
float Anisotropy; // 164 2 16bits (packed with WorldTangent)
// 166 total
void SetMinimalPayloadMode() { Flags |= RAY_TRACING_PAYLOAD_FLAG_MINIMAL_PAYLOAD; }
bool IsMinimalPayloadMode() { return (Flags & RAY_TRACING_PAYLOAD_FLAG_MINIMAL_PAYLOAD) != 0; }
void SetFrontFace() { Flags |= RAY_TRACING_PAYLOAD_FLAG_FRONT_FACE; }
bool IsFrontFace() { return (Flags & RAY_TRACING_PAYLOAD_FLAG_FRONT_FACE) != 0; }
void SetEnableSkyLightContribution() { Flags |= RAY_TRACING_PAYLOAD_FLAG_ENABLE_SKY_LIGHT_CONTRIBUTION; }
bool IsEnableSkyLightContribution() { return (Flags & RAY_TRACING_PAYLOAD_FLAG_ENABLE_SKY_LIGHT_CONTRIBUTION) != 0; }
void SetIgnoreTranslucentMaterials() { Flags |= RAY_TRACING_PAYLOAD_FLAG_IGNORE_TRANSLUCENT; }
bool IsIgnoreTranslucentMaterials() { return (Flags & RAY_TRACING_PAYLOAD_FLAG_IGNORE_TRANSLUCENT) != 0; }
FRayCone GetRayCone() { return RayCone; }
void SetRayCone(FRayCone NewRayCone) { RayCone = NewRayCone; }
bool HasAnisotropy() { return abs(Anisotropy) >= 0.001f; }
};
struct FPackedMaterialClosestHitPayload : FMinimalPayload
{
// float FMinimalPayload::HitT // 4 bytes
uint PackedRayCone; // 4 bytes (fp16 width, fp16 spread)
float MipBias; // 4 bytes (can be packed into only 4 bits if necessary)
uint RadianceAndNormal[3]; // 12 bytes
uint BaseColorAndOpacity[2]; // 8 bytes
uint MetallicAndSpecularAndRoughness; // 4 bytes
uint IorAndShadingModelIDAndBlendingModeAndFlagsAndPrimitiveLightingChannelMask; // 4 bytes
uint PackedIndirectIrradiance[2]; // 8 bytes
uint PackedCustomData; // 4 bytes
uint WorldTangentAndAnisotropy[2]; // 8 bytes
uint PackedPixelCoord; // 4 bytes
// 64 bytes total
void SetPixelCoord(uint2 PixelCoord) { PackedPixelCoord = (PixelCoord.x & 0xFFFF) | (PixelCoord.y << 16); }
uint2 GetPixelCoord() { return uint2(PackedPixelCoord & 0xFFFF, PackedPixelCoord >> 16); }
void SetMinimalPayloadMode() { IorAndShadingModelIDAndBlendingModeAndFlagsAndPrimitiveLightingChannelMask |= RAY_TRACING_PAYLOAD_FLAG_MINIMAL_PAYLOAD << 24; }
bool IsMinimalPayloadMode() { return ((IorAndShadingModelIDAndBlendingModeAndFlagsAndPrimitiveLightingChannelMask >> 24) & RAY_TRACING_PAYLOAD_FLAG_MINIMAL_PAYLOAD) != 0; }
void SetEnableSkyLightContribution() { IorAndShadingModelIDAndBlendingModeAndFlagsAndPrimitiveLightingChannelMask |= RAY_TRACING_PAYLOAD_FLAG_ENABLE_SKY_LIGHT_CONTRIBUTION << 24; }
bool IsEnableSkyLightContribution() { return ((IorAndShadingModelIDAndBlendingModeAndFlagsAndPrimitiveLightingChannelMask >> 24) & RAY_TRACING_PAYLOAD_FLAG_ENABLE_SKY_LIGHT_CONTRIBUTION) != 0; }
void SetIgnoreTranslucentMaterials() { IorAndShadingModelIDAndBlendingModeAndFlagsAndPrimitiveLightingChannelMask |= RAY_TRACING_PAYLOAD_FLAG_IGNORE_TRANSLUCENT << 24; }
bool IsIgnoreTranslucentMaterials() { return ((IorAndShadingModelIDAndBlendingModeAndFlagsAndPrimitiveLightingChannelMask >> 24) & RAY_TRACING_PAYLOAD_FLAG_IGNORE_TRANSLUCENT) != 0; }
FRayCone GetRayCone() { return UnpackRayCone(PackedRayCone); }
void SetRayCone(FRayCone NewRayCone) { PackedRayCone = PackRayCone(NewRayCone); }
float GetMipBias() { return MipBias; }
void SetMipBias(float NewMipBias) { MipBias = NewMipBias; }
void SetRadiance(in float3 InRadiance)
{
RadianceAndNormal[0] = f32tof16(InRadiance.x) | (f32tof16(InRadiance.y) << 16);
RadianceAndNormal[1] &= 0xffff << 16; // Clear the radiance (low bits), keep packed normal component (high bits)
RadianceAndNormal[1] |= f32tof16(InRadiance.z);
}
float3 GetRadiance()
{
float3 Result;
Result.x = f16tof32(RadianceAndNormal[0]);
Result.y = f16tof32(RadianceAndNormal[0] >> 16);
Result.z = f16tof32(RadianceAndNormal[1]);
return Result;
}
void SetIndirectIrradiance(float3 InIndirectIrradiance)
{
PackedIndirectIrradiance[0] = f32tof16(InIndirectIrradiance.x);
PackedIndirectIrradiance[0] |= f32tof16(InIndirectIrradiance.y) << 16;
PackedIndirectIrradiance[1] = f32tof16(InIndirectIrradiance.z);
}
float3 GetIndirectIrradiance()
{
float3 Result;
Result.x = f16tof32(PackedIndirectIrradiance[0]);
Result.y = f16tof32(PackedIndirectIrradiance[0] >> 16);
Result.z = f16tof32(PackedIndirectIrradiance[1]);
return Result;
}
float3 GetWorldNormal()
{
float3 Result;
Result.x = f16tof32(RadianceAndNormal[1] >> 16);
Result.y = f16tof32(RadianceAndNormal[2]);
Result.z = f16tof32(RadianceAndNormal[2] >> 16);
return Result;
}
float4 GetCustomData()
{
float4 Result;
Result.x = PackedCustomData & 0xFF;
Result.y = (PackedCustomData >> 8) & 0xFF;
Result.z = (PackedCustomData >> 16) & 0xFF;
Result.w = (PackedCustomData >> 24) & 0xFF;
Result /= 255.0;
return Result;
}
float3 GetBaseColor()
{
float3 Result;
Result.x = f16tof32(BaseColorAndOpacity[0]);
Result.y = f16tof32(BaseColorAndOpacity[0] >> 16);
Result.z = f16tof32(BaseColorAndOpacity[1]);
return Result;
}
float3 GetWorldTangent()
{
float3 Result;
Result.x = f16tof32(WorldTangentAndAnisotropy[0]);
Result.y = f16tof32(WorldTangentAndAnisotropy[0] >> 16);
Result.z = f16tof32(WorldTangentAndAnisotropy[1]);
return Result;
}
float GetOpacity() { return f16tof32(BaseColorAndOpacity[1] >> 16); }
float GetMetallic() { return float(MetallicAndSpecularAndRoughness & 0xFF) / 255.0f; }
float GetSpecular() { return float((MetallicAndSpecularAndRoughness >> 8) & 0xFF) / 255.0f; }
float GetRoughness() { return f16tof32(MetallicAndSpecularAndRoughness >> 16); }
float GetIor() { return f16tof32(IorAndShadingModelIDAndBlendingModeAndFlagsAndPrimitiveLightingChannelMask); }
uint GetShadingModelID() { return (IorAndShadingModelIDAndBlendingModeAndFlagsAndPrimitiveLightingChannelMask >> 16) & 0xF; }
uint GetBlendingMode() { return (IorAndShadingModelIDAndBlendingModeAndFlagsAndPrimitiveLightingChannelMask >> 20) & 0xF; }
uint GetFlags() { return (IorAndShadingModelIDAndBlendingModeAndFlagsAndPrimitiveLightingChannelMask >> 24) & 0x1F; }
uint GetPrimitiveLightingChannelMask() { return (IorAndShadingModelIDAndBlendingModeAndFlagsAndPrimitiveLightingChannelMask >> 29) & 0x7; }
float GetAnisotropy() { return f16tof32(WorldTangentAndAnisotropy[1] >> 16); }
float3 GetDiffuseColor() { return GetBaseColor() - GetBaseColor() * GetMetallic(); }
float3 GetSpecularColor() { return ComputeF0(GetSpecular(), GetBaseColor(), GetMetallic()); }
};
FPackedMaterialClosestHitPayload PackRayTracingPayload(FMaterialClosestHitPayload Input, in FRayCone RayCone)
{
FPackedMaterialClosestHitPayload Output = (FPackedMaterialClosestHitPayload)0;
Output.HitT = Input.HitT;
Output.SetRayCone(RayCone);
Output.RadianceAndNormal[0] = f32tof16(Input.Radiance.x);
Output.RadianceAndNormal[0] |= f32tof16(Input.Radiance.y) << 16;
Output.RadianceAndNormal[1] = f32tof16(Input.Radiance.z);
Output.RadianceAndNormal[1] |= f32tof16(Input.WorldNormal.x) << 16;
Output.RadianceAndNormal[2] = f32tof16(Input.WorldNormal.y);
Output.RadianceAndNormal[2] |= f32tof16(Input.WorldNormal.z) << 16;
Output.BaseColorAndOpacity[0] = f32tof16(Input.BaseColor.x);
Output.BaseColorAndOpacity[0] |= f32tof16(Input.BaseColor.y) << 16;
Output.BaseColorAndOpacity[1] = f32tof16(Input.BaseColor.z);
Output.BaseColorAndOpacity[1] |= f32tof16(Input.Opacity) << 16;
Output.MetallicAndSpecularAndRoughness = (uint(round(Input.Metallic * 255.0f)) & 0xFF);
Output.MetallicAndSpecularAndRoughness |= (uint(round(Input.Specular * 255.0f)) & 0xFF) << 8;
Output.MetallicAndSpecularAndRoughness |= f32tof16(Input.Roughness) << 16;
Output.IorAndShadingModelIDAndBlendingModeAndFlagsAndPrimitiveLightingChannelMask = f32tof16(Input.Ior); // 16 bits
Output.IorAndShadingModelIDAndBlendingModeAndFlagsAndPrimitiveLightingChannelMask |= (Input.ShadingModelID & 0xF) << 16; // 4 bits
Output.IorAndShadingModelIDAndBlendingModeAndFlagsAndPrimitiveLightingChannelMask |= (Input.BlendingMode & 0xF) << 20; // 4 bits
Output.IorAndShadingModelIDAndBlendingModeAndFlagsAndPrimitiveLightingChannelMask |= (Input.Flags & 0x1F) << 24; // 5 bits
Output.IorAndShadingModelIDAndBlendingModeAndFlagsAndPrimitiveLightingChannelMask |= (Input.PrimitiveLightingChannelMask & 0x7) << 29; // 3 bits
Output.PackedIndirectIrradiance[0] = f32tof16(Input.IndirectIrradiance.x);
Output.PackedIndirectIrradiance[0] |= f32tof16(Input.IndirectIrradiance.y) << 16;
Output.PackedIndirectIrradiance[1] = f32tof16(Input.IndirectIrradiance.z);
int4 CustomData = round(Input.CustomData * 255);
Output.PackedCustomData = CustomData.x | (CustomData.y << 8) | (CustomData.z << 16) | (CustomData.w << 24);
Output.WorldTangentAndAnisotropy[0] = f32tof16(Input.WorldTangent.x);
Output.WorldTangentAndAnisotropy[0] |= f32tof16(Input.WorldTangent.y) << 16;
Output.WorldTangentAndAnisotropy[1] = f32tof16(Input.WorldTangent.z);
Output.WorldTangentAndAnisotropy[1] |= f32tof16(Input.Anisotropy) << 16;
return Output;
}
FMaterialClosestHitPayload UnpackRayTracingPayload(FPackedMaterialClosestHitPayload Input, RayDesc Ray)
{
FMaterialClosestHitPayload Output = (FMaterialClosestHitPayload)0;
Output.HitT = Input.HitT;
Output.RayCone = Input.GetRayCone();
Output.Radiance = Input.GetRadiance();
Output.WorldNormal = Input.GetWorldNormal();
Output.BaseColor = Input.GetBaseColor();
Output.Opacity = Input.GetOpacity();
Output.Metallic = Input.GetMetallic();
Output.Specular = Input.GetSpecular();
Output.Roughness = Input.GetRoughness();
Output.Ior = Input.GetIor();
Output.ShadingModelID = Input.GetShadingModelID();
Output.BlendingMode = Input.GetBlendingMode();
Output.PrimitiveLightingChannelMask = Input.GetPrimitiveLightingChannelMask();
Output.Flags = Input.GetFlags();
Output.IndirectIrradiance = Input.GetIndirectIrradiance();
Output.CustomData = Input.GetCustomData();
Output.WorldTangent = Input.GetWorldTangent();
Output.Anisotropy = Input.GetAnisotropy();
Output.DiffuseColor = Output.BaseColor - Output.BaseColor * Output.Metallic;
Output.SpecularColor = ComputeF0(Output.Specular, Output.BaseColor, Output.Metallic);
Output.WorldPos = Ray.Origin + Output.HitT * Ray.Direction;
return Output;
}