BRDF.hlsl 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #ifdef COMPILEPS
  2. #ifdef PBR
  3. // Following BRDF methods are based upon research Frostbite EA
  4. //[Lagrade et al. 2014, "Moving Frostbite to Physically Based Rendering"]
  5. //Schlick Fresnel
  6. //specular = the rgb specular color value of the pixel
  7. //VdotH = the dot product of the camera view direction and the half vector
  8. float3 SchlickFresnel(float3 specular, float VdotH)
  9. {
  10. return specular + (float3(1.0, 1.0, 1.0) - specular) * pow(1.0 - VdotH, 5.0);
  11. }
  12. //Schlick Gaussian Fresnel
  13. //specular = the rgb specular color value of the pixel
  14. //VdotH = the dot product of the camera view direction and the half vector
  15. float3 SchlickGaussianFresnel(in float3 specular, in float VdotH)
  16. {
  17. float sphericalGaussian = pow(2.0, (-5.55473 * VdotH - 6.98316) * VdotH);
  18. return specular + (float3(1.0, 1.0, 1.0) - specular) * sphericalGaussian;
  19. }
  20. //Get Fresnel
  21. //specular = the rgb specular color value of the pixel
  22. //VdotH = the dot product of the camera view direction and the half vector
  23. float3 Fresnel(float3 specular, float VdotH)
  24. {
  25. return SchlickFresnel(specular, VdotH);
  26. }
  27. // Smith GGX corrected Visibility
  28. // NdotL = the dot product of the normal and direction to the light
  29. // NdotV = the dot product of the normal and the camera view direction
  30. // roughness = the roughness of the pixel
  31. float SmithGGXSchlickVisibility(float NdotL, float NdotV, float roughness)
  32. {
  33. float rough2 = roughness * roughness;
  34. float lambdaV = NdotL * sqrt((-NdotV * rough2 + NdotV) * NdotV + rough2);
  35. float lambdaL = NdotV * sqrt((-NdotL * rough2 + NdotL) * NdotL + rough2);
  36. return 0.5 / (lambdaV + lambdaL);
  37. }
  38. // Get Visibility
  39. // NdotL = the dot product of the normal and direction to the light
  40. // NdotV = the dot product of the normal and the camera view direction
  41. // roughness = the roughness of the pixel
  42. float Visibility(float NdotL, float NdotV, float roughness)
  43. {
  44. return SmithGGXSchlickVisibility(NdotL, NdotV, roughness);
  45. }
  46. // GGX Distribution
  47. // NdotH = the dot product of the normal and the half vector
  48. // roughness = the roughness of the pixel
  49. float GGXDistribution(float NdotH, float roughness)
  50. {
  51. float rough2 = roughness * roughness;
  52. float tmp = (NdotH * rough2 - NdotH) * NdotH + 1;
  53. return rough2 / (tmp * tmp);
  54. }
  55. // Blinn Distribution
  56. // NdotH = the dot product of the normal and the half vector
  57. // roughness = the roughness of the pixel
  58. float BlinnPhongDistribution(in float NdotH, in float roughness)
  59. {
  60. const float specPower = max((2.0 / (roughness * roughness)) - 2.0, 1e-4f); // Calculate specular power from roughness
  61. return pow(saturate(NdotH), specPower);
  62. }
  63. // Beckmann Distribution
  64. // NdotH = the dot product of the normal and the half vector
  65. // roughness = the roughness of the pixel
  66. float BeckmannDistribution(in float NdotH, in float roughness)
  67. {
  68. const float rough2 = roughness * roughness;
  69. const float roughnessA = 1.0 / (4.0 * rough2 * pow(NdotH, 4.0));
  70. const float roughnessB = NdotH * NdotH - 1.0;
  71. const float roughnessC = rough2 * NdotH * NdotH;
  72. return roughnessA * exp(roughnessB / roughnessC);
  73. }
  74. // Get Distribution
  75. // NdotH = the dot product of the normal and the half vector
  76. // roughness = the roughness of the pixel
  77. float Distribution(float NdotH, float roughness)
  78. {
  79. return GGXDistribution(NdotH, roughness);
  80. }
  81. // Lambertian Diffuse
  82. // diffuseColor = the rgb color value of the pixel
  83. // roughness = the roughness of the pixel
  84. // NdotV = the normal dot with the camera view direction
  85. // NdotL = the normal dot with the light direction
  86. // VdotH = the camera view direction dot with the half vector
  87. float3 LambertianDiffuse(float3 diffuseColor, float NdotL)
  88. {
  89. return diffuseColor * NdotL;
  90. }
  91. // Burley Diffuse
  92. // diffuseColor = the rgb color value of the pixel
  93. // roughness = the roughness of the pixel
  94. // NdotV = the normal dot with the camera view direction
  95. // NdotL = the normal dot with the light direction
  96. // VdotH = the camera view direction dot with the half vector
  97. float3 BurleyDiffuse(float3 diffuseColor, float roughness, float NdotV, float NdotL, float VdotH)
  98. {
  99. const float energyBias = lerp(0, 0.5, roughness);
  100. const float energyFactor = lerp(1.0, 1.0 / 1.51, roughness);
  101. const float fd90 = energyBias + 2.0 * VdotH * VdotH * roughness;
  102. const float f0 = 1.0;
  103. const float lightScatter = f0 + (fd90 - f0) * pow(1.0f - NdotL, 5.0f);
  104. const float viewScatter = f0 + (fd90 - f0) * pow(1.0f - NdotV, 5.0f);
  105. return diffuseColor * lightScatter * viewScatter * energyFactor;
  106. }
  107. //Get Diffuse
  108. // diffuseColor = the rgb color value of the pixel
  109. // roughness = the roughness of the pixel
  110. // NdotV = the normal dot with the camera view direction
  111. // NdotL = the normal dot with the light direction
  112. // VdotH = the camera view direction dot with the half vector
  113. float3 Diffuse(float3 diffuseColor, float roughness, float NdotV, float NdotL, float VdotH)
  114. {
  115. //return LambertianDiffuse(diffuseColor, NdotL);
  116. return BurleyDiffuse(diffuseColor, roughness, NdotV, NdotL, VdotH);
  117. }
  118. #endif
  119. #endif