PBR.glsl 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. #include "BRDF.glsl"
  2. #ifdef COMPILEPS
  3. #line 100
  4. vec3 GetSpecularDominantDir(vec3 normal, vec3 reflection, float roughness)
  5. {
  6. float smoothness = 1.0 - roughness;
  7. float lerpFactor = smoothness * (sqrt(smoothness) + roughness);
  8. return mix(normal, reflection, lerpFactor);
  9. }
  10. vec3 SphereLight(vec3 worldPos, vec3 lightVec, vec3 normal, vec3 toCamera, float roughness, vec3 specColor, vec3 diffColor, out float ndl)
  11. {
  12. float specEnergy = 1.0f;
  13. float radius = cLightRad / 100;
  14. float rough2 = max(roughness, 0.08);
  15. rough2 *= rough2;
  16. float radius2 = radius * radius;
  17. float distToLightSqrd = dot(lightVec,lightVec);
  18. float invDistToLight = inversesqrt(distToLightSqrd);
  19. float sinAlphaSqr = clamp(radius2 / distToLightSqrd, 0.0, 1.0);
  20. float sinAlpha = sqrt(sinAlphaSqr);
  21. ndl = dot(normal, (lightVec * invDistToLight));
  22. if(ndl < sinAlpha)
  23. {
  24. ndl = max(ndl, -sinAlpha);
  25. ndl = ((sinAlpha + ndl) * (sinAlpha + ndl)) / (4 * sinAlpha);
  26. }
  27. float sphereAngle = clamp(radius * invDistToLight, 0.0, 1.0);
  28. specEnergy = rough2 / (rough2 + 0.5f * sphereAngle);
  29. specEnergy *= specEnergy;
  30. vec3 R = 2 * dot(toCamera, normal) * normal - toCamera;
  31. R = GetSpecularDominantDir(normal, R, roughness);
  32. // Find closest point on sphere to ray
  33. vec3 closestPointOnRay = dot(lightVec, R) * R;
  34. vec3 centerToRay = closestPointOnRay - lightVec;
  35. float invDistToRay = inversesqrt(dot(centerToRay, centerToRay));
  36. vec3 closestPointOnSphere = lightVec + centerToRay * clamp(radius * invDistToRay, 0.0, 1.0);
  37. lightVec = closestPointOnSphere;
  38. vec3 L = normalize(lightVec);
  39. vec3 h = normalize(toCamera + L);
  40. float hdn = clamp(dot(h, normal), 0.0, 1.0);
  41. float hdv = dot(h, toCamera);
  42. float ndv = clamp(dot(normal, toCamera),0.0, 1.0);
  43. float hdl = clamp(dot(h, lightVec), 0.0, 1.0);
  44. vec3 diffuseFactor = Diffuse(diffColor, roughness, ndv, ndl, hdv) * ndl;
  45. vec3 fresnelTerm = Fresnel(specColor, hdv, hdl) ;
  46. float distTerm = Distribution(hdn, roughness);
  47. float visTerm = Visibility(ndl, ndv, roughness);
  48. vec3 specularFactor = distTerm * visTerm * fresnelTerm * ndl/ M_PI;
  49. return diffuseFactor + specularFactor;
  50. }
  51. vec3 TubeLight(vec3 worldPos, vec3 lightVec, vec3 normal, vec3 toCamera, float roughness, vec3 specColor, vec3 diffColor, out float ndl)
  52. {
  53. float radius = cLightRad / 100;
  54. float len = cLightLength / 10;
  55. vec3 pos = (cLightPosPS.xyz - worldPos);
  56. vec3 reflectVec = reflect(-toCamera, normal);
  57. vec3 L01 = cLightDirPS * len;
  58. vec3 L0 = pos - 0.5 * L01;
  59. vec3 L1 = pos + 0.5 * L01;
  60. vec3 ld = L1 - L0;
  61. float distL0 = length( L0 );
  62. float distL1 = length( L1 );
  63. float NoL0 = dot( L0, normal ) / ( 2.0 * distL0 );
  64. float NoL1 = dot( L1, normal ) / ( 2.0 * distL1 );
  65. ndl = ( 2.0 * clamp( NoL0 + NoL1, 0.0, 1.0 ) )
  66. / ( distL0 * distL1 + dot( L0, L1 ) + 2.0 );
  67. float a = len * len;
  68. float b = dot( reflectVec, L01 );
  69. float t = clamp( dot( L0, b * reflectVec - L01 ) / (a - b*b), 0.0, 1.0 );
  70. vec3 closestPoint = L0 + ld * clamp(t, 0.0, 1.0);
  71. vec3 centreToRay = dot( closestPoint, reflectVec ) * reflectVec - closestPoint;
  72. closestPoint = closestPoint + centreToRay * clamp(radius / length(centreToRay), 0.0, 1.0);
  73. vec3 l = normalize(closestPoint);
  74. vec3 h = normalize(toCamera + l);
  75. ndl = clamp(dot(normal, lightVec), 0.0, 1.0);
  76. float hdn = clamp(dot(h, normal), 0.0, 1.0);
  77. float hdv = dot(h, toCamera);
  78. float ndv = clamp(dot(normal, toCamera), 0.0, 1.0);
  79. float hdl = clamp(dot(h, lightVec), 0.0, 1.0);
  80. float distL = length(closestPoint);
  81. float alpha = max(roughness, 0.08) * max(roughness, 0.08);
  82. float alphaPrime = clamp(radius / (distL * 2.0) + alpha, 0.0, 1.0);
  83. vec3 diffuseFactor = Diffuse(diffColor, roughness, ndv, ndl, hdv) * ndl;
  84. vec3 fresnelTerm = Fresnel(specColor, hdv, hdl) ;
  85. float distTerm = Distribution(hdn, roughness);
  86. float visTerm = Visibility(ndl, ndv, roughness);
  87. vec3 specularFactor = distTerm * visTerm * fresnelTerm * ndl/ M_PI;
  88. return diffuseFactor + specularFactor;
  89. }
  90. //Return the PBR BRDF value
  91. // lightDir = the vector to the light
  92. // lightVev = normalised lightDir
  93. // toCamera = vector to the camera
  94. // normal = surface normal of the pixel
  95. // roughness = roughness of the pixel
  96. // diffColor = the rgb color of the pixel
  97. // specColor = the rgb specular color of the pixel
  98. vec3 GetBRDF(vec3 worldPos, vec3 lightDir, vec3 lightVec, vec3 toCamera, vec3 normal, float roughness, vec3 diffColor, vec3 specColor)
  99. {
  100. vec3 Hn = normalize(toCamera + lightDir);
  101. float vdh = clamp(dot(toCamera, Hn), M_EPSILON, 1.0);
  102. float ndh = clamp(dot(normal, Hn), M_EPSILON, 1.0);
  103. float ndl = clamp(dot(normal, lightVec), M_EPSILON, 1.0);
  104. float ldh = clamp(dot(lightVec, Hn), M_EPSILON, 1.0);
  105. float ndv = abs(dot(normal, toCamera)) + 1e-5;
  106. vec3 diffuseFactor = Diffuse(diffColor, roughness, ndv, ndl, vdh);
  107. vec3 specularFactor = vec3(0.0, 0.0, 0.0);
  108. #ifdef SPECULAR
  109. if(cLightRad > 0.0)
  110. {
  111. if(cLightLength > 0.0)
  112. {
  113. specularFactor = TubeLight(worldPos, lightVec, normal, toCamera, roughness, specColor, diffColor, ndl);
  114. specularFactor *= ndl;
  115. }
  116. else
  117. {
  118. specularFactor = SphereLight(worldPos, lightVec, normal, toCamera, roughness, specColor, diffColor, ndl);
  119. specularFactor *= ndl;
  120. }
  121. }
  122. else
  123. {
  124. vec3 fresnelTerm = Fresnel(specColor, vdh, ldh) ;
  125. float distTerm = Distribution(ndh, roughness);
  126. float visTerm = Visibility(ndl, ndv, roughness);
  127. specularFactor = fresnelTerm * distTerm * visTerm / M_PI;
  128. return diffuseFactor + specularFactor;
  129. }
  130. #endif
  131. return diffuseFactor + specularFactor;
  132. }
  133. #endif