TraceRay 笔记

 官网地址:

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值