light-frag-params.glsl.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /**
  2. * Copyright (c) 2017-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. *
  6. * adapted from three.js (https://github.com/mrdoob/three.js/)
  7. * which under the MIT License, Copyright © 2010-2019 three.js authors
  8. */
  9. export default `
  10. uniform float uLightIntensity;
  11. uniform float uAmbientIntensity;
  12. uniform float uReflectivity;
  13. uniform float uMetalness;
  14. uniform float uRoughness;
  15. struct PhysicalMaterial {
  16. vec3 diffuseColor;
  17. float specularRoughness;
  18. vec3 specularColor;
  19. };
  20. struct IncidentLight {
  21. vec3 color;
  22. vec3 direction;
  23. };
  24. struct ReflectedLight {
  25. vec3 directDiffuse;
  26. vec3 directSpecular;
  27. vec3 indirectDiffuse;
  28. };
  29. struct GeometricContext {
  30. vec3 position;
  31. vec3 normal;
  32. vec3 viewDir;
  33. };
  34. vec3 F_Schlick(const in vec3 specularColor, const in float dotLH) {
  35. // Original approximation by Christophe Schlick '94
  36. // float fresnel = pow( 1.0 - dotLH, 5.0 );
  37. // Optimized variant (presented by Epic at SIGGRAPH '13)
  38. // https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf
  39. float fresnel = exp2((-5.55473 * dotLH - 6.98316) * dotLH);
  40. return (1.0 - specularColor) * fresnel + specularColor;
  41. }
  42. // Moving Frostbite to Physically Based Rendering 3.0 - page 12, listing 2
  43. // https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
  44. float G_GGX_SmithCorrelated(const in float alpha, const in float dotNL, const in float dotNV) {
  45. float a2 = pow2(alpha);
  46. // dotNL and dotNV are explicitly swapped. This is not a mistake.
  47. float gv = dotNL * sqrt(a2 + (1.0 - a2) * pow2(dotNV));
  48. float gl = dotNV * sqrt(a2 + (1.0 - a2) * pow2(dotNL));
  49. return 0.5 / max(gv + gl, EPSILON);
  50. }
  51. // Microfacet Models for Refraction through Rough Surfaces - equation (33)
  52. // http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html
  53. // alpha is "roughness squared" in Disney’s reparameterization
  54. float D_GGX(const in float alpha, const in float dotNH) {
  55. float a2 = pow2(alpha);
  56. float denom = pow2(dotNH) * (a2 - 1.0) + 1.0; // avoid alpha = 0 with dotNH = 1
  57. return RECIPROCAL_PI * a2 / pow2(denom);
  58. }
  59. vec3 BRDF_Diffuse_Lambert(const in vec3 diffuseColor) {
  60. return RECIPROCAL_PI * diffuseColor;
  61. }
  62. // GGX Distribution, Schlick Fresnel, GGX-Smith Visibility
  63. vec3 BRDF_Specular_GGX(const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness) {
  64. float alpha = pow2(roughness); // UE4's roughness
  65. vec3 halfDir = normalize(incidentLight.direction + geometry.viewDir);
  66. float dotNL = saturate(dot(geometry.normal, incidentLight.direction));
  67. float dotNV = saturate(dot(geometry.normal, geometry.viewDir));
  68. float dotNH = saturate(dot(geometry.normal, halfDir));
  69. float dotLH = saturate(dot(incidentLight.direction, halfDir));
  70. vec3 F = F_Schlick(specularColor, dotLH);
  71. float G = G_GGX_SmithCorrelated(alpha, dotNL, dotNV);
  72. float D = D_GGX(alpha, dotNH);
  73. return F * (G * D);
  74. }
  75. // ref: https://www.unrealengine.com/blog/physically-based-shading-on-mobile - environmentBRDF for GGX on mobile
  76. vec3 BRDF_Specular_GGX_Environment(const in GeometricContext geometry, const in vec3 specularColor, const in float roughness) {
  77. float dotNV = saturate(dot(geometry.normal, geometry.viewDir));
  78. const vec4 c0 = vec4(-1, -0.0275, -0.572, 0.022);
  79. const vec4 c1 = vec4(1, 0.0425, 1.04, -0.04);
  80. vec4 r = roughness * c0 + c1;
  81. float a004 = min(r.x * r.x, exp2(-9.28 * dotNV)) * r.x + r.y;
  82. vec2 AB = vec2(-1.04, 1.04) * a004 + r.zw;
  83. return specularColor * AB.x + AB.y;
  84. }
  85. void RE_Direct_Physical(const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {
  86. float dotNL = saturate(dot(geometry.normal, directLight.direction));
  87. vec3 irradiance = dotNL * directLight.color;
  88. irradiance *= PI; // punctual light
  89. reflectedLight.directSpecular += irradiance * BRDF_Specular_GGX(directLight, geometry, material.specularColor, material.specularRoughness);
  90. reflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert(material.diffuseColor);
  91. }
  92. void RE_IndirectDiffuse_Physical(const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {
  93. reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert(material.diffuseColor);
  94. }
  95. `