cube_uv_reflection_fragment.glsl 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. #define DISABLE_CUBE_UV_MIPMAP_INTERPOLATION
  2. #ifdef ENVMAP_TYPE_CUBE_UV
  3. #define CUBE_UV_TEXTURE_SIZE 1024
  4. int getFaceFromDirection(vec3 direction) {
  5. vec3 absDirection = abs(direction);
  6. int face = -1;
  7. if( absDirection.x > absDirection.z ) {
  8. if(absDirection.x > absDirection.y )
  9. face = direction.x > 0.0 ? 0 : 3;
  10. else
  11. face = direction.y > 0.0 ? 1 : 4;
  12. }
  13. else {
  14. if(absDirection.z > absDirection.y )
  15. face = direction.z > 0.0 ? 2 : 5;
  16. else
  17. face = direction.y > 0.0 ? 1 : 4;
  18. }
  19. return face;
  20. }
  21. const float cubeUV_maxLods1 = log2(float(CUBE_UV_TEXTURE_SIZE)*0.25) - 1.0;
  22. const float cubeUV_rangeClamp = exp2((6.0 - 1.0) * 2.0);
  23. vec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {
  24. float scale = exp2(cubeUV_maxLods1 - roughnessLevel);
  25. float dxRoughness = dFdx(roughness);
  26. float dyRoughness = dFdy(roughness);
  27. vec3 dx = dFdx( vec * scale * dxRoughness );
  28. vec3 dy = dFdy( vec * scale * dyRoughness );
  29. float d = max( dot( dx, dx ), dot( dy, dy ) );
  30. // Clamp the value to the max mip level counts. hard coded to 6 mips
  31. d = clamp(d, 1.0, cubeUV_rangeClamp);
  32. float mipLevel = 0.5 * log2(d);
  33. return vec2(floor(mipLevel), fract(mipLevel));
  34. }
  35. const float cubeUV_maxLods2 = log2(float(CUBE_UV_TEXTURE_SIZE)*0.25) - 2.0;
  36. const float cubeUV_rcpTextureSize = 1.0 / float(CUBE_UV_TEXTURE_SIZE);
  37. vec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {
  38. mipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;
  39. float a = 16.0 * cubeUV_rcpTextureSize;
  40. vec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );
  41. vec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;
  42. // float powScale = exp2(roughnessLevel + mipLevel);
  43. float powScale = exp2_packed.x * exp2_packed.y;
  44. // float scale = 1.0 / exp2(roughnessLevel + 2.0 + mipLevel);
  45. float scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;
  46. // float mipOffset = 0.75*(1.0 - 1.0/exp2(mipLevel))/exp2(roughnessLevel);
  47. float mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;
  48. bool bRes = mipLevel == 0.0;
  49. scale = bRes && (scale < a) ? a : scale;
  50. vec3 r;
  51. vec2 offset;
  52. int face = getFaceFromDirection(direction);
  53. float rcpPowScale = 1.0 / powScale;
  54. if( face == 0) {
  55. r = vec3(direction.x, -direction.z, direction.y);
  56. offset = vec2(0.0+mipOffset,0.75 * rcpPowScale);
  57. offset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;
  58. }
  59. else if( face == 1) {
  60. r = vec3(direction.y, direction.x, direction.z);
  61. offset = vec2(scale+mipOffset, 0.75 * rcpPowScale);
  62. offset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;
  63. }
  64. else if( face == 2) {
  65. r = vec3(direction.z, direction.x, direction.y);
  66. offset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);
  67. offset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;
  68. }
  69. else if( face == 3) {
  70. r = vec3(direction.x, direction.z, direction.y);
  71. offset = vec2(0.0+mipOffset,0.5 * rcpPowScale);
  72. offset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;
  73. }
  74. else if( face == 4) {
  75. r = vec3(direction.y, direction.x, -direction.z);
  76. offset = vec2(scale+mipOffset, 0.5 * rcpPowScale);
  77. offset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;
  78. }
  79. else {
  80. r = vec3(direction.z, -direction.x, direction.y);
  81. offset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);
  82. offset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;
  83. }
  84. r = normalize(r);
  85. float texelOffset = 0.5 * cubeUV_rcpTextureSize;
  86. float s1 = (r.y/abs(r.x) + 1.0)*0.5;
  87. float s2 = (r.z/abs(r.x) + 1.0)*0.5;
  88. vec2 uv = offset + vec2(s1, s2) * scale;
  89. float min_x = offset.x + texelOffset;
  90. float max_x = offset.x + scale - texelOffset;
  91. float min_y = offset.y + texelOffset;
  92. float max_y = offset.y + scale - texelOffset;
  93. float delx = max_x - min_x;
  94. float dely = max_y - min_y;
  95. uv.x = min_x + s1*delx;
  96. uv.y = min_y + s2*dely;
  97. return uv;
  98. }
  99. const float cubeUV_maxLods3 = log2(float(CUBE_UV_TEXTURE_SIZE)*0.25) - 3.0;
  100. vec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {
  101. float roughnessVal = roughness* cubeUV_maxLods3;
  102. float r1 = floor(roughnessVal);
  103. float r2 = r1 + 1.0;
  104. float t = fract(roughnessVal);
  105. vec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);
  106. float s = mipInfo.y;
  107. float level0 = mipInfo.x;
  108. float level1 = level0 + 1.0;
  109. level1 = level1 > 5.0 ? 5.0 : level1;
  110. #if defined( DISABLE_CUBE_UV_MIPMAP_INTERPOLATION )
  111. // round to nearest mipmap if we are not interpolating.
  112. level0 += min( floor( s + 0.5 ), 5.0 );
  113. #endif
  114. // Tri linear interpolation.
  115. vec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);
  116. vec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));
  117. vec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);
  118. vec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));
  119. vec4 result = mix(color10, color20, t);
  120. #if ! defined( DISABLE_CUBE_UV_MIPMAP_INTERPOLATION )
  121. vec2 uv_11 = getCubeUV(reflectedDirection, r1, level1);
  122. vec4 color11 = envMapTexelToLinear(texture2D(envMap, uv_11));
  123. vec2 uv_21 = getCubeUV(reflectedDirection, r2, level1);
  124. vec4 color21 = envMapTexelToLinear(texture2D(envMap, uv_21));
  125. vec4 c2 = mix(color11, color21, t);
  126. result = mix(result, c2, s);
  127. #endif
  128. return vec4(result.rgb, 1.0);
  129. }
  130. #endif