bumpFragmentFunctions.fx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. #ifdef BUMP
  2. varying vec2 vBumpUV;
  3. uniform vec3 vBumpInfos;
  4. uniform sampler2D bumpSampler;
  5. #if defined(TANGENT) && defined(NORMAL)
  6. varying mat3 vTBN;
  7. #endif
  8. // Thanks to http://www.thetenthplanet.de/archives/1180
  9. mat3 cotangent_frame(vec3 normal, vec3 p, vec2 uv)
  10. {
  11. // get edge vectors of the pixel triangle
  12. vec3 dp1 = dFdx(p);
  13. vec3 dp2 = dFdy(p);
  14. vec2 duv1 = dFdx(uv);
  15. vec2 duv2 = dFdy(uv);
  16. // solve the linear system
  17. vec3 dp2perp = cross(dp2, normal);
  18. vec3 dp1perp = cross(normal, dp1);
  19. vec3 tangent = dp2perp * duv1.x + dp1perp * duv2.x;
  20. vec3 binormal = dp2perp * duv1.y + dp1perp * duv2.y;
  21. // construct a scale-invariant frame
  22. float invmax = inversesqrt(max(dot(tangent, tangent), dot(binormal, binormal)));
  23. return mat3(tangent * invmax, binormal * invmax, normal);
  24. }
  25. vec3 perturbNormal(vec3 viewDir, mat3 cotangentFrame, vec2 uv)
  26. {
  27. vec3 map = texture2D(bumpSampler, uv).xyz;
  28. #ifdef INVERTNORMALMAPX
  29. map.x = 1.0 - map.x;
  30. #endif
  31. #ifdef INVERTNORMALMAPY
  32. map.y = 1.0 - map.y;
  33. #endif
  34. map = map * 255. / 127. - 128. / 127.;
  35. return normalize(cotangentFrame * map);
  36. }
  37. #ifdef PARALLAX
  38. const float minSamples = 4.;
  39. const float maxSamples = 15.;
  40. const int iMaxSamples = 15;
  41. // http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/a-closer-look-at-parallax-occlusion-mapping-r3262
  42. vec2 parallaxOcclusion(vec3 vViewDirCoT, vec3 vNormalCoT, vec2 texCoord, float parallaxScale) {
  43. float parallaxLimit = length(vViewDirCoT.xy) / vViewDirCoT.z;
  44. parallaxLimit *= parallaxScale;
  45. vec2 vOffsetDir = normalize(vViewDirCoT.xy);
  46. vec2 vMaxOffset = vOffsetDir * parallaxLimit;
  47. float numSamples = maxSamples + (dot(vViewDirCoT, vNormalCoT) * (minSamples - maxSamples));
  48. float stepSize = 1.0 / numSamples;
  49. // Initialize the starting view ray height and the texture offsets.
  50. float currRayHeight = 1.0;
  51. vec2 vCurrOffset = vec2(0, 0);
  52. vec2 vLastOffset = vec2(0, 0);
  53. float lastSampledHeight = 1.0;
  54. float currSampledHeight = 1.0;
  55. for (int i = 0; i < iMaxSamples; i++)
  56. {
  57. currSampledHeight = texture2D(bumpSampler, vBumpUV + vCurrOffset).w;
  58. // Test if the view ray has intersected the surface.
  59. if (currSampledHeight > currRayHeight)
  60. {
  61. float delta1 = currSampledHeight - currRayHeight;
  62. float delta2 = (currRayHeight + stepSize) - lastSampledHeight;
  63. float ratio = delta1 / (delta1 + delta2);
  64. vCurrOffset = (ratio)* vLastOffset + (1.0 - ratio) * vCurrOffset;
  65. // Force the exit of the loop
  66. break;
  67. }
  68. else
  69. {
  70. currRayHeight -= stepSize;
  71. vLastOffset = vCurrOffset;
  72. vCurrOffset += stepSize * vMaxOffset;
  73. lastSampledHeight = currSampledHeight;
  74. }
  75. }
  76. return vCurrOffset;
  77. }
  78. vec2 parallaxOffset(vec3 viewDir, float heightScale)
  79. {
  80. // calculate amount of offset for Parallax Mapping With Offset Limiting
  81. float height = texture2D(bumpSampler, vBumpUV).w;
  82. vec2 texCoordOffset = heightScale * viewDir.xy * height;
  83. return -texCoordOffset;
  84. }
  85. #endif
  86. #endif