3
0

ReflectionProbeRenderCommon.azsli 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #pragma once
  9. #include <Atom/Features/PBR/LightingUtils.azsli>
  10. #include <Atom/Features/PBR/Microfacet/Fresnel.azsli>
  11. // compute final probe specular using the probe cubemap and the roughness, normals, and specularF0 for the surface
  12. bool ComputeProbeSpecular(float2 screenCoords, float3 positionWS, float4x4 obbTransformInverse, float3 outerObbHalfLengths, uint sampleIndex, out float3 specular)
  13. {
  14. // make sure the pixel belongs to this probe volume
  15. // this is necessary since it could have the correct stencil value but actually reside
  16. // in another volume that's in between the camera and the volume we're rendering
  17. if (!ObbContainsPoint(obbTransformInverse, outerObbHalfLengths, positionWS))
  18. {
  19. return false;
  20. }
  21. // retrieve normal from the encoded buffer written by the forward pass
  22. float4 encodedNormal = PassSrg::m_normal.Load(screenCoords, sampleIndex);
  23. float3 normal = DecodeNormalSignedOctahedron(encodedNormal.rgb);
  24. bool enableIBL = DecodeUnorm2BitFlag1(encodedNormal.a);
  25. if (!enableIBL)
  26. {
  27. return false;
  28. }
  29. bool multiScatterCompensationEnabled = DecodeUnorm2BitFlag2(encodedNormal.a);
  30. float3 dirToCamera = normalize(ViewSrg::m_worldPosition.xyz - positionWS);
  31. float NdotV = dot(normal, dirToCamera);
  32. NdotV = max(NdotV, 0.01f); // [GFX TODO][ATOM-4466] This is a current band-aid for specular noise at grazing angles.
  33. // retrieve specularF0 and roughness
  34. float4 specularF0Sample = PassSrg::m_specularF0.Load(screenCoords, sampleIndex);
  35. float3 specularF0 = specularF0Sample.rgb;
  36. float roughness = specularF0Sample.a;
  37. // sample BRDF map (using smoothness)
  38. float smoothness = 1.0f - roughness;
  39. float2 brdfUV = float2(saturate(NdotV), smoothness);
  40. float2 brdf = PassSrg::m_brdfMap.Sample(PassSrg::LinearSampler, brdfUV).rg;
  41. float3 reflectDir = reflect(-dirToCamera, normal);
  42. // compute parallax corrected reflection vector, if necessary
  43. float3 localReflectDir = reflectDir;
  44. if (ObjectSrg::m_useParallaxCorrection)
  45. {
  46. localReflectDir = ApplyParallaxCorrectionOBB(
  47. ObjectSrg::GetWorldMatrixInverse(),
  48. ObjectSrg::m_outerObbHalfLengths,
  49. positionWS,
  50. reflectDir);
  51. }
  52. // sample reflection cubemap with the appropriate roughness mip
  53. float3 probeSpecular = ObjectSrg::m_reflectionCubeMap.SampleLevel(SceneSrg::m_samplerEnv, GetCubemapCoords(localReflectDir), GetRoughnessMip(roughness)).rgb;
  54. // compute final specular amount
  55. float3 multiScatterCompensation = GetMultiScatterCompensation(specularF0, brdf, multiScatterCompensationEnabled);
  56. specular = probeSpecular * multiScatterCompensation * (specularF0.xyz * brdf.x + brdf.y);
  57. return true;
  58. }