RayTracing Material AO not populated in Substrate blendable or disabled modes.

In RayTracingHitShaders.usf, on the GetMaterialPayload() function, MaterialAO is only correctly populated when taking the adaptive Substrate path, but missing on the Substrate disabled or blendable GBuffer path.

I fixed this issue locally like this:

/**
 * Set material attributes for full materials
 **/
Payload.TranslatedWorldPos = DFFastToTranslatedWorld(MaterialParameters.AbsoluteWorldPosition, ResolvedView.PreViewTranslation);
Payload.WorldNormal = WorldNormal;
Payload.Radiance = EmissiveColor;
Payload.BaseColor = BaseColor;
Payload.Specular = Specular;
Payload.Roughness = Roughness;
Payload.Metallic = Metallic;
Payload.GBufferAO = GetMaterialAmbientOcclusion(PixelMaterialInputs);

Notice the last line, which is what I added.

Ernesto.

[Attachment Removed]

Steps to Reproduce
With Substrate disabled or set to blendable GBuffer format (SUBSTRATE_GBUFFER_FORMAT == 0), add an AO output to a Material and notice that Payload.GBufferAO is not populated (zero).

[Attachment Removed]

Hi,

Let’s assume, we set it as you suggested, the issue is that GBufferAO is never actually stored. FMaterialClosestHitPayload is packed into a FPackedMaterialClosestHitPayload struct, which does not have space for storing GBufferAO. So despite being set, it the value will be invalid if you plan to use it as hit payload after a ray query.

/Charles.

[Attachment Removed]

Indeed, good solution. I forgot we had some spare space there. Great that solved your issue!

/Charles.

[Attachment Removed]

Thank you for the explanation Charles. I ended up packing it in the top 8 bits of FlagsAndMipBias, which is currently unused.

void SetMaterialAO(float InMaterialAO)
{
	FlagsAndMipBias = (FlagsAndMipBias & 0x00FFFFFF) | ((uint(round(saturate(InMaterialAO) * 255.0f)) & 0xFF) << 24);
}
float GetMaterialAO()
{
	return float((FlagsAndMipBias >> 24) & 0xFF) / 255.0f;
}

We’ll see how the quantization looks like. Might not be something you want to adopt, but we’re currently using GetGBufferDataFromPayload(), which assumes the value is populated.

Thanks again,

Ernesto.

[Attachment Removed]