IBL.hlsl 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. #ifdef COMPILEPS
  2. float GetMipFromRoughness(float roughness)
  3. {
  4. return (roughness * 12.0 - pow(roughness, 6.0) * 1.5);
  5. }
  6. float3 EnvBRDFApprox (float3 specColor, float roughness, float ndv)
  7. {
  8. const float4 c0 = float4(-1, -0.0275, -0.572, 0.022 );
  9. const float4 c1 = float4(1, 0.0425, 1.0, -0.04 );
  10. float4 r = roughness * c0 + c1;
  11. float a004 = min( r.x * r.x, exp2( -9.28 * ndv ) ) * r.x + r.y;
  12. float2 AB = float2( -1.04, 1.04 ) * a004 + r.zw;
  13. return specColor * AB.x + AB.y;
  14. }
  15. float3 FixCubeLookup(float3 v)
  16. {
  17. float M = max(max(abs(v.x), abs(v.y)), abs(v.z));
  18. float scale = (1024 - 1) / 1024;
  19. if (abs(v.x) != M) v.x += scale;
  20. if (abs(v.y) != M) v.y += scale;
  21. if (abs(v.z) != M) v.z += scale;
  22. return v;
  23. }
  24. /// Calculate IBL contributation
  25. /// reflectVec: reflection vector for cube sampling
  26. /// wsNormal: surface normal in word space
  27. /// toCamera: normalized direction from surface point to camera
  28. /// roughness: surface roughness
  29. /// ambientOcclusion: ambient occlusion
  30. float3 ImageBasedLighting(in float3 reflectVec, in float3 wsNormal, in float3 toCamera, in float3 diffColor, in float3 specColor, in float roughness, inout float3 reflectionCubeColor)
  31. {
  32. roughness = max(roughness, 0.08);
  33. reflectVec = GetSpecularDominantDir(wsNormal, reflectVec, roughness);
  34. const float ndv = saturate(dot(-toCamera, wsNormal));
  35. /// Test: Parallax correction, currently not working
  36. // float3 intersectMax = (cZoneMax - toCamera) / reflectVec;
  37. // float3 intersectMin = (cZoneMin - toCamera) / reflectVec;
  38. // float3 furthestPlane = max(intersectMax, intersectMin);
  39. // float planeDistance = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z);
  40. // // Get the intersection position
  41. // float3 intersectionPos = toCamera + reflectVec * planeDistance;
  42. // // Get corrected reflection
  43. // reflectVec = intersectionPos - ((cZoneMin + cZoneMax )/ 2);
  44. const float mipSelect = GetMipFromRoughness(roughness);
  45. float3 cube = SampleCubeLOD(ZoneCubeMap, float4(FixCubeLookup(reflectVec), mipSelect)).rgb;
  46. float3 cubeD = SampleCubeLOD(ZoneCubeMap, float4(FixCubeLookup(wsNormal), 9.0)).rgb;
  47. // Fake the HDR texture
  48. float brightness = clamp(cAmbientColor.a, 0.0, 1.0);
  49. float darknessCutoff = clamp((cAmbientColor.a - 1.0) * 0.1, 0.0, 0.25);
  50. const float hdrMaxBrightness = 5.0;
  51. float3 hdrCube = pow(cube + darknessCutoff, max(1.0, cAmbientColor.a));
  52. hdrCube += max(0.0, hdrCube - 1.0) * hdrMaxBrightness;
  53. float3 hdrCubeD = pow(cubeD + darknessCutoff, max(1.0, cAmbientColor.a));
  54. hdrCubeD += max(0.0, hdrCubeD - 1.0) * hdrMaxBrightness;
  55. const float3 environmentSpecular = EnvBRDFApprox(specColor, roughness, ndv);
  56. const float3 environmentDiffuse = EnvBRDFApprox(diffColor, 1.0, ndv);
  57. return (hdrCube * environmentSpecular + hdrCubeD * environmentDiffuse) * brightness;
  58. }
  59. #endif